【问题标题】:Calculate duration between events with pandas用熊猫计算事件之间的持续时间
【发布时间】:2019-01-16 22:58:45
【问题描述】:

我有一个数据框

df = pd.DataFrame([['2018-07-02', 'B'],
 ['2018-07-03', 'A'],
 ['2018-07-06', 'B'],
 ['2018-07-08', 'B'],
 ['2018-07-09', 'A'],
 ['2018-07-09', 'A'],
 ['2018-07-10', 'A'],
 ['2018-07-12', 'B'],
 ['2018-07-15', 'A'],
 ['2018-07-16', 'A'],
 ['2018-07-18', 'B'],
 ['2018-07-22', 'A'],
 ['2018-07-25', 'B'],
 ['2018-07-25', 'B'],
 ['2018-07-27', 'A'],
 ['2018-07-28', 'A']], columns = ['DateEvent','Event'])

其中计数从事件 A 开始,到事件 B 结束。有些事件可能在一天以上开始并在一天以上结束。

我已经算过差值了:

df = df.set_index('DateEvent')
begin = df.loc[df['Event'] == 'A'].index
cutoffs = df.loc[df['Event'] == 'B'].index

idx = cutoffs.searchsorted(begin)
mask = idx < len(cutoffs)
idx = idx[mask]
begin = begin[mask]
end = cutoffs[idx]

pd.DataFrame({'begin':begin, 'end':end})

但我也得到了多个开始和结束的区别:

begin         end
0  2018-07-03  2018-07-06
1  2018-07-09  2018-07-12
2  2018-07-09  2018-07-12
3  2018-07-10  2018-07-12
4  2018-07-15  2018-07-18
5  2018-07-16  2018-07-18
6  2018-07-22  2018-07-25

所需的输出包括事件 A 的第一次出现和事件 B 的最后一次出现...寻找最大持续时间,只是为了确定。

我可以在删除不必要的事件之前或之后循环,但有没有更好、更 Pythonic 的方式?

谢谢,

阿莱什

编辑:

我已经成功地将代码用作 groupby 中的函数。但它并不干净,而且确实需要一些时间。如何重写代码以将组包含在 df 中?

df = pd.DataFrame([['2.07.2018', 1, 'B'],
['3.07.2018', 1, 'A'],
['3.07.2018', 2, 'A'],
['6.07.2018', 2, 'B'],
['8.07.2018', 2, 'B'],
['9.07.2018', 2, 'A'],
['9.07.2018', 2, 'A'],
['9.07.2018', 2, 'B'],
['9.07.2018', 3, 'A'],
['10.07.2018', 3, 'A'],
['10.07.2018', 3, 'B'],
['12.07.2018', 3, 'B'],
['15.07.2018', 3, 'A'],
['16.07.2018', 4, 'A'],
['16.07.2018', 4, 'B'],
['18.07.2018', 4, 'B'],
['18.07.2018', 4, 'A'],
['22.07.2018', 5, 'A'],
['25.07.2018', 5, 'B'],
['25.07.2018', 7, 'B'],
['25.07.2018', 7, 'A'],
['25.07.2018', 7, 'B'],
['27.07.2018', 9, 'A'],
['28.07.2018', 9, 'A'],
['28.07.2018', 9, 'B']], columns = ['DateEvent','Group','Event'])

我正在尝试以某种方式对一组进行 cumsum 组合,但无法获得预期的结果。

谢谢!

【问题讨论】:

  • 你在寻找第一个 A 和第一个 B 之间的区别是什么?您对这些数据的预期输出是什么?
  • 啊,是的...所需的输出是事件 A 的第一次出现和事件 B 的最后一次出现。我将相应地更新问题。谢谢!
  • @ScottBoston,如果你有时间,我再次需要你的帮助。我已经用另一列升级了我原来的问题。谢谢!!!

标签: python pandas diff


【解决方案1】:

让我们试试吧:

df = pd.DataFrame([['2018-07-02', 'B'],
 ['2018-07-03', 'A'],
 ['2018-07-06', 'B'],
 ['2018-07-08', 'B'],
 ['2018-07-09', 'A'],
 ['2018-07-09', 'A'],
 ['2018-07-10', 'A'],
 ['2018-07-12', 'B'],
 ['2018-07-15', 'A'],
 ['2018-07-16', 'A'],
 ['2018-07-18', 'B'],
 ['2018-07-22', 'A'],
 ['2018-07-25', 'B'],
 ['2018-07-25', 'B'],
 ['2018-07-27', 'A'],
 ['2018-07-28', 'A']], columns = ['DateEvent','Event'])

a = (df['Event'] != 'A').cumsum()
a = a.groupby(a).cumcount()
df['Event Group'] = (a == 1).cumsum()

df_out = df.groupby('Event Group').filter(lambda x: set(x['Event']) == set(['A','B']))\
           .groupby('Event Group')['DateEvent'].agg(['first','last'])\
           .rename(columns={'first':'start','last':'end'})\
           .reset_index()

print(df_out)

输出:

   Event Group       start         end
0            1  2018-07-03  2018-07-08
1            2  2018-07-09  2018-07-12
2            3  2018-07-15  2018-07-18
3            4  2018-07-22  2018-07-25

编辑

a = (df['Event'] != 'A').cumsum().mask(df['Event'] != 'A')
df['Event Group'] = a.ffill()
df_out = df.groupby('Event Group').filter(lambda x: set(x['Event']) == set(['A','B']))\
           .groupby('Event Group')['DateEvent'].agg(['first','last'])\
           .rename(columns={'first':'start','last':'end'})\
           .reset_index()

【讨论】:

  • 在这几行代码中,这是一些严肃的 Python。我对你的看法,好先生。
  • @AlešJuvančič 谢谢。编码愉快!
  • 如果我将第一个事件从 B 更改为 A(一开始有两个 A 事件),第一个事件将获得不同的组并在以后被丢弃......如何克服这个问题?谢谢!
  • 我看到了问题...用您的数据尝试第二段代码。
  • 是的,它现在可以工作了...我需要一些时间来尝试理解更改:) 谢谢 Scott!
猜你喜欢
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
相关资源
最近更新 更多