【问题标题】:Sorting columns in pandas dataframe based on column name [duplicate]根据列名对熊猫数据框中的列进行排序[重复]
【发布时间】:2012-06-19 11:44:06
【问题描述】:

我有一个 dataframe 有超过 200 列。问题是它们生成的顺序是

['Q1.3','Q6.1','Q1.2','Q1.1',......]

我需要按如下方式对列进行排序:

['Q1.1','Q1.2','Q1.3',.....'Q6.1',......]

我有什么方法可以在 Python 中做到这一点吗?

【问题讨论】:

  • 该问题顶部有一个横幅“这个问题在这里已经有了答案:如何更改 DataFrame 列的顺序?(34 个答案)去年关闭。”它所说的问题是一个完全不同的问题,因此应该删除此横幅和链接。
  • 我投票重新打开这个问题,我相信它被错误地标记为重复:提供的重复询问如何重新排序列,而这个问题询问如何按列名排序。严格来说,后者的答案是前者的子集,但寻求后者答案的用户不太可能在重复的答案中找到它(提到排序的最高投票答案目前在投票总数中排名第 5)。

标签: python pandas dataframe


【解决方案1】:

你可以这样做:

df[排序(df.columns)]

编辑:较短的是

df[sorted(df)]

【讨论】:

  • 为此我得到“'DataFrame' 对象不可调用”。版本:熊猫 0.14。
  • @lvelin,你知道为什么sorted(df) 有效吗?它在某处有记录吗?
  • @zyxue, sorted 将寻找迭代类 magic methods 来确定要排序的内容。看看这个问题*.com/questions/48868228/…
【解决方案2】:

你还可以做得更简洁:

df.sort_index(axis=1)

确保将结果分配回去:

df = df.sort_index(axis=1)

或者,就地执行:

df.sort_index(axis=1, inplace=True)

【讨论】:

  • 记得按@multigoodverse 做df = df.sort_index(axis=1)
  • 或用df.sort_index(axis=1, inplace=True)就地修改df
  • 另外,sort_indexreindex 快,以防开发人员担心
  • 这应该是公认的答案。
  • 同意@rsmith54,因为此解决方案也适用于重复的列名。
【解决方案3】:
df = df.reindex(sorted(df.columns), axis=1)

这假设对列名进行排序将给出您想要的顺序。如果您的列名不会按字典顺序排序(例如,如果您希望列 Q10.3 出现在 Q9.1 之后),则需要进行不同的排序,但这与 pandas 无关。

【讨论】:

  • 我喜欢这个,因为可以使用相同的方法对行进行排序(我需要对行和列进行排序)。虽然方法相同,但您可以省略 axis 参数(或提供其默认值,0),例如 df.reindex_axis(sorted(non_sorted_row_index)),相当于 df.reindex(sorted(non_sorted_row_index))
  • 请注意,重新索引不是就地完成的,因此要将排序实际应用于 df 您必须使用df = df.reindex_axis(...)。另外,请注意,使用这种方法很容易进行非字典排序,因为列名列表可以单独排序为任意顺序,然后传递给reindex_axis。这对于@Wes McKinney (df = df.sort_index(axis=1)) 建议的替代方法是不可能的,但是对于纯粹的字典排序来说,这种方法更清晰。
  • 不确定 '.reindex_axis' 何时被弃用,请参阅下面的消息。 FutureWarning: '.reindex_axis' 已弃用,将在未来版本中删除。请改用“.reindex”。这与 ipykernel 包是分开的,所以我们可以避免导入,直到
  • 这实际上是对数据框的列进行排序吗?乍一看,这似乎只是对列名进行排序然后重置索引。
  • reindex_axis 已弃用,结果为 FutureWarning。但是,.reindex 工作正常。对于上面的例子,使用df.reindex(columns=sorted(df.columns))
【解决方案4】:

一个用例是您已使用某些前缀命名(某些)列,并且您希望使用这些前缀以某种特定顺序(非字母顺序)对列进行排序。

例如,您可能以Ft_ 开头所有功能,以Lbl_ 开头标签,等等,您首先需要所有不带前缀的列,然后是所有功能,然后是标签。您可以使用以下函数来做到这一点(我会注意到使用sum 来减少列表可能会出现效率问题,但这不是问题,除非您有很多列,而我没有):

def sortedcols(df, groups = ['Ft_', 'Lbl_'] ):
    return df[ sum([list(filter(re.compile(r).search, list(df.columns).copy())) for r in (lambda l: ['^(?!(%s))' % '|'.join(l)] + ['^%s' % i  for i in l ] )(groups)   ], [])  ]

【讨论】:

    【解决方案5】:

    Tweet's answer 可以通过

    传递给上面的 BrenBarn 的答案
    data.reindex_axis(sorted(data.columns, key=lambda x: float(x[1:])), axis=1)
    

    所以对于你的例子,说:

    vals = randint(low=16, high=80, size=25).reshape(5,5)
    cols = ['Q1.3', 'Q6.1', 'Q1.2', 'Q9.1', 'Q10.2']
    data = DataFrame(vals, columns = cols)
    

    你得到:

    data
    
        Q1.3    Q6.1    Q1.2    Q9.1    Q10.2
    0   73      29      63      51      72
    1   61      29      32      68      57
    2   36      49      76      18      37
    3   63      61      51      30      31
    4   36      66      71      24      77
    

    然后做:

    data.reindex_axis(sorted(data.columns, key=lambda x: float(x[1:])), axis=1)
    

    导致:

    data
    
    
         Q1.2    Q1.3    Q6.1    Q9.1    Q10.2
    0    2       0       1       3       4
    1    7       5       6       8       9
    2    2       0       1       3       4
    3    2       0       1       3       4
    4    2       0       1       3       4
    

    【讨论】:

      【解决方案6】:

      对于多个列,您可以按您想要的顺序排列列:

      #['A', 'B', 'C'] <-this is your columns order
      df = df[['C', 'B', 'A']]
      

      此示例显示了对列进行排序和切片:

      d = {'col1':[1, 2, 3], 'col2':[4, 5, 6], 'col3':[7, 8, 9], 'col4':[17, 18, 19]}
      df = pandas.DataFrame(d)
      

      你得到:

      col1  col2  col3  col4
       1     4     7    17
       2     5     8    18
       3     6     9    19
      

      然后做:

      df = df[['col3', 'col2', 'col1']]
      

      导致:

      col3  col2  col1
      7     4     1
      8     5     2
      9     6     3     
      

      【讨论】:

        【解决方案7】:

        如果你需要一个任意序列而不是排序序列,你可以这样做:

        sequence = ['Q1.1','Q1.2','Q1.3',.....'Q6.1',......]
        your_dataframe = your_dataframe.reindex(columns=sequence)
        

        我在 2.7.10 中对此进行了测试,它对我有用。

        【讨论】:

          【解决方案8】:
          print df.sort_index(by='Frequency',ascending=False)
          

          其中by是列的名称,如果要根据列对数据集进行排序

          【讨论】:

            【解决方案9】:

            最快的方法是:

            df.sort_index(axis=1)
            

            请注意,这会创建一个新实例。因此,您需要将结果存储在一个新变量中:

            sortedDf=df.sort_index(axis=1)
            

            【讨论】:

              【解决方案10】:

              不要忘记在 Wes 的答案中添加“inplace=True”或将结果设置为新的 DataFrame。

              df.sort_index(axis=1, inplace=True)
              

              【讨论】:

                【解决方案11】:

                sort 方法和sorted 函数允许您提供自定义函数来提取用于比较的密钥:

                >>> ls = ['Q1.3', 'Q6.1', 'Q1.2']
                >>> sorted(ls, key=lambda x: float(x[1:]))
                ['Q1.2', 'Q1.3', 'Q6.1']
                

                【讨论】:

                • 这通常适用于列表,我很熟悉。如何将其应用于 pandas DataFrame?
                • 不确定,我承认我的回答不是针对这个库的。