代码之家  ›  专栏  ›  技术社区  ›  the_darkside

聚合行重复(运行长度)

  •  0
  • the_darkside  · 技术社区  · 5 年前

    在给定系统快照的以下数据帧中,我对记录中的任何更改感兴趣 var1 var2 ,假设系统状态保持不变,直到发生变化。这类似于游程编码,它压缩序列,其中相同的数据值出现在许多连续的数据元素中。从这个意义上说,我对捕捉跑步感兴趣。例如:

        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
    

    变量1 变量2

    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
    

    然而, 随着时间的推移,可以更改并恢复为相同的原始值,因此“最小值/最大值”函数不起作用 var1 变量2 应与同一列中随时间变化的前一个值进行比较,类似于但不完全是 shift()

    有没有一个有效的方法在熊猫或numpy,类似的方法 rle()

    0 回复  |  直到 5 年前
        1
  •  1
  •   KarlT    5 年前

    对于连续分组,您可以在 (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
    

    分组方式+聚合

    >>> 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