Calcular la climatología diaria utilizando pandas python.

Estoy tratando de usar pandas para calcular la climatología diaria. Mi código es:

import pandas as pd dates = pd.date_range('1950-01-01', '1953-12-31', freq='D') rand_data = [int(1000*random.random()) for i in xrange(len(dates))] cum_data = pd.Series(rand_data, index=dates) cum_data.to_csv('test.csv', sep="\t") 

cum_data es el dataframe que contiene las fechas diarias desde el 1 de enero de 1950 hasta el 31 de diciembre de 1953. Quiero crear un nuevo vector de longitud 365 con el primer elemento que contiene el promedio de rand_data para el 1 de enero de 1950, 1951, 1952 y 1953. Y así encendido para el segundo elemento …

¿Alguna sugerencia de cómo puedo hacer esto usando pandas?

Puede agruparse por día del año y calcular la media de estos grupos:

 cum_data.groupby(cum_data.index.dayofyear).mean() 

Sin embargo, tienes que ser consciente de los años bisiestos. Esto causará problemas con este enfoque. Como alternativa, también puedes agrupar por mes y día:

 In [13]: cum_data.groupby([cum_data.index.month, cum_data.index.day]).mean() Out[13]: 1 1 462.25 2 631.00 3 615.50 4 496.00 ... 12 28 378.25 29 427.75 30 528.50 31 678.50 Length: 366, dtype: float64 

@joris. Gracias. Tu respuesta fue justo lo que necesitaba para usar pandas para calcular las climatologías diarias, pero no llegaste al paso final. Re-mapeando el mes, índice de días a un índice del día del año para todos los años, incluidos los años bisiestos, es decir, de 1 a 366. Así que pensé en compartir mi solución para otros usuarios. 1950 a 1953 es de 4 años con un año bisiesto, 1952. Tenga en cuenta que, dado que se utilizan valores aleatorios, cada ejecución dará resultados diferentes.

 ... from datetime import date doy = [] doy_mean = [] doy_size = [] for name, group in cum_data.groupby([cum_data.index.month, cum_data.index.day]): (mo, dy) = name # Note: can use any leap year here. yrday = (date(1952, mo, dy)).timetuple().tm_yday doy.append(yrday) doy_mean.append(group.mean()) doy_size.append(group.count()) # Note: useful climatology stats are also available via group.describe() returned as dict #desc = group.describe() # desc["mean"], desc["min"], desc["max"], std,quartiles, etc. # we lose the counts here. new_cum_data = pd.Series(doy_mean, index=doy) print new_cum_data.ix[366] >> 634.5 pd_dict = {} pd_dict["mean"] = doy_mean pd_dict["size"] = doy_size cum_data_df = pd.DataFrame(data=pd_dict, index=doy) print cum_data_df.ix[366] >> mean 634.5 >> size 4.0 >> Name: 366, dtype: float64 # and just to check Feb 29 print cum_data_df.ix[60] >> mean 343 >> size 1 >> Name: 60, dtype: float64 

Con la esperanza de que pueda ser de alguna ayuda, quiero publicar mi solución para obtener una serie de climatología con el mismo índice y longitud de la serie de tiempo original.

Utilizo la solución de joris para obtener un “modelo de climatología” de 365/366 elementos, luego construyo la serie deseada tomando los valores de este modelo de climatología y el índice de tiempo de mi serie de tiempo original. De esta manera, las cosas como años bisiestos son automáticamente atendidas.

 #I start with my time series named 'serData'. #I apply joris' solution to it, getting a 'model climatology' of length 365 or 366. serClimModel = serData.groupby([serData.index.month, serData.index.day]).mean() #Now I build the climatology series, taking values from serClimModel depending on the index of serData. serClimatology = serClimModel[zip(serData.index.month, serData.index.day)] #Now serClimatology has a time index like this: [1,1] ... [12,31]. #So, as a final step, I take as time index the one of serData. serClimatology.index = serData.index