python - scikit - ¿Cómo remuestrear un marco de datos con diferentes funciones aplicadas a cada columna?
sklearn time series prediction (4)
Tengo una serie de tiempos con temperatura y radiación en un dataframe
pandas. La resolución del tiempo es de 1 minuto en pasos regulares.
import datetime
import pandas as pd
import numpy as np
date_times = pd.date_range(datetime.datetime(2012, 4, 5, 8, 0),
datetime.datetime(2012, 4, 5, 12, 0),
freq=''1min'')
tamb = np.random.sample(date_times.size) * 10.0
radiation = np.random.sample(date_times.size) * 10.0
frame = pd.DataFrame(data={''tamb'': tamb, ''radiation'': radiation},
index=date_times)
frame
<class ''pandas.core.frame.DataFrame''>
DatetimeIndex: 241 entries, 2012-04-05 08:00:00 to 2012-04-05 12:00:00
Freq: T
Data columns:
radiation 241 non-null values
tamb 241 non-null values
dtypes: float64(2)
¿Cómo puedo muestrear este dataframe
de dataframe
a una resolución de una hora, calculando la media horaria de la temperatura y la suma horaria de la radiación?
Con pandas 0.18, la API de remuestreo cambió (consulte la docs ). Entonces para pandas> = 0.18 la respuesta es:
In [31]: frame.resample(''1H'').agg({''radiation'': np.sum, ''tamb'': np.mean})
Out[31]:
tamb radiation
2012-04-05 08:00:00 5.161235 279.507182
2012-04-05 09:00:00 4.968145 290.941073
2012-04-05 10:00:00 4.478531 317.678285
2012-04-05 11:00:00 4.706206 335.258633
2012-04-05 12:00:00 2.457873 8.655838
Respuesta anterior:
Estoy respondiendo mi pregunta para reflejar los cambios relacionados con las series de tiempo en pandas >= 0.8
(todas las demás respuestas están desactualizadas).
Usando pandas> = 0.8 la respuesta es:
In [30]: frame.resample(''1H'', how={''radiation'': np.sum, ''tamb'': np.mean})
Out[30]:
tamb radiation
2012-04-05 08:00:00 5.161235 279.507182
2012-04-05 09:00:00 4.968145 290.941073
2012-04-05 10:00:00 4.478531 317.678285
2012-04-05 11:00:00 4.706206 335.258633
2012-04-05 12:00:00 2.457873 8.655838
Necesitas usar groupby
como tal:
grouped = frame.groupby(lambda x: x.hour)
grouped.agg({''radiation'': np.sum, ''tamb'': np.mean})
# Same as: grouped.agg({''radiation'': ''sum'', ''tamb'': ''mean''})
siendo la salida:
radiation tamb
key_0
8 298.581107 4.883806
9 311.176148 4.983705
10 315.531527 5.343057
11 288.013876 6.022002
12 5.527616 8.507670
Así que, en esencia, estoy dividiendo el valor de la hora y luego calculando la media de tamb
y la suma de radiation
y devolviendo el DataFrame
(enfoque similar a la ddply
de R). Para más información, vería la página de documentación de groupby , así como this publicación del blog.
Edición: Para mejorar un poco esta escala, puede agrupar el día y la hora como tales:
grouped = frame.groupby(lambda x: (x.day, x.hour))
grouped.agg({''radiation'': ''sum'', ''tamb'': ''mean''})
radiation tamb
key_0
(5, 8) 298.581107 4.883806
(5, 9) 311.176148 4.983705
(5, 10) 315.531527 5.343057
(5, 11) 288.013876 6.022002
(5, 12) 5.527616 8.507670
Para atormentarlo, en pandas 0.8.0 (bajo un fuerte desarrollo en la rama de timeseries
en GitHub), podrá hacer:
In [5]: frame.convert(''1h'', how=''mean'')
Out[5]:
radiation tamb
2012-04-05 08:00:00 7.840989 8.446109
2012-04-05 09:00:00 4.898935 5.459221
2012-04-05 10:00:00 5.227741 4.660849
2012-04-05 11:00:00 4.689270 5.321398
2012-04-05 12:00:00 4.956994 5.093980
Los métodos mencionados anteriormente son la estrategia correcta con la versión de producción actual de pandas.
También puede asof
la asof
utilizando el método pandas.DateRange
objetos pandas.DateRange
.
In [21]: hourly = pd.DateRange(datetime.datetime(2012, 4, 5, 8, 0),
... datetime.datetime(2012, 4, 5, 12, 0),
... offset=pd.datetools.Hour())
In [22]: frame.groupby(hourly.asof).size()
Out[22]:
key_0
2012-04-05 08:00:00 60
2012-04-05 09:00:00 60
2012-04-05 10:00:00 60
2012-04-05 11:00:00 60
2012-04-05 12:00:00 1
In [23]: frame.groupby(hourly.asof).agg({''radiation'': np.sum, ''tamb'': np.mean})
Out[23]:
radiation tamb
key_0
2012-04-05 08:00:00 271.54 4.491
2012-04-05 09:00:00 266.18 5.253
2012-04-05 10:00:00 292.35 4.959
2012-04-05 11:00:00 283.00 5.489
2012-04-05 12:00:00 0.5414 9.532