首页 > 解决方案 > 将时间序列列与条件相加

问题描述

我目前正在处理从工程工厂收到的一些数据,数据(大致)如下所示:

    df = pd.DataFrame({'ID' : np.random.randint(1,25,size=5),
'on/off' : np.random.randint(0,2,size=5),
'Time' : pd.date_range(start='01/01/2019',periods=5,freq='5s')})
     print(df)
    ID  on/off  Time
0   17  0   2019-01-01 00:00:00 
1   21  0   2019-01-01 00:00:05 
2   12  1   2019-01-01 00:00:10 
3   12  1   2019-01-01 00:00:15 
4   12  0   2019-01-01 00:00:20 

on/off 列中的 0 和 1 对应于机器的开启或关闭时间(0 = on 1 = off)

目前,我使用下面这行漂亮的代码来获取我的列之间的差异,因为数据正在滚动

df['Time Difference'] = (df.time - df.time.shift()) 
print(df)
    ID  on/off  Time    Time Difference
0   17  0   2019-01-01 00:00:00 NaT
1   21  0   2019-01-01 00:00:05 00:00:05
2   12  1   2019-01-01 00:00:10 00:00:05
3   12  1   2019-01-01 00:00:15 00:00:05
4   12  0   2019-01-01 00:00:20 00:00:05

现在因为这个数据框非常冗长(每周我会收到大约 150k 行)

在下一个 0 出现之前,计算机器关闭时间(df['on/off] == 1)的最佳方法是什么?因此,在 2019 年 1 月 1 日的上述示例中,ID 为 12 的机器在 00:00:20 恢复之前没有运行 15 秒

我真的很困惑这个..!我可以按 ID、开关、日期、时间戳对它进行分组,但我不确定如何处理单个列中的滚动数据位。非常感谢任何帮助或建议。

DN。

标签: pythonpandasdataframetime

解决方案


这是一种方法,它适用于一个简单的例子,一台机器在一天的过程中会在开启和关闭之间变化。无论机器是否处于第一行on或状态,它都可以工作。off

df = pd.DataFrame({'ID': [12, 12, 12, 12, 12],
                   'on/off': [0,0,1,0,1],
                   'Time': ['2019-01-01 00:00:00', '2019-01-01 00:00:05', '2019-01-01 00:00:10','2019-01-01 00:00:15','2019-01-01 00:00:20']
})

    ID  on/off  Time
0   12  0       2019-01-01 00:00:00
1   12  0       2019-01-01 00:00:05
2   12  1       2019-01-01 00:00:10
3   12  0       2019-01-01 00:00:15
4   12  1       2019-01-01 00:00:20
  1. 首先,我确保Time列 dtype 是 datetime64:

df['Time'] = pd.to_datetime(df['Time'])

  1. 然后我得到状态改变的所有行的索引(从offon,或从onoff
s = df[df['on/off'].shift(1) != df['on/off']].index
df = df.loc[s]
  1. 然后我创建一个名为 的列time shift,它显示电源状态更改的最近行的时间戳:
df['time shift'] = df['Time'].shift(1)

此时数据框如下所示:

    ID  on/off  Time                 time shift
0   12  0       2019-01-01 00:00:00  NaT
2   12  1       2019-01-01 00:00:10  2019-01-01 00:00:00
3   12  0       2019-01-01 00:00:15  2019-01-01 00:00:10
4   12  1       2019-01-01 00:00:20  2019-01-01 00:00:15
  1. 现在,由于我们要计算机器关闭的持续时间,我只查看状态变为的行索引on
r = df[df['on/off'] == 1].index
df = df.loc[r]

此时,数据框如下所示。请注意,该time shift列显示的是机器最近关闭的时间点,该时间早于Time列中显示的时间,即机器重新打开时的时间戳。找出这两列之间的差异将为我们提供机器在白天关闭的每个持续时间的长度:

    ID  on/off  Time                 time shift
2   12  1       2019-01-01 00:00:10  2019-01-01 00:00:00
4   12  1       2019-01-01 00:00:20  2019-01-01 00:00:15
  1. off以下行通过将机器处于其状态的每个时期的持续时间相加来计算总停机时间:
(df['Time'] - df['time shift']).sum()

哪个输出:

Timedelta('0 days 00:00:15')

关于 Pandas.shift()方法如何工作的一些附加上下文:

Shift 获取列中的所有行,并将它们向前或向后移动一定量。.shift(1)告诉 pandas 将每行的索引向前或向上.shift(-1)移动 1。告诉 pandas 将每行的索引向后或向下移动 1。或者,.shift(1)让您查看前一行的列的值索引,并.shift(-1)让您在下一行索引处查看列的值,相对于列中的给定行。这是一种比较不同行的列值的便捷方法,无需使用 for 循环。


推荐阅读