以Pandas为单位聚合行重复(运行长度)

2024-04-29 14:46:57 发布

您现在位置:Python中文网/ 问答频道 /正文

在给定系统快照的以下数据帧中,我感兴趣的是记录var1var2随时间的变化,假设系统的状态在发生变化之前保持不变。这类似于运行长度编码,它压缩序列,其中相同的数据值出现在许多连续的数据元素中。从这个意义上说,我对捕捉跑步感兴趣。例如:

    var1 var2   timestamp
    foo  2  2017-01-01 00:07:45
    foo  2  2017-01-01 00:13:42
    foo  3  2017-01-01 00:19:41
    bar  3  2017-01-01 00:25:41
    bar  2  2017-01-01 00:37:36
    bar  2  2017-01-01 00:43:37
    foo  2  2017-01-01 01:01:29
    foo  2  2017-01-01 01:01:34
    bar  2  2017-01-01 01:19:25
    bar  2  2017-01-01 01:25:22

应浓缩为:

expected_output

       var1 var2       min              max
        foo 2   2017-01-01 00:07:45 2017-01-01 00:19:41
        foo 3   2017-01-01 00:19:41 2017-01-01 00:25:41
        bar 3   2017-01-01 00:25:41 2017-01-01 00:37:36
        bar 2   2017-01-01 00:37:36 2017-01-01 01:01:29
        foo 2   2017-01-01 01:01:29 2017-01-01 01:19:25
        bar 2   2017-01-01 01:25:22 None

我尝试了以下聚合,有效地消除了var1var2重复数据,并提供了每个组的最小和最大时间戳:

output = test.groupby(['var1','var2'])['timestamp'].agg(['min','max']).reset_index()

output

   var1 var2       min              max
    bar 2   2017-01-01 00:37:36 2017-01-01 01:25:22
    bar 3   2017-01-01 00:25:41 2017-01-01 00:25:41
    foo 2   2017-01-01 00:07:45 2017-01-01 01:01:34
    foo 3   2017-01-01 00:19:41 2017-01-01 00:19:41

但是,var1var2可以随着时间的推移更改并恢复到相同的原始值,因此min/max函数不起作用,因为var1 var2应该随着时间的推移与同一列中的前一个值进行比较,这与shift()方法类似,但并不完全相同

pandas或numpy中是否有一种有效的方法,类似于R中的rle()方法,可以对这些运行进行分组或分区,并将下一次运行的最小时间戳作为其最大时间戳?真正的数据集超过1000万行。如有任何建议,将不胜感激


Tags: 数据方法outputfoo系统记录时间bar
1条回答
网友
1楼 · 发布于 2024-04-29 14:46:57

对于连续分组,您可以在(df.col != df.col.shift()).cumsum()上分组

您希望将其用于任一列,以便可以将它们|放在一起

>>> ((df.var1 != df.var1.shift()) | (df.var2 != df.var2.shift())).cumsum()
0    1
1    1
2    2
3    3
4    4
5    4
6    5
7    5
8    6
9    6
dtype: int64

groupby+agg

>>> cond = ((df.var1 != df.var1.shift()) | (df.var2 != df.var2.shift())).cumsum()
>>> output = df.groupby(cond).agg(
...     var1=('var1', 'first'),
...     var2=('var2', 'first'),
...     min=('timestamp', 'min'),
...     max=('timestamp', 'max')
... )
>>> output
  var1  var2                  min                  max
1  foo     2  2017-01-01 00:07:45  2017-01-01 00:13:42
2  foo     3  2017-01-01 00:19:41  2017-01-01 00:19:41
3  bar     3  2017-01-01 00:25:41  2017-01-01 00:25:41
4  bar     2  2017-01-01 00:37:36  2017-01-01 00:43:37
5  foo     2  2017-01-01 01:01:29  2017-01-01 01:01:34
6  bar     2  2017-01-01 01:19:25  2017-01-01 01:25:22

然后可以将最大值设置为下一行的最小值:

>>> output['max'] = output['min'].shift(-1)
>>> output
  var1  var2                  min                  max
1  foo     2  2017-01-01 00:07:45  2017-01-01 00:19:41
2  foo     3  2017-01-01 00:19:41  2017-01-01 00:25:41
3  bar     3  2017-01-01 00:25:41  2017-01-01 00:37:36
4  bar     2  2017-01-01 00:37:36  2017-01-01 01:01:29
5  foo     2  2017-01-01 01:01:29  2017-01-01 01:19:25
6  bar     2  2017-01-01 01:19:25                  NaN

相关问题 更多 >