Los valores faltantes son comunes y ocurren debido a un error humano, un error del instrumento, el procesamiento de otro equipo o simplemente por la falta de datos para una determinada observación.
En este Byte, veremos cómo llenar NaNs en un
DataFrame
, si elige manejar NaN rellenándolos.
En primer lugar, vamos a crear un simulacro DataFrame
con algunos valores aleatorios descartados:
import numpy as np
array = np.random.randn(25, 3)
mask = np.random.choice([1, 0], array.shape, p=[.3, .7]).astype(bool)
array[mask] = np.nan
df = pd.DataFrame(array, columns=['Col1', 'Col2', 'Col3'])
Col1 Col2 Col3
0 -0.671603 -0.792415 0.783922
1 0.207720 NaN 0.996131
2 -0.892115 -1.282333 NaN
3 -0.315598 -2.371529 -1.959646
4 NaN NaN -0.584636
5 0.314736 -0.692732 -0.303951
6 0.355121 NaN NaN
7 NaN -1.900148 1.230828
8 -1.795468 0.490953 NaN
9 -0.678491 -0.087815 NaN
10 0.755714 0.550589 -0.702019
11 0.951908 -0.529933 0.344544
12 NaN 0.075340 -0.187669
13 NaN 0.314342 -0.936066
14 NaN 1.293355 0.098964
Grafiquemos, digamos, la tercera columna:
plt.plot(df['Col3'])
Cuando se llena con varias técnicas, este gráfico lleno de NaN se puede reemplazar con:
fillna() – Media, Mediana, Moda
Puede completar estos valores en una nueva columna y asignarla a la columna que desea completar, o en el lugar usando el inplace
argumento. Aquí, extraeremos los valores completos en una nueva columna para facilitar la inspección:
mean = df['Col3'].fillna(df['Col3'].mean(), inplace=False)
median = df['Col3'].fillna(df['Col3'].median(), inplace=False)
mode = df['Col3'].fillna(df['Col3'].mode(), inplace=False)
La mediana, la media y la moda de la columna son -0.187669
, -0.110873
y 0.000000
y estos valores se utilizarán para cada NaN respectivamente. Esto se está llenando efectivamente con valores constantes, donde el valor que se ingresa depende de la entrada de la columna.
Primero, llenar con valores medianos da como resultado:
Con valores medios:
Con valores de modo:
fillna() – Valor constante
También puede rellenar con un valor constante en su lugar:
Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!
constant = df['Col3'].fillna(0, inplace=False
Esto da como resultado que se coloque un valor constante (0) en lugar de cada NaN. 0
está cerca de nuestra mediana y media e igual a la moda, por lo que los valores completos se parecerán mucho a ese método para nuestro conjunto de datos simulado:
0 0.783922
1 0.996131
2 0.000000
3 -1.959646
4 -0.584636
5 -0.303951
6 0.000000
7 1.230828
8 0.000000
9 0.000000
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
fillna() – Relleno hacia adelante y hacia atrás
En cada fila, puede hacer un relleno hacia adelante o hacia atrás, tomando el valor de la fila anterior o posterior:
ffill = df['Col3'].fillna(method='ffill')
bfill = df['Col3'].fillna(method='bfill')
Con el relleno hacia adelante, dado que nos falta la fila 2, el valor de la fila 1 se toma para llenar la segunda. Los valores se propagan hacia adelante:
0 0.783922
1 0.996131
2 0.996131
3 -1.959646
4 -0.584636
5 -0.303951
6 -0.303951
7 1.230828
8 1.230828
9 1.230828
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
Con el llenado hacia atrás, sucede lo contrario. La fila 2 se llena con el valor de la fila 3:
0 0.783922
1 0.996131
2 -1.959646
3 -1.959646
4 -0.584636
5 -0.303951
6 1.230828
7 1.230828
8 -0.702019
9 -0.702019
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
Aunque, si hay más de uno NaN
en una secuencia: estos no funcionarán bien y pueden generar una cascada de NaN más abajo, sesgando los datos y eliminando los valores realmente registrados.
interpolar()
La interpolate()
delega la interpolación de valores a SciPy's conjunto de métodos para interpolar valores. Acepta una amplia variedad de argumentos, incluyendo, nearest
, zero
, slinear
, quadratic
, cubic
, spline
, barycentric
, polynomial
, krogh
, piecewise_polynomial
, spline
, pchip
, akima
, cubicspline
, etc.
La interpolación es mucho más flexible e "inteligente" que simplemente llenar valores con constantes o medias variables como los métodos anteriores.
La interpolación puede completar correctamente una secuencia de una manera que ningún otro método puede hacerlo, como por ejemplo:
s = pd.Series([0, 1, np.nan, np.nan, np.nan, 5])
s.fillna(s.mean()).values
s.fillna(method='ffill').values
s.interpolate().values
La interpolación por defecto es lineal, y suponiendo que 1...5
es probable que un 1, 2, 3, 4, 5
La secuencia no es descabellada (pero no está garantizada). Tanto el llenado constante como el llenado hacia adelante o hacia atrás fallan miserablemente aquí. En términos generales, la interpolación suele ser un buen amigo cuando se trata de llenar NaN con señales ruidosas o conjuntos de datos corruptos.
Experimentar con tipos de interpolación puede producir mejores resultados.
Aquí hay dos métodos de interpolación (splice
y polynomial
requiere un order
argumento):
nearest = df['Col3'].interpolate(method='nearest')
polynomial = df['Col3'].interpolate(method='polynomial', order=3)
Estos dan como resultado:
Y: