我认为这是相当简单的事情,但我找不到如何做到这一点。我一直在寻找教程和stackoverflow。
假设我有一个像这样的数据帧df:
Group Id_In_Group SomeQuantity
1 1 10
1 2 20
2 1 7
3 1 16
3 2 22
3 3 5
3 4 12
3 5 28
4 1 1
4 2 18
4 3 14
4 4 7
5 1 36
我想只选择组中至少有4个对象的行(因此至少有4行具有相同的“组”编号),并且对于第4个对象的SomeQuantity,当按组排序时升序SomeQuantity,大于20(例如)。
在给定的Dataframe中,例如,它只返回第3组,因为它有4个(> = 4)成员,其第4个SomeQuantity(排序后)是22(> = 20),所以应该构建数据框:
Group Id_In_Group SomeQuantity
3 1 16
3 2 22
3 3 5
3 4 12
3 5 28
(由SomeQuantity分类或不分类。)
有人可以帮助我吗? :)
答案 0 :(得分:5)
我会使用.groupby()
+ .filter()
方法:
In [66]: df.groupby('Group').filter(lambda x: len(x) >= 4 and x['SomeQuantity'].max() >= 20)
Out[66]:
Group Id_In_Group SomeQuantity
3 3 1 16
4 3 2 22
5 3 3 5
6 3 4 12
7 3 5 28
答案 1 :(得分:3)
使用map
,value_counts
,groupby
,filter
的方法略有不同:
(df[df.Group.map(df.Group.value_counts().ge(4))]
.groupby('Group')
.filter(lambda x: np.any(x['SomeQuantity'].sort_values().iloc[3] >= 20)))
步骤细分:
执行value_counts
以计算组列中存在的不同元素的总计数。
>>> df.Group.value_counts()
3 5
4 4
1 2
5 1
2 1
Name: Group, dtype: int64
使用map
功能,如字典(其中索引成为键,系列元素成为值),将这些结果映射回原始DF
>>> df.Group.map(df.Group.value_counts())
0 2
1 2
2 1
3 5
4 5
5 5
6 5
7 5
8 4
9 4
10 4
11 4
12 1
Name: Group, dtype: int64
然后,我们检查值为4或更高的元素,这是我们的阈值限制,并仅从整个DF
中获取那些子集。
>>> df[df.Group.map(df.Group.value_counts().ge(4))]
Group Id_In_Group SomeQuantity
3 3 1 16
4 3 2 22
5 3 3 5
6 3 4 12
7 3 5 28
8 4 1 1
9 4 2 28
10 4 3 14
11 4 4 7
为了对此使用groupby.filter
操作,我们必须确保在执行排序过程时返回与每个分组键对应的单个布尔值,并将第四个元素与阈值20进行比较。
np.any
会返回与我们的过滤器匹配的所有可能性。
>>> df[df.Group.map(df.Group.value_counts().ge(4))] \
.groupby('Group').apply(lambda x: x['SomeQuantity'].sort_values().iloc[3])
Group
3 22
4 18
dtype: int64
从这些中,我们比较第四个元素.iloc[3]
,因为它是基于0的索引并返回所有这些有利的匹配。
答案 2 :(得分:1)
这就是我处理你的问题,疣和所有的方法。我确定有更好的方法可以做到这一点。
查找包含“群组中的4个对象”的群组
import collections
groups = list({k for k, v in collections.Counter(df.Group).items() if v > 3} );groups
Out:[3, 4]
使用这些组过滤到包含这些组的新df:
df2 = df[df.Group.isin(groups)]
“4th SomeQuantity(排序后)是22(> = 20)”
df3 = df2.sort_values(by='SomeQuantity',ascending=False)
(根据以下评论更新......)
df3.groupby('Group').filter(lambda grp: any(grp.sort_values('SomeQuantity').iloc[3] >= 20)).sort_index()
Group Id_In_Group SomeQuantity
3 3 1 16
4 3 2 22
5 3 3 5
6 3 4 12
7 3 5 28