[英]Split and alter values of pandas 'groupby' elements based on length of the groups
[英]Delete items in pandas groupby groups based on values
我有一个这样的数据框:
ID A B C
"Z" "apple" 1 5
"Z" "pear" 3 1
"C" "apple" 1 8
"E" "strawberry" 2 5
"E" "pear" 5 1
"D" "apple" 1 5
"D" "pear" 3 1
"D" "melon" 1 5
对于具有相同id的那些,我想按如下方式过滤行:如果一个ID下有两条记录,其中一条是“apple”,我想删除包含“apple”的行。 如果我有两个以上的记录,其中一个是“apple”,并且如果我有多个该 ID 的记录并且没有一个是“apple”,我想删除属于该 ID 的所有记录。 所以df应该是这样的:
ID A B C
"Z" "pear" 3 1
"C" "apple" 1 8
我猜测起点应该是按 ID 分组,但我不知道如何编写 function 来执行 rest。
使用带有链式掩码的boolean indexing
|
对于按位OR
:
#filter apples
m0 = df['A'].eq('apple')
#get counts per groups
s = df.groupby('ID')['ID'].transform('size')
#check if at least one apple per group
m2 = m0.groupby(df['ID']).transform('any')
#chain mask with length 2, at least one apple and all not apples OR
#length 1 with apples
df = df[(s.eq(2) & ~m0 & m2) | (s.eq(1) & m0)]
print (df)
ID A B C
1 Z pear 3 1
2 C apple 1 8
详情:
with pd.option_context('expand_frame_repr', False):
print (df.assign(m = m0,
s = s,
m2 = m2,
s2 = s.eq(2),
invm0 = ~m0,
first = (s.eq(2) & ~m0 & m2),
s1 = s.eq(1),
second = (s.eq(1) & m0),
both =(s.eq(2) & ~m0 & m2) | (s.eq(1) & m0)
))
ID A B C m s m2 s2 invm0 first s1 second both
0 Z apple 1 5 True 2 True True False False False False False
1 Z pear 3 1 False 2 True True True True False False True
2 C apple 1 8 True 1 True False False False True True True
3 E strawberry 2 5 False 2 False True True False False False False
4 E pear 5 1 False 2 False True True False False False False
5 D apple 1 5 True 3 True False False False False False False
6 D pear 3 1 False 3 True False True False False False False
7 D melon 1 5 False 3 True False True False False False False
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.