使用当前行作为条件的Pandas累计和
我有一个比较大的数据集,大约有200万条记录,每条记录都有一个开始时间和结束时间。我想在每条记录中插入一个字段,用来计算在这个表中有多少条记录满足以下条件:
- 开始时间小于或等于“这一行”的开始时间
- 并且结束时间大于“这一行”的开始时间
简单来说,每条记录最后都会有一个数字,表示有多少个事件(包括它自己)在同一时间是“活跃”的。
我一直在尝试自学pandas来实现这个功能,但我甚至不知道从哪里开始。我能找到很多关于如何对满足特定条件的行进行求和的例子,比如“> 2”,但我就是搞不清楚如何遍历每一行,根据当前行的值来有条件地对某一列进行求和。
3 个回答
0
def counter (s: pd.Series):
return ((df["start"]<= s["start"]) & (df["end"] >= s["start"])).sum()
df["count"] = df.apply(counter , axis = 1)
这听起来是个简单很多的方法,就是用apply这个函数。虽然apply的速度没有Python自带的函数,比如cumsum()或者cum快,但它的速度应该比用for循环要快。
1
开始吧。这会很慢。
请注意,这里每一行都被算作和自己重叠,所以结果列的值永远不会是0。(如果想反过来算,就从结果中减去1。)
import pandas as pd
df = pd.DataFrame({'start_time': [4,3,1,2],'end_time': [7,5,3,8]})
df = df[['start_time','end_time']] #just changing the order of the columns for aesthetics
def overlaps_with_row(row,frame):
starts_before_mask = frame.start_time <= row.start_time
ends_after_mask = frame.end_time > row.start_time
return (starts_before_mask & ends_after_mask).sum()
df['number_which_overlap'] = df.apply(overlaps_with_row,frame=df,axis=1)
结果是:
In [8]: df
Out[8]:
start_time end_time number_which_overlap
0 4 7 3
1 3 5 2
2 1 3 1
3 2 8 2
[4 rows x 3 columns]
1
你可以试试下面的代码来得到最终的结果。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.array([[2,10],[5,8],[3,8],[6,9]]),columns=["start","end"])
active_events= {}
for i in df.index:
active_events[i] = len(df[(df["start"]<=df.loc[i,"start"]) & (df["end"]> df.loc[i,"start"])])
last_columns = pd.DataFrame({'No. active events' : pd.Series(active_events)})
df.join(last_columns)