按熊猫中的字符串和数字对MultiIndex列进行排序

时间:2020-07-29 20:25:26

标签: pandas string sorting numbers multi-index

我有一个熊猫multiIndex数据框,我想按名称和编号进行排序。

以类似的数据集df为例创建:

random= np.random.rand(3,10)
a = [ 'a','b','a','b','a','b','a','b','a', 'b']
b = ['p11_1','p11_1','p1_1','p1_1','p9_1','p9_1','p10_1','p10_1','p1_2','p1_2']
arrays = [a,b]
df = pd.DataFrame(data = random, columns = arrays)

标题层如下:

   a         b         a  ...         b         a         b
  p11_1     p11_1      p1_1  ...     p10_1      p1_2      p1_2

我可以使用简单的sort命令,但是会导致错误的输出:

df = df.sort_index(axis=1)

标题层如下:

      a                      ...         b                    
  p10_1     p11_1      p1_1  ...      p1_1      p1_2      p9_1

这对两层都进行排序,但是第二层不是所需的输出。

所需的输出按如下顺序排列第二层:

p1_1 < p1_2 < p9_1 < p10_1 < p11_1  

而不是:

p10_1 < p11_1 < p1_1 < p1_2 < p9_1 

有什么用!

3 个答案:

答案 0 :(得分:2)

您可以使用正则表达式提取数字,转换为int并排序:

import re
new_cols = sorted(df.columns, key=lambda x: (x[0],)+tuple(map(int, re.findall('(\d+)', x[1])) ))

df = df[new_cols]

输出:

          a                                                 b            \
       p1_1      p1_2      p9_1     p10_1     p11_1      p1_1      p1_2   
0  0.573945  0.648582  0.018916  0.349072  0.242901  0.672357  0.264832   
1  0.362348  0.046961  0.245218  0.971988  0.337589  0.868794  0.357096   
2  0.653817  0.882649  0.103931  0.778984  0.777559  0.056299  0.252898   

                                 
       p9_1     p10_1     p11_1  
0  0.645881  0.633993  0.340431  
1  0.908928  0.527769  0.862013  
2  0.302780  0.497609  0.378155  

答案 1 :(得分:2)

考虑到您需要自然排序第二级,可以致电numpy.lexsort

get_level = df.columns.get_level_values
idx = np.lexsort((
    get_level(1).str.extract(f'p(\d+)', expand=False).astype(int), get_level(0)))

df.iloc[:, idx]     

          a                      ...         b                    
       p1_1      p1_2      p9_1  ...      p9_1     p10_1     p11_1
0  0.879848  0.384629  0.006705  ...  0.296052  0.716751  0.790975
1  0.139579  0.158237  0.737015  ...  0.702624  0.356452  0.557185
2  0.335480  0.133805  0.040322  ...  0.161040  0.622088  0.219986

答案 2 :(得分:2)

让我们尝试Stackoverflow

natsorted