Pandas按组分组,其中一个组值在范围内

3
我想找到至少有一行满足 0.5 < C < 1.0 的分组大小。给定这样的一个数据框:
A B C
1 2 0.1
1 2 0.9
1 2 1.0
2 5 0
2 5 0.1
2 5 0.2
3 4 0.6
我希望返回类似下面的结果:
A B Size
1 2 3
3 4 1
我尝试了以下方法:
group = dataset.groupby(['A', 'B'])
filtered = group.filter(lambda x: 0.5 < x['C'] < 1.0)
filtered.size()

然而,第二行出现了以下错误:
``` ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). ```
在此上下文中,any()函数是有意义的,因为我希望任何C的值都在0.5和1.0之间才能计算该组,但我不知道在哪里调用any()。我尝试在lambda上调用它,也尝试在filter()之后调用它,但我尝试的所有方法都无效。

@Kris,那样会不会只返回0.5 < C < 1.0的行?我想要所有其组中至少有一行满足0.5 < C < 1.0的行。 - at.
如果您的左约束是 <=,则可以使用 .between()。因此,df["C"].between(0.5, 1, inclusive=False) - smci
4个回答

4
df["tmp"] = (df["C"] > 0.5) & (df["C"] < 1.0)
g = df.groupby(["A", "B"])
print(g.size()[g["tmp"].sum() > 0])

输出:

A  B
1  2    3
3  4    1
dtype: int64

1
在对 groupby 进行布尔索引时使用 any
df.groupby(['A','B']).size()[df.groupby(['A','B']).apply(lambda g:((g['C'] > 0.5) & (g['C'] < 1.0)).any())]

打印

A  B
1  2    3
3  4    1
dtype: int64

那就是我需要放置 any() 的地方! - at.
:-) 感谢您的投票,并很高兴它帮助您解决了 any() 问题!虽然还有一些其他的解决方案,但也可以说更加优雅。 - piterbarg

1
我们可以直接执行sum
out = df.C.between(.5,1).groupby([df['A'],df['B']]).sum().loc[lambda x : x!=0]
Out[180]: 
A  B
1  2    2
3  4    1
Name: C, dtype: int64

0
df.groupby(['A', 'B']).agg(
    {'C': lambda x: len(x) if np.logical_and(0.5 < x.values,  x.values < 1.).sum() else None}
).dropna().astype(int).rename(columns={'C': 'size'})

     size
A B      
1 2     3
3 4     1

或者如果您更喜欢将AB作为列:

df.groupby(['A', 'B']).agg(
    {'C': lambda x: len(x) if np.logical_and(0.5 < x.values,  x.values < 1.).sum() else None}
).dropna().astype(int).rename(columns={'C': 'size'}).reset_index()

   A  B  size
0  1  2     3
1  3  4     1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接