2012-04-04 7 views
21

Tengo una serie de veces con la temperatura y la radiación en pandas dataframe. La resolución de tiempo es de 1 minuto en pasos regulares.¿Cómo volver a muestrear un marco de datos con diferentes funciones aplicadas a cada columna?

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 abajo muestra esta dataframe a una resolución de una hora, el cálculo de la hora significa para la temperatura y la hora suma para la radiación?

Respuesta

41

Con pandas 0.18 la API de remuestreo ha cambiado (vea docs). Así que para los 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 

Antiguo Respuesta:

estoy respondiendo a mi pregunta para reflejar los cambios relacionados con la serie de tiempo en pandas >= 0.8 (todas las otras respuestas son obsoletas).

Uso de 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 
+2

Esto se puede extender a una lista de funciones por columna: 'frame.resample ('1H', how = {'radiation': [np.sum, np.min], 'tamb': np.mean})'.El DataFrame resultante tiene un MultiIndex en sus columnas, con el nombre original de la columna como nivel 0 y el nombre de la función como nivel 1. –

+1

Para agregar a mi comentario anterior: en lugar de una lista de funciones por columna, también puede usar un diccionario, donde la clave es el nombre de la nueva columna y el valor es la función a usar: 'frame.resample ('1H', how = {'radiation': {'sum_rad': np.sum, 'min_rad': np.min} , 'tamb': np.mean}) ' –

+0

indique si desea agregar una nueva columna al resultado, como count() de cada fila en el período de remuestreo. – codingknob

0

Es necesario utilizar 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'}) 

con el ser de 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 que parte en el valor de la hora y luego calculando la media de tamb y la suma de radiation y devuelve el DataFrame (enfoque similar a R's ddply). Para obtener más información, verificaría la página de documentación para groupby, así como también la publicación de blog this.

Editar: Para hacer esta escala un poco mejor que podría agrupar tanto en el día y la hora como tal:

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 
3

También puede disminuir la resolución usando el método de pandas.DateRange objectsasof.

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 
+0

+1 para el uso de 'DateRange.asof' – diliop

3

para tentar a usted, en pandas 0.8.0 (en fuerte desarrollo en la rama timeseries en GitHub), podrás 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 derecha estrategia con la versión de producción actual de pandas.

+0

Gracias, pero lo que yo quiero tener sería algo así como' frame.convert ('1h', cómo = {'radiación': 'suma,' tamb ':' significa '}) '. ¿Es esta una opción en 0.8? – bmu

+0

@ Wes McKinney esto debería ser 'remuestreo' en 0.8, ¿no es así? – bmu

+0

Si actualizara su respuesta, la aceptaría. de lo contrario, debería eliminarlo, creo, porque señalará a los usuarios en la dirección incorrecta. – bmu

Cuestiones relacionadas