【问题标题】:Pandas Dataframe - for each row, return count of other rows with overlapping datesPandas Dataframe - 对于每一行,返回具有重叠日期的其他行的计数
【发布时间】:2020-02-06 03:30:20
【问题描述】:

我有一个包含项目、开始日期和结束日期的数据框。对于每一行,我想返回项目开始时正在进行的其他项目的数量。使用df.apply() 时如何嵌套循环?我试过使用 for 循环,但我的数据框很大,而且花费的时间太长。

import datetime as dt

data = {'project' :['A', 'B', 'C'],
        'pr_start_date':[dt.datetime(2018, 9, 1), dt.datetime(2019, 4, 1), dt.datetime(2019, 6, 8)],
        'pr_end_date': [dt.datetime(2019, 6, 15), dt.datetime(2019, 12, 1), dt.datetime(2019, 8, 1)]}

df = pd.DataFrame(data)

def cons_overlap(start):
    overlaps = 0
    for i in df.index:
        other_start = df.loc[i, 'pr_start_date']
        other_end = df.loc[i, 'pr_end_date']
        if (start > other_start) & (start < other_end):
            overlaps += 1

    return overlaps

df['overlap'] = df.apply(lambda row: cons_overlap(row['pr_start_date']), axis=1)

这是我正在寻找的输出:

    pr  pr_start_date pr_end_date   overlap
0   A   2018-09-01    2019-06-15    0
1   B   2019-04-01    2019-12-01    1
2   C   2019-06-08    2019-08-01    2

【问题讨论】:

  • 你大概有多少项目?
  • @ALollz 大约 8000

标签: python pandas dataframe


【解决方案1】:

我建议你利用numpy broadcasting:

ends = df.pr_start_date.values < df.pr_end_date.values[:, None]
starts = df.pr_start_date.values > df.pr_start_date.values[:, None]
df['overlap'] = (ends & starts).sum(0)
print(df)

输出

  project pr_start_date pr_end_date  overlap
0       A    2018-09-01  2019-06-15        0
1       B    2019-04-01  2019-12-01        1
2       C    2019-06-08  2019-08-01        2

结束和开始都是 3x3 的矩阵,在满足条件时为真:

# ends   
[[ True  True  True]  
 [ True  True  True]
 [ True  True  True]]

# starts
[[False  True  True]
 [False False  True]
 [False False False]]

然后找到与逻辑 &amp; 的交集并跨列求和 (sum(0))。

【讨论】:

  • 这非常有效,而且非常有意义!谢谢!
【解决方案2】:

它应该比你的 for 循环更快

【讨论】:

    【解决方案3】:

    我假设这些行按开始日期排序,并检查以前开始但尚未完成的项目。 df.index.get_loc(r.name) 产生正在处理的行的索引。

    df["overlap"]=df.apply(lambda r: df.loc[:df.index.get_loc(r.name),"pr_end_date"].gt(r["pr_start_date"]).sum()-1, axis=1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 2021-12-22
      相关资源
      最近更新 更多