【问题标题】:Pandas : Event Flagging in time seriesPandas:时间序列中的事件标记
【发布时间】:2020-03-02 07:03:44
【问题描述】:

您好,我正在尝试在时间序列数据上生成一个标志,以识别落在事件 +-3 时间段内的观察结果。每个地方的活动日期可能会有所不同。不知道如何在熊猫中接近。任何建议都将受到欢迎。

【问题讨论】:

  • Don't add pictures of code/data,我们无法复制它来重现答案。而是添加数据的文本版本。
  • 每个地方都只有一个活动吗?
  • 通常是的,在某些情况下它可以有多个事件(甚至可以有重叠的窗口)。
  • 每次我尝试粘贴模拟数据时,stackoverflow 都会强制粘贴为图像选项...有什么想法吗?
  • 既然你有它在 excel 中,用df = pd.read_excel 将其读入 pandas,然后执行print(df),将该输出粘贴到你的问题中。

标签: pandas time-series


【解决方案1】:

让我们试试吧:

import pandas as pd
import numpy as np

d = pd.date_range('2019-01-01', '2019-01-10', freq='D')

df = pd.DataFrame({'ID':np.arange(1,21)
                  ,'Place':['A']*10+['B']*10
                  ,'Date':d.to_list() * 2
                  ,'event':[0]*5+[1]+[0]*7+[1]+[0]*6
                  ,'Flag':[0,0,-3,-2,-1,1,2,3,4,0,-3,-2,-1,
                          1,2,3,4,0,0,0]},
                 index = np.arange(1,21))

n=3
s = df['event'].rolling(n*2+1, center=True, min_periods=1).max()
s = s.cumsum()

l = ((s - s.where(s.duplicated()).ffill())).fillna(0) 
l.update(l[l>n]+1)

df['Flag'] = (l - n-1).where(l.gt(0), 0)
print(df)

输出:

    ID Place       Date  event  Flag
1    1     A 2019-01-01      0   0.0
2    2     A 2019-01-02      0   0.0
3    3     A 2019-01-03      0  -3.0
4    4     A 2019-01-04      0  -2.0
5    5     A 2019-01-05      0  -1.0
6    6     A 2019-01-06      1   1.0
7    7     A 2019-01-07      0   2.0
8    8     A 2019-01-08      0   3.0
9    9     A 2019-01-09      0   4.0
10  10     A 2019-01-10      0   0.0
11  11     B 2019-01-01      0  -3.0
12  12     B 2019-01-02      0  -2.0
13  13     B 2019-01-03      0  -1.0
14  14     B 2019-01-04      1   1.0
15  15     B 2019-01-05      0   2.0
16  16     B 2019-01-06      0   3.0
17  17     B 2019-01-07      0   4.0
18  18     B 2019-01-08      0   0.0
19  19     B 2019-01-09      0   0.0
20  20     B 2019-01-10      0   0.0

【讨论】:

  • 这确实非常有效。最有趣的是,当时间窗口包含多个事件时,它会自动正确运行。也更容易理解发生了什么。
  • @Mario 完成。现在就来看看吧。
【解决方案2】:

我们可以使用pd.merge_asof 将最接近的事件“日期”带到每个“地点”内的每一行。我使用np.select 让您的标志列正确,因为它遵循一些奇怪的逻辑。

如果窗口重叠,您可以更改condschoices 中的顺序,以使一个优先于另一个,而无需彻底检查任何其他逻辑。

import pandas as pd
import numpy as np
df['Date'] = pd.to_datetime(df.Date)

# Bring closest event date to `df`. Sort ruins order, but can fix later.
df = pd.merge_asof(df.sort_values('Date'), 
                   (df.loc[df.Event.eq(1), ['Place', 'Date']]
                      .sort_values('Date')
                      .rename(columns={'Date': 'Date_2'})), 
                   by='Place', 
                   direction='nearest',
                   left_on='Date',
                   right_on='Date_2')

# Find day difference, needs to be adjusted in subsequent steps
df['Flag'] = (df['Date'] - df['Date_2']).dt.days

# Fix Flag to be desired final value.
conds = [df.Flag.ge(-3) & df.Flag.lt(0), df.Flag.ge(0) & df.Flag.le(3)]
choices = [df.Flag, df.Flag+1]
df['Flag'] = np.select(conds, choices, default=0)

输出:print(df.sort_values('ID'))

    ID Place       Date  Event     Date_2  Flag
0    1     A 2019-01-01      0 2019-01-06     0
2    2     A 2019-01-02      0 2019-01-06     0
4    3     A 2019-01-03      0 2019-01-06    -3
6    4     A 2019-01-04      0 2019-01-06    -2
8    5     A 2019-01-05      0 2019-01-06    -1
10   6     A 2019-01-06      1 2019-01-06     1
12   7     A 2019-01-07      0 2019-01-06     2
15   8     A 2019-01-08      0 2019-01-06     3
17   9     A 2019-01-09      0 2019-01-06     4
18  10     A 2019-01-10      0 2019-01-06     0
1   11     B 2019-01-01      0 2019-01-04    -3
3   12     B 2019-01-02      0 2019-01-04    -2
5   13     B 2019-01-03      0 2019-01-04    -1
7   14     B 2019-01-04      1 2019-01-04     1
9   15     B 2019-01-05      0 2019-01-04     2
11  16     B 2019-01-06      0 2019-01-04     3
13  17     B 2019-01-07      0 2019-01-04     4
14  18     B 2019-01-08      0 2019-01-04     0
16  19     B 2019-01-09      0 2019-01-04     0
19  20     B 2019-01-10      0 2019-01-04     0

【讨论】:

  • 谢谢 - 说 merge_asof() 有一个意外的关键字参数“方向” - 适用于 20 及以上..将升级我的熊猫
  • 有用,但有点复杂,Scott 的回答说明了一个时间窗口中的多个事件(即使他可能不是故意的 :-))
猜你喜欢
  • 2023-03-12
  • 2018-01-29
  • 2023-03-07
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 2014-03-05
  • 2019-02-27
  • 2020-03-23
相关资源
最近更新 更多