我经常使用pandas'agg()
函数来运行data.frame的每一列的摘要统计信息。例如,以下是产生均值和标准差的方法:
df = pd.DataFrame({'A': ['group1', 'group1', 'group2', 'group2', 'group3', 'group3'],
'B': [10, 12, 10, 25, 10, 12],
'C': [100, 102, 100, 250, 100, 102]})
>>> df
[output]
A B C
0 group1 10 100
1 group1 12 102
2 group2 10 100
3 group2 25 250
4 group3 10 100
5 group3 12 102
在这两种情况下,将各行发送到agg函数的顺序无关紧要。但请考虑以下示例,其中:
df.groupby('A').agg([np.mean, lambda x: x.iloc[1] ])
[output]
mean <lambda> mean <lambda>
A
group1 11.0 12 101 102
group2 17.5 25 175 250
group3 11.0 12 101 102
在这种情况下,lambda按预期运行,输出每组中的第二行。但是,我无法在pandas文档中找到任何内容,这意味着在所有情况下都保证这是真的。我想使用agg()
和加权平均函数,所以我想确保进入函数的行的顺序与它们在原始数据框中出现的顺序相同。
有没有人知道,理想情况下是通过docs或pandas源代码中的某个地方,如果确保如此?
答案 0 :(得分:17)
查看此增强功能issue
简短的回答是肯定的,groupby将保留传入的排序。您可以使用这样的示例证明这一点:
In [20]: df.sort_index(ascending=False).groupby('A').agg([np.mean, lambda x: x.iloc[1] ])
Out[20]:
B C
mean <lambda> mean <lambda>
A
group1 11.0 10 101 100
group2 17.5 10 175 100
group3 11.0 10 101 100
对于重新采样不是这样,因为它需要单调索引(它将使用非单调索引,但会先对其进行排序)。
它们是groupby的sort=
标志,但这与组本身的排序有关,而与组内的观察无关。
仅供参考:df.groupby('A').nth(1)
是一种获取组的第二个值的安全方法(如果一个组具有&lt; 2个元素,则上述方法将失败)
答案 1 :(得分:7)
Panda的0.19.1 doc说“groupby保留了每个组中行的顺序”,所以这是行为保证。
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html
答案 2 :(得分:2)
为了保留顺序,您需要传递.groupby(..., sort=False)
。在您的情况下,分组列已经排序,因此没有什么区别,但通常必须使用sort=False
标志:
df.groupby('A', sort=False).agg([np.mean, lambda x: x.iloc[1] ])
答案 3 :(得分:0)
更容易:
import pandas as pd
pd.pivot_table(df,index='A',aggfunc=(np.mean))
输出:
B C
A
group1 11.0 101
group2 17.5 175
group3 11.0 101
答案 4 :(得分:0)
参考: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html
SORT参数的描述如下:
sort:bool,默认为True 排序组键。关闭此功能可获得更好的性能。请注意,这不会影响每个组中观察的顺序。 Groupby保留每个组中行的顺序。
答案 5 :(得分:0)
很遗憾,这个问题的答案是否定的。在过去的几天里,我创建了一个用于非均匀分块的算法,发现它不可能保持顺序,因为 groupby 引入了子帧,其中每个帧的关键是 groupby 输入。所以你最终得到:
allSubFrames = df.groupby("myColumnToOrderBy")
for orderKey, individualSubFrame in allSubFrames:
do something...
因为它使用字典你失去了排序。
如果你之后执行排序,如上所述,我刚刚测试了一个庞大的数据集,你最终会得到一个 O(n log n) 计算。
然而,我发现如果你有例如按顺序排列的时间序列数据,你想在其中保留顺序,最好将排序列更改为列表,然后创建一个记录第一个项目的计数器每个时间序列。这导致 O(n) 计算。
因此,基本上如果您使用的是相对较小的数据集,上述建议的答案是合理的,但如果使用大数据集,则需要考虑避免分组和排序。而是使用:list(df['myColumnToOrderBy'])
并对其进行迭代。