如何排序格式错误的pandas Dataframe列?

时间:2017-02-26 02:44:32

标签: python sorting pandas dataframe

我有一个超过10000列的pandas Dataframe。这些列需要按顺序排序。通常这很简单:

import numpy as np
import pandas as pd
df = pd.read_csv("...*.csv")
df.reindex_axis(sorted(df.columns), axis=1)  # sort the columns of the dataframe

对于我的Dataframe df,这些列中的每一列都是以下格式的字符串:

sampleFIRSTNUMBER_SECONDNUMBER

e.g。 sample42_5864183439sample3_8976711222

编辑:作为示例数据框,

df = pd.DataFrame([[1,2,3,4, 5], [5, 6, 7, 8, 9], [9, 10, 11, 12, 13]],columns=['sample1_5','sample10_5','sample100_5','sample1_50', 'sample111_500'])
print(df)

   sample1_5  sample10_5  sample100_5  sample1_50  sample111_500
0          1           2            3           4              5
1          5           6            7           8              9
2          9          10           11          12             13

我遇到的问题是排序值的经典问题:目前,sample10_####位于sample1_####之前。

对于" SECONDNUMBER"也是如此,即10000在1之前,在10之前等等。 也就是说,chr10_10001目前排在chr10_11之前。

我如何正确地格式化这些列,以便" FIRSTNUMER"和" SECONDNUMBER"都按顺序排序?我认为此列不是sample1_5,而是sample01_000005格式。手动为这个大小的数据集重新注释这些列名称是不可行的; for循环解析每个数字可能在算法上很困难。

是否有正确的大熊猫友好方式重新格式化这些列? (或者我可能不正确地使用排序?)

2 个答案:

答案 0 :(得分:3)

v = df.columns.str.extract('^\D+(\d+)_(\d+)$', expand=True).values.astype(int)

df.iloc[:, np.lexsort(v.T[::-1])]

enter image description here

答案 1 :(得分:2)

您可以extractzfill一起使用,axis=1sort_index进行排序更好:

df = pd.DataFrame([[1,2,3,4]],columns=['sample1_5','sample10_5','sample100_5','sample1_50'])
df = df.sort_index(axis=1)
print (df)
   sample100_5  sample10_5  sample1_5  sample1_50
0            3           2          1           4

df1 = df.columns.to_series().str.extract('([a-z]+)(\d+)_(\d+)', expand=True)
df1[1] = df1[1].str.zfill(3) 
df1[2] = df1[2].str.zfill(2)
df1['new'] = df1.apply(lambda x: '{}{}_{}'.format(x[0],x[1],x[2]), axis=1)
print (df1)
                  0    1   2           new
sample100_5  sample  100  05  sample100_05
sample10_5   sample  010  05  sample010_05
sample1_5    sample  001  05  sample001_05
sample1_50   sample  001  50  sample001_50

df.columns = df1['new']
df.columns.name = None
print (df)
   sample100_05  sample010_05  sample001_05  sample001_50
0             3             2             1             4

print (df.sort_index(axis=1))
   sample001_05  sample001_50  sample010_05  sample100_05
0             1             4             2             3