根据行数切片 Pandas Dataframe
Slicing Pandas Dataframe according to number of lines
我想这是相当简单的事情,但我找不到如何制作它。我一直在搜索教程和计算器。
假设我有一个像这样的数据框 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
我只想 select 组中至少有 4 个对象的行(因此至少有 4 行具有相同的 "group" 编号)并且第 4 个为 SomeQuantity对象在组中按 SomeQuantity 升序排序时大于 20(例如)。
例如,在给定的 Dataframe 中,它只会 return 第三组,因为它有 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 排序)。
有人可以帮助我吗? :)
我会使用 .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
使用 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
计算 Group 列中存在的不同元素的总数。
>>> 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
操作,我们必须确保我们 return 在执行排序过程并将第四个元素与阈值为 20。
np.any
return 所有这些可能性都符合我们的过滤器。
>>> 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 开始索引和 return 所有这些有利的匹配。
我就是这样解决你的问题的,包括缺点和所有问题。我相信有更好的方法可以做到这一点。
查找“组中有 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)]
“第 4 个 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
我想这是相当简单的事情,但我找不到如何制作它。我一直在搜索教程和计算器。
假设我有一个像这样的数据框 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
我只想 select 组中至少有 4 个对象的行(因此至少有 4 行具有相同的 "group" 编号)并且第 4 个为 SomeQuantity对象在组中按 SomeQuantity 升序排序时大于 20(例如)。
例如,在给定的 Dataframe 中,它只会 return 第三组,因为它有 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 排序)。
有人可以帮助我吗? :)
我会使用 .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
使用 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
计算 Group 列中存在的不同元素的总数。
>>> 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
操作,我们必须确保我们 return 在执行排序过程并将第四个元素与阈值为 20。
np.any
return 所有这些可能性都符合我们的过滤器。
>>> 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 开始索引和 return 所有这些有利的匹配。
我就是这样解决你的问题的,包括缺点和所有问题。我相信有更好的方法可以做到这一点。
查找“组中有 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)]
“第 4 个 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