1. is_unique
Como su nombre indica, este método comprueba si todos los valores de una serie son únicos:
import pandas as pd print(pd.Series([1, 2, 3, 4]).is_unique) print(pd.Series([1, 2, 3, 1]).is_unique) Output: True False
2 & 3. is_monotonic y is_monotonic_decreasing
Con estos 2 métodos, podemos comprobar si los valores de una Serie están en orden ascendente/descendente:
print(pd.Series([1, 2, 3, 8]).is_monotonic) print(pd.Series([1, 2, 3, 1]).is_monotonic) print(pd.Series([9, 8, 4, 0]).is_monotonic_decreasing) Output: True False True
Ambos métodos funcionan también para una Serie con valores de cadena. En este caso, Python utiliza un ordenamiento lexicográfico bajo el capó, comparando dos cadenas posteriores carácter por carácter. No es lo mismo que un ordenamiento alfabético, y de hecho, el ejemplo con los datos numéricos de arriba es un caso particular de dicho ordenamiento. Como dice la documentación de Python
El ordenamiento lexicográfico para cadenas utiliza el número de punto de código Unicode para ordenar los caracteres individuales.
Leer También: 4 Funciones de Python Pandas Imprescindibles Para el Análisis de Series Temporales
En la práctica, significa principalmente que también se tienen en cuenta las mayúsculas y minúsculas y los símbolos especiales:
print(pd.Series(['fox', 'koala', 'panda']).is_monotonic) print(pd.Series(['FOX', 'Fox', 'fox']).is_monotonic) print(pd.Series(['*', '&', '_']).is_monotonic) Output: True True False
Una curiosa excepción ocurre cuando todos los valores de una Serie son iguales. En este caso, ambos métodos devuelven True:
print(pd.Series([1, 1, 1, 1, 1]).is_monotonic) print(pd.Series(['fish', 'fish']).is_monotonic_decreasing) Output: True True
4. hasnans
Este método comprueba si una Serie contiene valores NaN:
import numpy as np print(pd.Series([1, 2, 3, np.nan]).hasnans) print(pd.Series([1, 2, 3, 10, 20]).hasnans) Output: True False
5. empty
A veces, podemos querer saber si una Serie está completamente vacía, sin contener ni siquiera valores NaN:
print(pd.Series().empty) print(pd.Series(np.nan).empty) Output: True False
Una Serie puede quedar vacía después de algunas manipulaciones con ella, por ejemplo, el filtrado:
s = pd.Series([1, 2, 3]) s[s > 3].empty Output: True
6 & 7. first_valid_index() y last_valid_index()
Estos 2 métodos devuelven el índice del primer/último valor no NaN y son particularmente útiles para los objetos de la Serie con muchos NaNs:
print(pd.Series([np.nan, np.nan, 1, 2, 3, np.nan]).first_valid_index()) print(pd.Series([np.nan, np.nan, 1, 2, 3, np.nan]).last_valid_index()) Output: 2 4
Si todos los valores de una serie son NaN, ambos métodos devuelven None:
print(pd.Series([np.nan, np.nan, np.nan]).first_valid_index()) print(pd.Series([np.nan, np.nan, np.nan]).last_valid_index()) Output: None None
8. truncate()
Este método permite truncar una Serie antes y después de algún valor del índice. Vamos a truncar la Serie de la sección anterior dejando sólo los valores que no son NaN:
s = pd.Series([np.nan, np.nan, 1, 2, 3, np.nan]) s.truncate(before=2, after=4) Output: 2 1.0 3 2.0 4 3.0 dtype: float64
El índice original de la Serie se ha conservado. Podemos querer restablecerlo y también asignar la Serie truncada a una variable:
s_truncated = s.truncate(before=2, after=4).reset_index(drop=True) print(s_truncated) Output: 0 1.0 1 2.0 2 3.0 dtype: float64
9. convert_dtypes()
Como dice la documentación de pandas, este método se utiliza para
Convertir columnas a los mejores dtypes posibles usando dtypes que soportan pd.NA.
Si se consideran sólo los objetos Series y no los DataFrames, la única aplicación de este método es convertir todos los enteros anulables (es decir, los números float con una parte decimal igual a 0, como 1.0, 2.0, etc.) de nuevo en enteros "normales". Estos números flotantes aparecen cuando la serie original contiene tanto enteros como valores NaN. Dado que NaN es un float en numpy y pandas, hace que toda la Serie con cualquier valor que falte pase a ser también de tipo float.
Veamos el ejemplo de la sección anterior para ver cómo funciona:
print(pd.Series([np.nan, np.nan, 1, 2, 3, np.nan])) print('\n') print(pd.Series([np.nan, np.nan, 1, 2, 3, np.nan]).convert_dtypes()) Output: 0 NaN 1 NaN 2 1.0 3 2.0 4 3.0 5 NaN dtype: float64 0 <NA> 1 <NA> 2 1 3 2 4 3 5 <NA> dtype: Int64
10. clip()
We can clip all the values of a Series at input thresholds (lower and upper parameters):
s = pd.Series(range(1, 11)) print(s) s_clipped = s.clip(lower=2, upper=7) print(s_clipped) Output: 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 dtype: int64 0 2 1 2 2 3 3 4 4 5 5 6 6 7 7 7 8 7 9 7 dtype: int64
11. rename_axis()
En el caso de un objeto Serie, este método establece el nombre del índice:
s = pd.Series({'flour': '300 g', 'butter': '150 g', 'sugar': '100 g'}) print(s) s=s.rename_axis('ingredients') print(s) Output: flour 300 g butter 150 g sugar 100 g dtype: object ingredients flour 300 g butter 150 g sugar 100 g dtype: object
12 & 13. nsmallest() y nlargest()
Estos 2 métodos devuelven los elementos más pequeños/grandes de una Serie. Por defecto, devuelven 5 valores, en orden ascendente para nsmallest() y en descendente - para nlargest().
s = pd.Series([3, 2, 1, 100, 200, 300, 4, 5, 6]) s.nsmallest() Output: 2 1 1 2 0 3 6 4 7 5 dtype: int64
Es posible especificar otro número de los valores más pequeños/más grandes a devolver. Además, es posible que queramos restablecer el índice y asignar el resultado a una variable:
largest_3 = s.nlargest(3).reset_index(drop=True) print(largest_3) Output: 0 300 1 200 2 100 dtype: int64
14. pct_change()
Para un objeto Serie, podemos calcular el cambio porcentual (o, más precisamente, el cambio de fracción) entre el elemento actual y uno anterior. Este enfoque puede ser útil, por ejemplo, cuando se trabaja con series temporales, o para crear un gráfico de cascada en % o fracciones.
s = pd.Series([20, 33, 14, 97, 19]) s.pct_change() Output: 0 NaN 1 0.650000 2 -0.575758 3 5.928571 4 -0.804124 dtype: float64
Para que la serie resultante sea más legible, vamos a redondearla:
s.pct_change().round(2) Output: 0 NaN 1 0.65 2 -0.58 3 5.93 4 -0.80 dtype: float64
15. explode()
Este método transforma cada elemento tipo lista de una Serie (listas, tuplas, conjuntos, Series, ndarrays) en una fila. Los elementos tipo lista vacíos se transformarán en una fila con NaN. Para evitar índices repetidos en la Serie resultante, es mejor restablecer el índice:
s = pd.Series([[np.nan], {1, 2}, 3, (4, 5)]) print(s) s_exploded = s.explode().reset_index(drop=True) print(s_exploded) Output: 0 [nan] 1 {1, 2} 2 3 3 (4, 5) dtype: object 0 NaN 1 1 2 2 3 3 4 4 5 5 dtype: object
16. repeat()
Este método se utiliza para repetir consecutivamente cada elemento de una Serie un número definido de veces. También en este caso, tiene sentido restablecer el índice:
s = pd.Series([1, 2, 3]) print(s) s_repeated = s.repeat(2).reset_index(drop=True) print(s_repeated) Output: 0 1 1 2 2 3 dtype: int64 0 1 1 1 2 2 3 2 4 3 5 3 dtype: int64
Si el número de repeticiones se asigna a 0, se devolverá una Serie vacía:
s.repeat(0) Output: Series([], dtype: int64)
Conclusión
En resumen, hemos investigado 16 métodos de pandas poco utilizados para trabajar con Series y algunos de sus casos de aplicación. Si conoces otras formas interesantes de manipular Series en pandas, eres bienvenido a compartirlas en los comentarios.
¡Gracias por leer!
Leer También: Usando Python y Pandas Datareader Para Analizar Datos Financieros