使用当前行作为条件的Pandas累计和

2 投票
3 回答
1765 浏览
提问于 2025-04-18 13:19

我有一个比较大的数据集,大约有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)

撰写回答