添加一个虚拟指示分组数据框中连续行之间的变化

Add a dummy indicating change between consecutive rows in grouped dataframe

这是对我之前的问题 的跟进。 假设这样的数据集(最初是从 .csv 中读取的):

data = pd.DataFrame({'id': [1,2,3,1,2,3,1,2,3],
                     'time':['2017-01-01 12:00:00','2017-01-01 12:00:00','2017-01-01 12:00:00',
                            '2017-01-01 12:10:00','2017-01-01 12:10:00','2017-01-01 12:10:00',
                            '2017-01-01 12:20:00','2017-01-01 12:20:00','2017-01-01 12:20:00'],
                     'values': [10,11,12,10,12,13,10,13,13]})

data = data.set_index('id')

=>

    id  time                    values
0   1   2017-01-01 12:00:00     10
1   2   2017-01-01 12:00:00     11
2   3   2017-01-01 12:00:00     12
3   1   2017-01-01 12:10:00     10
4   2   2017-01-01 12:10:00     12
5   3   2017-01-01 12:10:00     13
6   1   2017-01-01 12:20:00     10
7   2   2017-01-01 12:20:00     13
8   3   2017-01-01 12:20:00     13

每个观察期的所有 ID 的时间都是相同的。对于许多观察,该系列继续进行,即每十分钟一次。 之前学习了如何获取每个id连续两个周期之间values的变化总数:

data.groupby(data.index).values.apply(lambda x: (x != x.shift()).sum() - 1)

这很好用而且速度非常快。现在,我有兴趣向 df 添加一个新列。如果当前行和上一行之间有变化,它应该是一个虚拟值,指示 values 中的每一行。因此,结果如下:

=>

    id  time                    values    change
0   1   2017-01-01 12:00:00     10        0
1   2   2017-01-01 12:00:00     11        0
2   3   2017-01-01 12:00:00     12        0
3   1   2017-01-01 12:10:00     10        0
4   2   2017-01-01 12:10:00     12        1
5   3   2017-01-01 12:10:00     13        1
6   1   2017-01-01 12:20:00     10        0
7   2   2017-01-01 12:20:00     13        1
8   3   2017-01-01 12:20:00     13        0

折腾了半天,想出了一个办法。然而,它真的很慢。它不会 运行 在我相当大的实际数据集上:

def calc_change(x):
    x = (x != x.shift())
    x.iloc[0,] = False
    return x

changes = data.groupby(data.index, as_index=False).values.apply(
                       calc_change).reset_index().iloc[:,2]
data = data.sort_index().reset_index()
data.loc[changes, 'change'] = 1 
data = data.fillna(0)

我相信还有更好的,感谢您的帮助!

如果您的 id 列未设置为索引,您可以使用此解决方案。

data['change'] = data.groupby(['id'])['values'].apply(lambda x: x.diff() > 0).astype(int)

你得到

    id  time             values change
0   1   2017-01-01 12:00:00 10  0
1   2   2017-01-01 12:00:00 11  0
2   3   2017-01-01 12:00:00 12  0
3   1   2017-01-01 12:10:00 10  0
4   2   2017-01-01 12:10:00 12  1
5   3   2017-01-01 12:10:00 13  1
6   1   2017-01-01 12:20:00 10  0
7   2   2017-01-01 12:20:00 13  1
8   3   2017-01-01 12:20:00 13  0

以id为索引,

data = data.sort_index()
data['change'] = data.groupby(data.index)['values'].apply(lambda x: x.diff() > 0).astype(int)