根据较小的日期范围对大型pandas数据帧求和

时间:2016-12-24 14:57:31

标签: python pandas

我有一个大型的pandas数据框,其中包含与之关联的每小时数据。然后我想把它解析成"每月"将每小时数据相加的数据。但是,这些月份不一定是日历月,它们通常在一个月的中间开始,在下个月的中间结束。

我可以建立一个"月"这些日期范围中的每一个都落入并循环通过它,但我认为通过大熊猫有更好的方法来做到这一点。

这是我当前的代码,最后一行引发错误,是问题的症结所在:

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

但当然,我没有得到它。

2 个答案:

答案 0 :(得分:3)

pd.merge_asof仅适用于pandas 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
来自docs

  

对于左侧DataFrame中的每一行,我们选择右侧DataFrame中的最后一行,其中“on”键小于或等于左侧的键。两个DataFrame必须按键排序。

但这只会考虑start日期。

query
我在end处理了query日期,因为我现在在end

后的数据框中方便地pd.merge_asof

groupby
我相信这部分很明显。

答案 1 :(得分: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

然后,您可以将日期转回并创建新列