假设我有一个DataFrame
,如下所示:
import pandas as pd
import numpy as np
df = pd.DataFrame.from_dict({'measurement_id': np.repeat([1, 2], [30, 30]),
'min': np.concatenate([np.repeat([1, 2, 3, 4, 5], [6, 6, 6, 6, 6]),
np.repeat([1, 2, 3, 4, 5], [6, 6, 6, 6, 6])]),
'obj': list('ABCDEF' * 10),
'var': [1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2,
1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2,
2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2,
2, 1, 1, 1, 2, 1]})
因此,有2个测量值在一分钟的间隔内测量了6个对象的var
值。我想做的是创建一个列,该列将计算每个var
值未更改的时间(多少分钟)。我认为可以通过适当的groupby
来实现,它等效于R函数data.table::rleid
,该函数创建游程类型id列并最终计算在所得列的一个值内有多少分钟。
因此,输出结果如下:
df['rleid_output'] = np.concatenate([[1] * 18, [2] * 12, [3] * 6, [4] * 18, [5] * 6])
df['expected_output'] = np.concatenate([[3] * 18, [2] * 12, [1] * 6, [3] * 18, [1] * 6])
不幸的是,我不知道如何在熊猫中做到这一点。我在创建等效的rleid
以及随后获得expected_output
方面都在挣扎。不管是否使用expected_output
等价物,如何实现rleid
的任何想法?
@Edit:要回答有关“ expected_output”的逻辑的评论,这是我脑海计算的方式:
obj
和var
对:(A,1),(B,1),(C,2),(D,2), (E,2),(F,2)var
的{{1}}值变为1。至少有一对已更改,因此我们的整个分配被视为已更改,并开始了新值obj = C
。同时,我们已经知道先前的分配恰好持续了3分钟,对于所有先前的行,rleid_output
的值应设置为3。当前分配(expected_output
,obj
)是(A,1),(B,1),(C,1),(D,2),(E,2),(F,2 )。var
,measurement_id
)实际上是新的度量,因此这是我们的最后一刻,我们已经知道我们应该将min
设置为具有expected_output
的行中的2和(measurement_id, min) == (1, 4)
的分配相同,持续2分钟。(measurement_id, min) == (1, 5)
。它从分配(A,2),(B,2),(C,1),(D,1),(E,2),(F,2)开始。它会在下一分钟更改,因此我们可以将其标记为仅持续1分钟(值为(measurement_id, min) == (2, 1)
)的作业。expected_output
表示从36到53的行。expected_output = 3
的值更改为2,因此我们有了新的赋值((A,2),(B,1),(C,1),(D, 1),(E,2),(F,1))仅持续1分钟,因为我们没有进一步的测量。我希望现在更清楚
另外,最好能知道如何通过单独的作业更改来做到这一点,即,如果我们不将作业视为一个整体,而是将各个对(例如, (A,2)
@ Edit2:根据以下要求,简化了示例:
var