我有一个这样的熊猫数据框:
id some_value
0 tag1 v1
1 tag1 v2
2 tag1 v1
3 tag2 v2
4 tag2 v2
5 tag2 v3
,我想知道some_value
中的值对于每个ID多久更改一次。因此,对于tag1
将是两次(因为它首先从v1
变为v2
然后又变回),对于tag2
它将是一次。我已经解决了这样的问题:
import pandas as pd
df = pd.DataFrame({'id': ['tag1', 'tag1', 'tag1', 'tag2', 'tag2','tag2'], 'some_value': ['v1','v2','v1','v2','v2','v3']})
mask = df['id'] == df['id'].shift(-1)
df['changed'] = df['some_value'] != df['some_value'].shift(-1)
df[mask].groupby('id').sum()
该代码可以正常工作,因为它返回
changed
id
tag1 2.0
tag2 1.0
是否有更优雅的解决方案?
答案 0 :(得分:1)
实现此目标的一种方法是:
def numChanges(x):
return sum(x.iloc[:-1] != x.shift(-1).iloc[:-1])
df.groupby('id').agg({
'some_value' : numChanges
})
请注意,如果id列未排序,结果将有所不同,因此您的解决方案可能会产生不正确的结果,除非您打算这样做。
作为一个例子,在我的解决方案中,下面的数据集将产生tag2值为5,但根据您的结果为3。从技术上讲,正确的答案是5,但是如果对id变量进行排序,则不会有任何区别。
pd.concat([df]*3) #My solution outputs 5 changes for tag2 and yours will give 3 only