我有以下 Dataframe df:
data={'id':[1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2],
'value':[2,2,3,2,2,2,3,3,3,3,1,4,1,1,1,4,4,1,1,1,1,1]}
df=pd.DataFrame.from_dict(data)
df
Out[8]:
id value
0 1 2
1 1 2
2 1 3
3 1 2
4 1 2
5 1 2
6 1 3
7 1 3
8 1 3
9 1 3
10 2 1
11 2 4
12 2 1
13 2 1
14 2 1
15 2 4
16 2 4
17 2 1
18 2 1
19 2 1
20 2 1
21 2 1
我需要做的是在id级别(df. groupby ['id '])识别值连续3次或更多次显示相同数字的情况。
我希望得到上述的以下结果:
df
Out[12]:
id value flag
0 1 2 0
1 1 2 0
2 1 3 0
3 1 2 1
4 1 2 1
5 1 2 1
6 1 3 1
7 1 3 1
8 1 3 1
9 1 3 1
10 2 1 0
11 2 4 0
12 2 1 1
13 2 1 1
14 2 1 1
15 2 4 0
16 2 4 0
17 2 1 1
18 2 1 1
19 2 1 1
20 2 1 1
21 2 1 1
我尝试过groupby和lambda的变体,使用panda rolling. mean来识别滚动周期的平均值在哪里与"值"进行比较,如果它们相同,则表示标记。但这有几个问题,包括您可能有不同的值,这些值的平均值将与您试图标记的值进行比较。此外,我不知道如何"标记"创建初始标记的滚动平均值的所有值。请看这里,这标识了标记的"右侧",但随后我需要填充滚动平均值长度的先前值。请看我的代码:
test=df.copy()
test['rma']=test.groupby('id')['value'].transform(lambda x: x.rolling(min_periods=3,window=3).mean())
test['flag']=np.where(test.rma==test.value,1,0)
结果是:
test
Out[61]:
id value rma flag
0 1 2 NaN 0
1 1 2 NaN 0
2 1 3 2.333333 0
3 1 2 2.333333 0
4 1 2 2.333333 0
5 1 2 2.000000 1
6 1 3 2.333333 0
7 1 3 2.666667 0
8 1 3 3.000000 1
9 1 3 3.000000 1
10 2 1 NaN 0
11 2 4 NaN 0
12 2 1 2.000000 0
13 2 1 2.000000 0
14 2 1 1.000000 1
15 2 4 2.000000 0
16 2 4 3.000000 0
17 2 1 3.000000 0
18 2 1 2.000000 0
19 2 1 1.000000 1
20 2 1 1.000000 1
21 2 1 1.000000 1
等不及要看看我错过了什么!谢谢
5条答案
按热度按时间xjreopfe1#
你可以试试这个;1)创建一个额外的组变量
df.value.diff().ne(0).cumsum()
来表示值的变化;2)使用transform('size')
计算组大小,并与3进行比较,然后得到所需的flag
列:1)*
diff
不等于零 *(这就是df.value.diff().ne(0)
的字面意思)给出了一个条件True
,只要值发生变化:2)然后
cumsum
给出id的非降序序列,其中每个id表示具有相同值的连续块,注意当对布尔值求和时,True
被认为是1而False
被认为是0:3)结合
id
列,可以对数据框进行分组,计算分组大小,得到flag
列。ghhaqwfi2#
结果相同,但速度稍快:
其中:
df.value != df.value.shift()
给出值变化cumsum()
为具有相同值的每个组创建"标签labels.value_counts()
统计每个标签的出现次数labels.map(...)
用上面计算的计数替换标签>= 3
在计数值上创建布尔掩码astype(int)
将布尔值强制转换为int在我的手中,它给你1.03毫秒的df,相比之下,2.1毫秒的心灵的做法。
编辑:
两种方法的混合甚至更快
使用样品df得到911 µ s。
EDIT2:正确的解决方案,以说明ID变更,如@clg4所示
其中,
... | df.id.diff().ne(0)
在ID发生变化时递增标签即使在ID更改时使用相同的值(在索引10上使用值3进行测试),这也能正常工作,并且耗时1.28ms
编辑3:更好的解释
假设索引10的值为3。
df.id.diff().ne(0)
|
是"按位或"运算符,只要其中一个元素是True
,它就给出True
。因此,如果id变化的值没有差异,则|
反映id变化。否则,它什么也不变化。当执行.cumsum()
时,标签在id变化的地方递增。因此索引10处的值3
不与来自索引6 - 9的值3
分组。gupuwyp23#
4si2a6ki4#
fjaof16o5#
输出: