我的情况如下。我有一个A类事件系列(a_series
),由PersonID索引,另一个ID与问题无关:
PersonID AnotherID
19 768 2013-02-03 13:39:00
767 2013-02-03 14:03:00
766 2013-02-03 15:35:00
765 2013-02-03 22:32:00
764 2013-02-04 11:36:00
763 2013-02-04 12:07:00
26 762 2013-02-18 13:21:00
...
730 66901 2014-08-21 21:09:00
67078 2014-08-22 23:44:00
67141 2014-08-23 11:16:00
67168 2014-08-23 14:53:00
67216 2014-08-23 21:45:00
Name: Timestamp, Length: 34175, dtype: datetime64[ns]
我还有另一个系列(b_series
),构建完全相同,但描述了B类事件:
PersonID AnotherID
26 939 2013-02-18 06:01:00
940 2013-02-18 06:47:00
941 2013-02-19 07:02:00
...
728 65159 2014-08-14 18:40:00
729 66104 2014-08-18 09:08:00
66229 2014-08-18 17:31:00
Name: Timestamp, Length: 1886, dtype: datetime64[ns]
请注意,虽然结构相同,但索引不相同 - 意味着某个人可能拥有的事件A多于事件B,并且可能根本没有特定类型的事件。
我想创建一个具有相同a_series
结构的系列,但是对于每一行,计算在A事件发生前12小时发生的b_series中的事件数。例如,如果我们从26 762 2013-02-18 13:21:00
获取行series_a
,则其值应为2.
我设法通过申请这样做:
def apply_func(x, series_b):
try:
return series_b.loc[x['PersonID']].\
between(x['Timestamp'] - timedelta(hours = 12), x['Timestamp']).sum()
except KeyError:
return 0
new_series = series_a.apply(apply_func, axis = 1, args = (seriesb,))
new_series.index = series_a.index
但我不禁觉得必须有一种更有效率的“熊猫”方式。也许用groupby或者查找?
答案 0 :(得分:1)
根据框架的大小和匹配数量, 可以更有效地使用连接操作:
首先,提供系列名称并将其更改为数据框:
>>> a.name, b.name = 'a', 'b'
>>> xb = b.reset_index(level=-1).filter('b')
>>> xa = a.reset_index()
然后,加入'PersonID'
:
>>> df = xa.join(xb, on='PersonID', how='inner')
>>> df
PersonID AnotherID a b
6 26 762 2013-02-18 13:21:00 2013-02-18 06:01:00
6 26 762 2013-02-18 13:21:00 2013-02-18 06:47:00
6 26 762 2013-02-18 13:21:00 2013-02-19 07:02:00
现在,计算点击次数:
>>> lag = np.timedelta64(12, 'h')
>>> df['cnt'] = (df['b'] < df['a']) & (df['a'] < df['b'] + lag)
>>> ts = df.groupby(['PersonID', 'AnotherID', 'a'])['cnt'].sum()
>>> ts
PersonID AnotherID a
26 762 2013-02-18 13:21:00 2
Name: cnt, dtype: float64
并与原始系列对齐:
>>> xcol = ['PersonID', 'AnotherID', 'a']
>>> xa.join(ts, on=xcol).fillna(0).set_index(xcol[:-1])
a cnt
PersonID AnotherID
19 768 2013-02-03 13:39:00 0
767 2013-02-03 14:03:00 0
766 2013-02-03 15:35:00 0
765 2013-02-03 22:32:00 0
764 2013-02-04 11:36:00 0
763 2013-02-04 12:07:00 0
26 762 2013-02-18 13:21:00 2
730 66901 2014-08-21 21:09:00 0
67078 2014-08-22 23:44:00 0
67141 2014-08-23 11:16:00 0
67168 2014-08-23 14:53:00 0
67216 2014-08-23 21:45:00 0