Fin*_*rog 11 python dataframe pandas
我正在尝试执行groupby过滤器,它与本文档中的示例非常相似: pandas groupby filter
>>> df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
... 'foo', 'bar'],
... 'B' : [1, 2, 3, 4, 5, 6],
... 'C' : [2.0, 5., 8., 1., 2., 9.]})
>>> grouped = df.groupby('A')
>>> grouped.filter(lambda x: x['B'].mean() > 3.)
A B C
1 bar 2 5.0
3 bar 4 1.0
5 bar 6 9.0
Run Code Online (Sandbox Code Playgroud)
我试图返回一个包含所有3列但只有2行的DataFrame.在按A列分组后,这两行包含列B的最小值.我尝试了以下代码行:
grouped.filter(lambda x: x['B'] == x['B'].min())
Run Code Online (Sandbox Code Playgroud)
但这不起作用,我得到这个错误:
TypeError: filter function returned a Series, but expected a scalar bool
我试图返回的DataFrame应如下所示:
A B C
0 foo 1 2.0
1 bar 2 5.0
Run Code Online (Sandbox Code Playgroud)
我很感激您提供的任何帮助.预先感谢您的帮助.
有一个根本的区别:在文档例子,有一个单独的Boolean值每组。也就是说,返回整组如果平均大于3.在你的榜样,你要过滤特定行中的一组。
对于您的任务,通常的技巧是对值进行排序并分别使用.head或.tail过滤到具有最小值或最大值的行:
df.sort_values('B').groupby('A').head(1)
# A B C
#0 foo 1 2.0
#1 bar 2 5.0
Run Code Online (Sandbox Code Playgroud)
对于更复杂的查询,您可以使用.transform或.apply创建一个布尔值Series来切片。在这种情况下,如果多行共享最小值并且您需要所有行,则更安全:
df[df.groupby('A').B.transform(lambda x: x == x.min())]
# A B C
#0 foo 1 2.0
#1 bar 2 5.0
Run Code Online (Sandbox Code Playgroud)
简短的回答:
grouped.apply(lambda x: x[x['B'] == x['B']].min())
Run Code Online (Sandbox Code Playgroud)
...和更长的一个:
您的grouped对象有 2 组:
In[25]: for df in grouped:
...: print(df)
...:
('bar',
A B C
1 bar 2 5.0
3 bar 4 1.0
5 bar 6 9.0)
('foo',
A B C
0 foo 1 2.0
2 foo 3 8.0
4 foo 5 2.0)
Run Code Online (Sandbox Code Playgroud)
filter()GroupBy 对象的方法用于将组作为实体过滤,而不是用于过滤它们的各个行。所以使用该filter()方法,你可能只能得到4个结果:
没有别的,不管方法中使用的参数(布尔函数)如何filter()。
所以你必须使用其他方法。一个合适的apply()方法是非常灵活的方法,它允许您应用任意函数
在您的情况下,该函数应返回(对于您的 2 个组中的每一个)列中具有最小值'B'的 1 行 DataFrame ,因此我们将使用布尔掩码
group['B'] == group['B'].min()
Run Code Online (Sandbox Code Playgroud)
用于选择这样的一行(或者 - 也许 - 更多行):
In[26]: def select_min_b(group):
...: return group[group['B'] == group['B'].min()]
Run Code Online (Sandbox Code Playgroud)
现在使用这个函数作为apply()GroupBy 对象的方法的参数,grouped我们将获得
In[27]: grouped.apply(select_min_b)
Out[27]:
A B C
A
bar 1 bar 2 5.0
foo 0 foo 1 2.0
Run Code Online (Sandbox Code Playgroud)
笔记:
相同,但只有一个命令(使用lambda函数):
grouped.apply(lambda group: group[group['B'] == group['B']].min())
Run Code Online (Sandbox Code Playgroud)
不需要groupby:-)
df.sort_values('B').drop_duplicates('A')
Out[288]:
A B C
0 foo 1 2.0
1 bar 2 5.0
Run Code Online (Sandbox Code Playgroud)
>>> # sort=False to return the rows in the order they originally occurred
>>> df.loc[df.groupby("A", sort=False)["B"].idxmin()]
A B C
0 foo 1 2.0
1 bar 2 5.0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
839 次 |
| 最近记录: |