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)