聚合行重复 pandas(运行 长度)
Aggregating row repeats in pandas (run lengths)
在给定系统的以下快照数据框中,我有兴趣记录 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
我尝试了以下聚合,它有效地删除了 var1
和 var2
的重复数据,并提供了每组的最小和最大时间戳:
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
和 var2
可以随着时间的推移改变并恢复到相同的原始值,因此 min/max 函数不起作用,因为 var1
和 var2
应该随着时间的推移与同一列中的先前值进行比较,类似于但不完全是 shift()
方法所做的。
pandas 或 numpy 中是否有一种有效的方法,类似于 R 中的 rle()
方法,可以对这样的 运行 进行分组或分区,并采用最小时间戳下一个 运行 作为最大值?真实数据集超过 1000 万行。如有任何建议,我们将不胜感激!
对于连续分组,您可以在 (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 + 聚合
>>> 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
在给定系统的以下快照数据框中,我有兴趣记录 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
我尝试了以下聚合,它有效地删除了 var1
和 var2
的重复数据,并提供了每组的最小和最大时间戳:
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
和 var2
可以随着时间的推移改变并恢复到相同的原始值,因此 min/max 函数不起作用,因为 var1
和 var2
应该随着时间的推移与同一列中的先前值进行比较,类似于但不完全是 shift()
方法所做的。
pandas 或 numpy 中是否有一种有效的方法,类似于 R 中的 rle()
方法,可以对这样的 运行 进行分组或分区,并采用最小时间戳下一个 运行 作为最大值?真实数据集超过 1000 万行。如有任何建议,我们将不胜感激!
对于连续分组,您可以在 (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 + 聚合
>>> 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