Python 数据帧中行子集的联接和求和
我有一个熊猫数据框,它存储日期范围和一些相关列:Python 数据帧中行子集的联接和求和,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个熊猫数据框,它存储日期范围和一些相关列: date_start date_end ... lots of other columns ... 1 2016-07-01 2016-07-02 2 2016-07-01 2016-07-03 3 2016-07-01 2016-07-04 4 2016-07-02 2016-07-07 5 2016-07-05 2016-07-06 和另一个按日期索
date_start date_end ... lots of other columns ...
1 2016-07-01 2016-07-02
2 2016-07-01 2016-07-03
3 2016-07-01 2016-07-04
4 2016-07-02 2016-07-07
5 2016-07-05 2016-07-06
和另一个按日期索引的皮卡丘目击数据框:
pikachu_sightings
date
2016-07-01 2
2016-07-02 4
2016-07-03 6
2016-07-04 8
2016-07-05 10
2016-07-06 12
2016-07-07 14
对于第一个df中的每一行,我想计算该日期范围内的pikachu_目击总数(即,date_开始
到date_结束
),并将其存储在新列中。因此,最终会出现这样的df(为了清晰起见,请留下数字):
如果我以迭代方式执行此操作,我会迭代日期范围表中的每一行,在观测表中选择与日期范围匹配的行子集,并对其执行求和-但这对于我的数据集来说太慢了:
for range in ranges.itertuples():
sightings_in_range = sightings[(sightings.index >= range.date_start) & (sightings.index <= range.date_end)]
sum_sightings_in_range = sightings_in_range["pikachu_sightings"].sum()
ranges.set_value(range.Index, 'total_pikachu_sightings', sum_sightings_in_range)
用于范围中的范围。itertuples():
sightings_in_range=sightings[(sightings.index>=range.date_start)&(sightings.index首先确保pikachu_sightings
具有日期时间索引并已排序
p = pikachu_sightings.squeeze() # force into a series
p.index = pd.to_datetime(p.index)
p = p.sort_index()
然后确保您的date\u start
和date\u end
是datetime
df.date_start = pd.to_datetime(df.date_start)
df.date_end = pd.to_datetime(df.date_end)
那就简单了
df.apply(lambda x: p[x.date_start:x.date_end].sum(), axis=1)
0 6
1 12
2 20
3 54
4 22
dtype: int64
矢量化解决方案的草图:
从一个p
开始,就像皮尔斯菲尔德的回答一样
确保date.
cols具有datetime64
d类型,即:
df['date_start'] = pd.to_datetime(df.date_time)
然后计算累计金额:
psums = p.cumsum()
及
不过,它还没有结束。asof
返回最后一个良好的值,因此它有时会采用确切的开始日期,有时则不会(取决于您的数据)。因此,您必须对此进行调整。(如果日期频率为day
,则可能会将p
的索引向后移动一小时,例如-pd.Timedelta(1,'h'))
,然后添加p.asof(df.start_date)
可能会起作用。谢谢,这是一个优雅的解决方案,而且很有效!最后一行的代码仍然使用熊猫吗?我问,因为对于一个大数据集(50000个日期范围和6000行pikachu_观测,30秒-并且想要处理一个更大的数据集!)@马特:是熊猫,不是矢量化的。
df['date_start'] = pd.to_datetime(df.date_time)
psums = p.cumsum()
result = psums.asof(df.date_end) - psums.asof(df.date_start)