Pandas按值排序,然后按索引排序

spa*_*ead 12 python pandas

我有以下数据集:

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
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我想要的是val在每个fac1组内进行排序,以产生这个:

在此输入图像描述

我已经梳理了文档,找不到简单明了的方法.我能做的最好的是以下黑客攻击:

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
Run Code Online (Sandbox Code Playgroud)

(我意识到以上可以从多种inplace选择中受益,只需这样做就可以使中间产品变得清晰).

我找到了这个SO帖子,它使用了分组和排序功能.但是,从该帖子改编的以下代码产生了错误的结果:

df2.groupby("fac1",axis=1).apply(lambda x : x.sort_values("val"))
Run Code Online (Sandbox Code Playgroud)

(出于空间考虑,删除了输出)

还有另一种方法来解决这个问题吗?

更新:解决方案

接受的解决方案是:

df2.sort_values(by='val').sort_index(kind='mergesort')
Run Code Online (Sandbox Code Playgroud)

排序算法必须是mergesort并且必须明确指定,因为它不是默认值.由于sort_index文件指出,"归并是唯一稳定的算法." 这里是不会正确排序,如果你没有指定其他样本数据集mergesortkind:

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()
Run Code Online (Sandbox Code Playgroud)

(省略所有空间考虑的输出)

Sam*_*Sam 15

编辑:我查看了文档,sort_index的默认排序算法是quicksort.这不是一个"稳定"算法,因为它不保留"排序输出中相等元素的输入顺序"(来自维基百科).但是,sort_index为您提供了选择"mergesort"的选项,这是一种稳定的排序算法.所以我的原始答案,

df2.sort_values(by='val').sort_index()
Run Code Online (Sandbox Code Playgroud)

工作,只是偶然.此代码应该每次都有效,因为它使用稳定的排序算法:

df2.sort_values(by='val').sort_index(kind = 'mergesort')
Run Code Online (Sandbox Code Playgroud)

  • 如果对你和我来说,有必要首先对列进行排序,然后对索引进行排序,那么你应该更改排序顺序!例如 `.sort_index().sort_values('A', kind='mergesort')` (3认同)