【问题标题】:Order MultiIndex columns by string and number in pandas在 Pandas 中按字符串和数字对 MultiIndex 列进行排序
【发布时间】:2020-11-19 12:48:54
【问题描述】:

我有一个 pandas 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

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

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 

一切都会有帮助!

【问题讨论】:

  • 请张贴您预期输出的视觉效果

标签: pandas string sorting numbers multi-index


【解决方案1】:

您可以使用正则表达式提取数字,转换为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  

【讨论】:

    【解决方案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
    

    【讨论】:

      【解决方案3】:

      让我们试试natsorted

      from natsort import natsorted
      df=df.reindex(columns=natsorted(df.columns.tolist(), key=lambda element: (element[0], element[1])))
      Out[126]: 
                a                      ...         b                    
             p1_1      p1_2      p9_1  ...      p9_1     p10_1     p11_1
      0  0.122500  0.339663  0.880657  ...  0.258351  0.777972  0.824912
      1  0.506081  0.947983  0.502101  ...  0.626606  0.187132  0.344037
      2  0.465429  0.688159  0.396115  ...  0.840099  0.750303  0.932954
      [3 rows x 10 columns]
      

      【讨论】:

      • 谢谢!但是你能告诉我这到底是怎么工作的吗?
      • @ezrabloemendaal 检查 natsorted 是什么stackoverflow.com/questions/29580978/…,它会对字符串进行排序并考虑数字和字符串的混合,之后您可以像正常排序一样使用它~
      猜你喜欢
      • 2018-07-02
      • 2016-01-23
      • 1970-01-01
      • 2021-06-10
      • 2012-04-03
      • 2016-04-08
      • 1970-01-01
      • 2018-08-22
      相关资源
      最近更新 更多