我有以下数据框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
我尝试过使用pandas rolling来改变groupby和lambda。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
迫不及待地想看看我错过了什么!谢谢
您可以尝试这样做;1)使用
df.value.diff().ne(0).cumsum()
创建一个额外的组变量来表示值的更改;2)使用transform('size')
来计算组大小并与三个值进行比较,然后得到所需的flag
列:故障:
1)
diff
不等于0(字面上是df.value.diff().ne(0)
的意思)在值发生变化时给出条件True
:2)然后
cumsum
给出一个id的非降序序列,其中每个id表示具有相同值的连续块,注意当对布尔值求和时,True
被视为一,而False
被视为零:3)结合
id
列,可以对数据帧进行分组,计算分组大小,得到flag
列。有关更可靠的解决方案,请参阅EDIT2
同样的结果,但速度要快一点:
其中:
df.value != df.value.shift()
给出值的变化cumsum()
为每个值相同的组创建“标签”labels.value_counts()
统计每个标签的出现次数labels.map(...)
用上面计算的计数替换标签>= 3
在计数值上创建布尔掩码astype(int)
将布尔值转换为int在我的手中,你的df值是1.03毫秒,而灵能症治疗的df值是2.1毫秒。 但我的不是一艘班轮。
编辑:
两种方法的混合甚至更快
提供911微秒的样品测向。
EDIT2:正确的解决方案来解释id更改,如@clg4所示
其中
... | df.id.diff().ne(0)
增加id更改的标签即使在id更改时使用相同的值(在索引10中使用值3进行测试),也可以使用1.28ms
EDIT3:更好的解释
以索引10的值为3的情况为例。
df.id.diff().ne(0)
|
是运算符“按位或”,只要其中一个元素是True
,它就给出True
。因此,如果id更改的值中没有diff,则|
反映id更改。否则什么也改变不了。 当执行.cumsum()
时,如果id发生变化,标签将递增,因此索引10处的值3
不会与索引6-9中的值3
分组。相关问题 更多 >
编程相关推荐