确定分组数据框中值的更改

时间:2017-09-18 22:06:50

标签: python pandas dataframe group-by pandas-groupby

假设这样的数据集(最初是从.csv读入的):

data = pd.DataFrame({'id': [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'],
                     'value': [10,11,12,10,12,13]})

=>

    id  time                    value
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

每个观察期的所有ID的时间都相同。对于许多观察,即每十分钟,该系列继续这样。

我希望value列中的总更改次数在连续时间之间按ID显示。例如:对于id = 1,没有变化(结果:0)。对于id = 2,有一个更改(结果:1)。 受这篇文章的启发,我尝试过差异: Determining when a column value changes in pandas dataframe

这是我到目前为止所做的(不按预期工作):

data = data.set_index(['id', 'time']) # MultiIndex 
grouped = data.groupby(level='id') 
data['diff'] = grouped['value'].diff()
data.loc[data['diff'].notnull(), 'diff'] = 1
data.loc[data['diff'].isnull(), 'diff'] = 0
grouped['diff'].sum()

但是,这只是每个id的出现次数之和。

由于我的数据集很大(并且不适合内存),因此解决方案应该尽可能快。 (这就是为什么我在id + time上使用MultiIndex。我期望显着的加速,因为最好的数据不再需要改组。)

此外,我遇到了与pandas dfs非常相似的dask数据帧。使用它们的解决方案将是非常棒的。

3 个答案:

答案 0 :(得分:3)

你想要这样的东西吗?

data.groupby('id').value.apply(lambda x: len(set(x)) - 1)

你得到了

id
1    0
2    1
3    1

编辑:正如@COLDSPEED所述,如果要求将更改捕获回特定值,请使用

data.groupby('id').value.apply(lambda x: (x != x.shift()).sum() - 1)

答案 1 :(得分:3)

data.groupby('id').value.agg(lambda x : (x.diff()!=0).sum()).add(-1)
id
1    0
2    1
3    1
Name: value, dtype: int64

另一个使用pct_change

data.groupby('id').value.apply(lambda x : (x.pct_change()!=0).sum()).add(-1)
Out[323]: 
id
1    0
2    1
3    1
Name: value, dtype: int64

答案 2 :(得分:3)

我认为您正在寻找groupby并按shift进行比较;

data.groupby('id')['value'].agg(lambda x: (x != x.shift(-1)).sum() - 1) 

id
1    0
2    1
3    1
Name: value, dtype: int64