使用 Pandas 选择符合特定条件的一组元素

4

我有一个按id分组的数据框。对于每个id组,我想返回所有列中a大于该组a平均值的行。我尝试了以下方法:

df = pd.DataFrame(data = {"a": np.arange(10), "b": np.arange(10)[::-1], "c": np.random.choice(a = np.arange(10), size = 10)}, index = pd.Index(data = np.random.choice(a = [1,2,3], size = 10), name = "id"))
df.groupby("id").apply(lambda x: x[x.a > x.a.mean()])

我的操作有误吗?

这会引发ValueError错误:重复的级别名称:“id”,分配给级别1,已经用于级别0。


当我使用3.6.2运行此代码时,我没有收到任何错误提示。 - andrew_reece
你用的是哪个版本?我用的是pandas: 0.23.0,numpy: 1.14.3和python 3.6。 - Alex
我得到了相同的错误 - python: 3.6.4.final.0, pandas: 0.23.0, numpy: 1.14.3 - jezrael
一定是最近的更改,我使用的是 Python 3.6.2、NumPy 1.13.1、Pandas 20.3。 - andrew_reece
1个回答

3

使用transform函数可以实现与使用apply函数相同的功能,但是在数据量较大时有更好的性能表现,并且结果Series与原始DataFrame大小相同。

df = df[df['a'] > df.groupby("id")['a'].transform('mean')]
print (df)
    a  b  c
id         
2   5  4  3
2   6  3  2
1   7  2  3
3   8  1  0
3   9  0  5

详情:

print (df.groupby("id")['a'].transform('mean'))
id
1    4.75
1    4.75
1    4.75
3    3.50
3    3.50
1    4.75
1    4.75
1    4.75
1    4.75
1    4.75
Name: a, dtype: float64

在您的解决方案中,需要使用参数group_keys=False来避免具有相同级别名称的MultiIndex,因为索引名称中包含id

df = df.groupby("id", group_keys=False).apply(lambda x: x[x.a > x.a.mean()])

如果首次使用reset_index()获取列名id和索引名id,但存在相同的值:
df = df.reset_index().groupby("id").apply(lambda x: x[x.a > x.a.mean()])
print (df)
      id  a  b  c
id               
2  6   2  6  3  3
   7   2  7  2  9
   9   2  9  0  1
3  5   3  5  4  9
   8   3  8  1  8

另一个测试 - 移除 索引名称 - id:

df = df.rename_axis(None)
print (df)
   a  b  c
3  0  9  2
2  1  8  2
1  2  7  6
3  3  6  1
1  4  5  3
2  5  4  9
3  6  3  6
2  7  2  1
1  8  1  0
1  9  0  1

df = df.groupby(level=0).apply(lambda x: x[x.a > x.a.mean()])
print (df)
     a  b  c
1 1  8  1  0
  1  9  0  1
2 2  5  4  9
  2  7  2  1
3 3  6  3  6

我知道那是怎么回事,但我做的有什么问题吗? - Alex
我看到了你的详细编辑,但我仍然不明白为什么我的方法失败了。 - Alex
啊,好的,现在明白了:这只是因为你可以按照其他东西进行分组,对吧?比如按列或某些 f(列) 进行分组。 - Alex
@Alex - 嗯,我认为你的解决方案完全没问题,在我看来只是一个小错误,只要 index 有名称就可以了。如果删掉它,就可以工作了,请查看最后一次编辑。 - jezrael
我认为 group_keys = False 是解决这个问题的正确方法,感谢您指出。 - Alex
显示剩余2条评论

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