我有一个 dataframe
,它由组标签 ('B') 和每个组的元素 ('A') 组成。组标签是有序的,我想知道我在组 i+1 中出现了多少组元素。
一个例子:
df= pd.DataFrame({ 'A': ['a','b','c','a','c','a','d'], 'B' : [1,1,1,2,2,3,3]})
A B
0 a 1
1 b 1
2 c 1
3 a 2
4 c 2
5 a 3
6 d 3
所需的输出类似于:
B
1 NaN
2 2
3 1
解决此问题的一种方法是计算组 I 和组 i+1 的并集中不同元素的数量,然后减去每个组中不同元素的数量。我试过:
pd.rolling_apply(grp['A'], lambda x: len(x.unique()),2)
但这会产生错误:
AttributeError: 'Series' object has no attribute 'type'
我如何让它与 rolling_apply
一起工作,或者有更好的方法来解决这个问题吗?
最佳答案
一种使用集合并移动结果的方法:
首先对dataframe进行分组,然后将每组的A列转换为一个集合:
In [86]: grp = df.groupby('B')
In [87]: s = grp.apply(lambda x : set(x['A']))
In [88]: s
Out[88]:
B
1 set([a, c, b])
2 set([a, c])
3 set([a, d])
dtype: object
要计算连续集合之间的交集,请制作一个移位版本(我将 NaN 替换为下一步的空集合):
In [89]: s2 = s.shift(1).fillna(set([]))
In [90]: s2
Out[90]:
B
1 set([])
2 set([a, c, b])
3 set([a, c])
dtype: object
合并两个系列并计算交集的长度:
In [91]: s.combine(s2, lambda x, y: len(x.intersection(y)))
Out[91]:
B
1 0
2 2
3 1
dtype: object
完成最后一步的另一种方法(对于集合 &
表示 intersection
):
df = pd.concat([s, s2], axis=1)
df.apply(lambda x: len(x[0] & x[1]), axis=1)
滚动应用不起作用的原因是 1) 您为其提供了一个 GroupBy 对象而不是一个系列,并且 2) 它仅适用于数值。
关于python - 计算 Pandas 滚动交叉点的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22465496/