如何设置MultiIndex的排序顺序



我有这样的数据帧:

import pandas as pd
import numpy as np
np.random.seed(123)
col_num = 1
row_num = 18
col_names = ['C' + str(x) for x in range(col_num)]
mix = pd.MultiIndex.from_product([['a', 'b'], [ '01 Jan 2011', '02 Feb 2000', '30 Apr 1999'], [1,2,3]])
df = pd.DataFrame(np.round(((np.random.rand(row_num,col_num)* 2 - 1)*100),2), columns = col_names, index = mix)
#df
                    C0
a 01 Jan 2011 1  39.29
              2 -42.77
              3 -54.63
  02 Feb 2000 1  10.26
              2  43.89
              3 -15.38
  30 Apr 1999 1  96.15
              2  36.97
              3  -3.81
b 01 Jan 2011 1 -21.58
              2 -31.36
              3  45.81
  02 Feb 2000 1 -12.29
              2 -88.06
              3 -20.39
  30 Apr 1999 1  47.60
              2 -63.50
              3 -64.91

如何对MultiIndex进行排序,使级别1上的日期按时间顺序保持,同时保持其他混合级别上的排序,包括级别排序的优先级(即:首先是级别0,然后是级别1,最后是级别2(。

我需要在最后的df中把日期作为字符串。最后的df将被腌制。我尝试在序列化之前设置日期的排序顺序,而不是在检索df之后编写排序函数。

让我们在设置映射到datetimelevel 1值后创建一个新的MultiIndex,然后在这个新索引上使用argsort来获得将对原始数据帧进行排序的索引:

idx = df.index.set_levels(pd.to_datetime(df.index.levels[1]), 1)
df1 = df.iloc[np.argsort(idx)]

print(df1)
                     C0
a 30 Apr 1999  1  96.15
               2  36.97
               3  -3.81
  02 Feb 2000  1  10.26
               2  43.89
               3 -15.38
  01 Jan 2011  1  39.29
               2 -42.77
               3 -54.63
b 30 Apr 1999  1  47.60
               2 -63.50
               3 -64.91
  02 Feb 2000  1 -12.29
               2 -88.06
               3 -20.39
  01 Jan 2011  1 -21.58
               2 -31.36
               3  45.81

如果想要创建所需的带有排序索引的df,并且不介意使用分类索引,这里有一个实现它的代码(可能有更简单的方法,但我找不到:(。

从上面问题的df开始。

from datetime import datetime as dt
org_l1 = df.index.get_level_values(1).unique().tolist()
l1_as_date = [dt.strptime(x, '%d %b %Y') for x in org_level1]
l1_as_date.sort()
l1_sorted_as_str = [dt.strftime(x, '%d %b %Y') for x in l1_as_date]
df= df.reset_index()
df.level_1 = df.level_1.astype('category')
df.level_1 = df.level_1.cat.set_categories(l1_sorted_as_str, ordered=True)
df = df.set_index(['level_0', 'level_1', 'level_2'])
df.sort_index(inplace=True)

最新更新