python - tutorial - pandas dataframe index
Extrapolar los valores en Pandas DataFrame (2)
Es muy fácil interpolar las células NaN en un DataFrame de Pandas:
In [98]: df
Out[98]:
neg neu pos avg
250 0.508475 0.527027 0.641292 0.558931
500 NaN NaN NaN NaN
1000 0.650000 0.571429 0.653983 0.625137
2000 NaN NaN NaN NaN
3000 0.619718 0.663158 0.665468 0.649448
4000 NaN NaN NaN NaN
6000 NaN NaN NaN NaN
8000 NaN NaN NaN NaN
10000 NaN NaN NaN NaN
20000 NaN NaN NaN NaN
30000 NaN NaN NaN NaN
50000 NaN NaN NaN NaN
[12 rows x 4 columns]
In [99]: df.interpolate(method=''nearest'', axis=0)
Out[99]:
neg neu pos avg
250 0.508475 0.527027 0.641292 0.558931
500 0.508475 0.527027 0.641292 0.558931
1000 0.650000 0.571429 0.653983 0.625137
2000 0.650000 0.571429 0.653983 0.625137
3000 0.619718 0.663158 0.665468 0.649448
4000 NaN NaN NaN NaN
6000 NaN NaN NaN NaN
8000 NaN NaN NaN NaN
10000 NaN NaN NaN NaN
20000 NaN NaN NaN NaN
30000 NaN NaN NaN NaN
50000 NaN NaN NaN NaN
[12 rows x 4 columns]
También me gustaría que extrapole los valores NaN que están fuera del alcance de la interpolación, usando el método dado. ¿Cómo podría hacer esto?
import pandas as pd
try:
# for Python2
from cStringIO import StringIO
except ImportError:
# for Python3
from io import StringIO
df = pd.read_table(StringIO(''''''
neg neu pos avg
0 NaN NaN NaN NaN
250 0.508475 0.527027 0.641292 0.558931
999 NaN NaN NaN NaN
1000 0.650000 0.571429 0.653983 0.625137
2000 NaN NaN NaN NaN
3000 0.619718 0.663158 0.665468 0.649448
4000 NaN NaN NaN NaN
6000 NaN NaN NaN NaN
8000 NaN NaN NaN NaN
10000 NaN NaN NaN NaN
20000 NaN NaN NaN NaN
30000 NaN NaN NaN NaN
50000 NaN NaN NaN NaN''''''), sep=''/s+'')
print(df.interpolate(method=''nearest'', axis=0).ffill().bfill())
rendimientos
neg neu pos avg
0 0.508475 0.527027 0.641292 0.558931
250 0.508475 0.527027 0.641292 0.558931
999 0.650000 0.571429 0.653983 0.625137
1000 0.650000 0.571429 0.653983 0.625137
2000 0.650000 0.571429 0.653983 0.625137
3000 0.619718 0.663158 0.665468 0.649448
4000 0.619718 0.663158 0.665468 0.649448
6000 0.619718 0.663158 0.665468 0.649448
8000 0.619718 0.663158 0.665468 0.649448
10000 0.619718 0.663158 0.665468 0.649448
20000 0.619718 0.663158 0.665468 0.649448
30000 0.619718 0.663158 0.665468 0.649448
50000 0.619718 0.663158 0.665468 0.649448
Nota: Cambié tu df
un poco para mostrar cómo la interpolación con la nearest
es diferente de hacer un df.fillna
. (Vea la fila con el índice 999).
También agregué una fila de NaNs con índice 0 para mostrar que bfill()
también puede ser necesario.
Extrapolación de Pandas DataFrame
s
DataFrame
s puede ser extrapolado, sin embargo, no hay una llamada de método simple dentro de pandas y requiere otra biblioteca (ej. Scipy.optimize ).
Extrapolando
La extrapolación, en general, requiere que uno haga ciertas suposiciones sobre los datos que se extrapolan. Una forma es mediante la curva de ajustar una ecuación general parametrizada a los datos para encontrar los valores de los parámetros que mejor describen los datos existentes, que luego se utiliza para calcular los valores que se extienden más allá del rango de estos datos. El problema difícil y limitante de este enfoque es que debe hacerse alguna suposición sobre la tendencia cuando se selecciona la ecuación parametrizada. Esto se puede encontrar a través de prueba y error con diferentes ecuaciones para dar el resultado deseado o se puede inferir a veces del origen de los datos. Los datos proporcionados en la pregunta realmente no son lo suficientemente grandes de un conjunto de datos para obtener una curva bien ajustada; sin embargo, es lo suficientemente bueno para ilustrar.
El siguiente es un ejemplo de extrapolación del DataFrame
con un polinomio de 3er orden
f ( x ) = a x 3 + b x 2 + c x + d (Ec. 1)
Esta función genérica ( func()
) se ajusta a la curva en cada columna para obtener parámetros únicos específicos de la columna (es decir, a , b , c , d ). Entonces, estas ecuaciones parametrizadas se usan para extrapolar los datos en cada columna para todos los índices con NaN
.
import pandas as pd
from cStringIO import StringIO
from scipy.optimize import curve_fit
df = pd.read_table(StringIO(''''''
neg neu pos avg
0 NaN NaN NaN NaN
250 0.508475 0.527027 0.641292 0.558931
500 NaN NaN NaN NaN
1000 0.650000 0.571429 0.653983 0.625137
2000 NaN NaN NaN NaN
3000 0.619718 0.663158 0.665468 0.649448
4000 NaN NaN NaN NaN
6000 NaN NaN NaN NaN
8000 NaN NaN NaN NaN
10000 NaN NaN NaN NaN
20000 NaN NaN NaN NaN
30000 NaN NaN NaN NaN
50000 NaN NaN NaN NaN''''''), sep=''/s+'')
# Do the original interpolation
df.interpolate(method=''nearest'', xis=0, inplace=True)
# Display result
print ''Interpolated data:''
print df
print
# Function to curve fit to the data
def func(x, a, b, c, d):
return a * (x ** 3) + b * (x ** 2) + c * x + d
# Initial parameter guess, just to kick off the optimization
guess = (0.5, 0.5, 0.5, 0.5)
# Create copy of data to remove NaNs for curve fitting
fit_df = df.dropna()
# Place to store function parameters for each column
col_params = {}
# Curve fit each column
for col in fit_df.columns:
# Get x & y
x = fit_df.index.astype(float).values
y = fit_df[col].values
# Curve fit column and get curve parameters
params = curve_fit(func, x, y, guess)
# Store optimized parameters
col_params[col] = params[0]
# Extrapolate each column
for col in df.columns:
# Get the index values for NaNs in the column
x = df[pd.isnull(df[col])].index.astype(float).values
# Extrapolate those points with the fitted function
df[col][x] = func(x, *col_params[col])
# Display result
print ''Extrapolated data:''
print df
print
print ''Data was extrapolated with these column functions:''
for col in col_params:
print ''f_{}(x) = {:0.3e} x^3 + {:0.3e} x^2 + {:0.4f} x + {:0.4f}''.format(col, *col_params[col])
Extrapolando resultados
Interpolated data:
neg neu pos avg
0 NaN NaN NaN NaN
250 0.508475 0.527027 0.641292 0.558931
500 0.508475 0.527027 0.641292 0.558931
1000 0.650000 0.571429 0.653983 0.625137
2000 0.650000 0.571429 0.653983 0.625137
3000 0.619718 0.663158 0.665468 0.649448
4000 NaN NaN NaN NaN
6000 NaN NaN NaN NaN
8000 NaN NaN NaN NaN
10000 NaN NaN NaN NaN
20000 NaN NaN NaN NaN
30000 NaN NaN NaN NaN
50000 NaN NaN NaN NaN
Extrapolated data:
neg neu pos avg
0 0.411206 0.486983 0.631233 0.509807
250 0.508475 0.527027 0.641292 0.558931
500 0.508475 0.527027 0.641292 0.558931
1000 0.650000 0.571429 0.653983 0.625137
2000 0.650000 0.571429 0.653983 0.625137
3000 0.619718 0.663158 0.665468 0.649448
4000 0.621036 0.969232 0.708464 0.766245
6000 1.197762 2.799529 0.991552 1.662954
8000 3.281869 7.191776 1.702860 4.058855
10000 7.767992 15.272849 3.041316 8.694096
20000 97.540944 150.451269 26.103320 91.365599
30000 381.559069 546.881749 94.683310 341.042883
50000 1979.646859 2686.936912 467.861511 1711.489069
Data was extrapolated with these column functions:
f_neg(x) = 1.864e-11 x^3 + -1.471e-07 x^2 + 0.0003 x + 0.4112
f_neu(x) = 2.348e-11 x^3 + -1.023e-07 x^2 + 0.0002 x + 0.4870
f_avg(x) = 1.542e-11 x^3 + -9.016e-08 x^2 + 0.0002 x + 0.5098
f_pos(x) = 4.144e-12 x^3 + -2.107e-08 x^2 + 0.0000 x + 0.6312
Parcela para la columna avg
Sin un conjunto de datos más grande o sin conocer la fuente de los datos, este resultado puede ser completamente incorrecto, pero debe ejemplificar el proceso para extrapolar un DataFrame
. La ecuación supuesta en func()
probablemente necesitaría jugarse para obtener la extrapolación correcta. Además, no se hizo ningún intento de hacer que el código fuera eficiente.
Actualizar:
Si su índice no es numérico, como un DatetimeIndex
, consulte esta respuesta para saber cómo extrapolarlos.