我有以下数据集:
import numpy as np
from pandas import DataFrame
import numpy.random as random
random.seed(12)
df = DataFrame (
{
"fac1" : ["a","a","a","a","b","b","b","b"] ,
"val" : random.choice(np.arange(0,20), 8, replace=False)
}
)
df2 = df.set_index(["fac1"])
df2
我想要的是在每个 fac1
组中按 val
排序,以产生这个:
我已经梳理了文档,找不到直接的方法。我能做的最好的就是以下 hack:
df3 = df2.reset_index()
df4 = df3.sort_values(["fac1","val"],ascending=[True,True],axis=0)
df5 = df4.set_index(["fac1"])
df5
# Produces the picture above
(我意识到以上内容可以从多个 inplace
选项中获益,只是这样做是为了使中间产品清晰)。
我确实找到了 this SO post ,它使用分组和排序功能。但是,改编自该帖子的以下代码产生了不正确的结果:
df2.groupby("fac1",axis=1).apply(lambda x : x.sort_values("val"))
(出于空间考虑删除了输出)
还有其他方法可以解决这个问题吗?
更新:解决方案
公认的解决方案是:
df2.sort_values(by='val').sort_index(kind='mergesort')
排序算法必须是mergesort
,并且必须明确指定,因为它不是默认值。作为the sort_index
documentation指出,“mergesort 是唯一的 stable 算法。”这是另一个示例数据集,如果您没有为 kind
指定 mergesort
,它将无法正确排序:
random.seed(12)
len = 32
df = DataFrame (
{
"fac1" : ["a" for i in range(int(len/2))] + ["b" for i in range(int(len/2))] ,
"val" : random.choice(np.arange(0,100), len, replace=False)
}
)
df2 = df.set_index(["fac1"])
df2.sort_values(by='val').sort_index()
(出于空间考虑,我省略了所有输出)
最佳答案
编辑:我查看了文档,发现 sort_index 的默认排序算法是快速排序。这不是一个“稳定”算法,因为它不保留“排序输出中相等元素的输入顺序”(来自维基百科)。但是,sort_index 为您提供了选择“mergesort”的选项,这是一种稳定的排序算法。所以我原来的回答,
df2.sort_values(by='val').sort_index()
,有效,只是偶然。这段代码应该每次都有效,因为它使用了稳定的排序算法:
df2.sort_values(by='val').sort_index(kind = 'mergesort')
关于python - Pandas 按值排序,然后按索引排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33699555/