2016-12-24 57 views
1

我有一个大型熊猫数据框,每小时数据都与它关联。然后我想把它解释为每小时数据总结的“每月”数据。但是,月份不一定是日历月,通常在一个月的中间开始,在下个月的中间结束。基于较小日期范围的大熊猫数据帧总和

我可以建立这些日期范围中每个日期范围的“月份”列表并循环遍历它,但我认为有一个更好的方法可以通过熊猫来完成。

这里是我当前的代码,最后一行抛出一个错误,是问题的症结所在:

dates = pd.Series(pd.date_range('1/1/2015 00:00','3/31/2015 23:45',freq='1H')) 
nums = np.random.randint(0,100,dates.count()) 
df = pd.DataFrame({'date':dates, 'num':nums}) 

month = pd.DataFrame({'start':['1/4/2015 00:00','1/24/2015 00:00'], 'end':['1/23/2015 23:00','2/23/2015 23:00']}) 
month['start'] = pd.to_datetime(month['start']) 
month['end'] = pd.to_datetime(month['end']) 

month['num'] = df['num'][(df['date'] >= month['start']) & (df['date'] <= month['end'])].sum() 

我希望类似的输出:

 start     end num 
0 2015-01-04 2015-01-23 23:00:00 33,251 
1 2015-01-24 2015-02-23 23:00:00 39,652 

但当然,我我没有那样做。

+1

试着看一下pd.tseries.offsets.Month,看看是否有一个开始日期和重采样由。如果没有开始日期,请添加所需月份的某一天的timedelta。 –

回答

3

pd.merge_asof只随大熊猫0.19
组合pd.merge_asof + query + groupby

pd.merge_asof(df, month, left_on='date', right_on='start') \ 
    .query('date <= end').groupby(['start', 'end']).num.sum().reset_index() 

enter image description here


解释
pd.merge_asof
从文档

对于左数据帧的每一行中,我们选择了正确的数据帧“开”键,其小于或等于左边的关键的最后一排。这两个DataFrames必须按键排序。

但是这只考虑了start的日期。

query
我照顾end日期与query,因为我现在有方便在end我的数据帧后pd.merge_asof

groupby
我相信这部分obvious`

+0

我得到:''模块'对象没有属性'merge_asof'' – pshep123

+0

它的一个熊猫0.19功能。 – piRSquared

+0

如果您无法升级,我们将不得不寻找其他解决方案 – piRSquared

2

也许你可以转换为一段时间并添加若干天

# create data 
dates = pd.Series(pd.date_range('1/1/2015 00:00','3/31/2015 23:45',freq='1H')) 
nums = np.random.randint(0,100,dates.count()) 
df = pd.DataFrame({'date':dates, 'num':nums}) 

# offset days and then create period 
df['periods'] = (df.date + pd.tseries.offsets.Day(23)).dt.to_period('M')] 

# group and sum 
df.groupby('periods')['num'].sum() 

输出

periods 
2015-01 10051 
2015-02 34229 
2015-03 37311 
2015-04 26655 

然后,您可以将日期向后移位,使新列