如何重新排列Pandas列的顺序?

31
>>> df =DataFrame({'a':[1,2,3,4],'b':[2,4,6,8]})
>>> df['x']=df.a + df.b
>>> df['y']=df.a - df.b
>>> df
   a  b   x  y
0  1  2   3 -1
1  2  4   6 -2
2  3  6   9 -3
3  4  8  12 -4

现在我想重新排列列的顺序,通过将'x','y'列作为第一和第二列:

>>> df = df[['x','y','a','b']]
>>> df
    x  y  a  b
0   3 -1  1  2
1   6 -2  2  4
2   9 -3  3  6
3  12 -4  4  8

但是如果我有很多列 'a','b','c','d'......,而且我不想显式地列出这些列。我该怎么办?

或者Pandas是否提供像set_column_sequence(dataframe,col_name,seq)这样的函数,以便我可以执行:set_column_sequence(df,'x',0)set_column_sequence(df,'y',1)

6个回答

50

你也可以像这样做:

df = df[['x', 'y', 'a', 'b']]

您可以使用以下方法获取列列表:

cols = list(df.columns.values)

输出的结果将类似于这样:

['a', 'b', 'x', 'y']

然后很容易在将其放入第一个函数之前手动重新排列


4
对于像我一样的新手,重新排列从cols获取的list。然后执行df=df[cols],也就是重新排列的列表被插入到第一个表达式中而不仅仅是一对括号。 - Sid
你能解释一下第一个例子吗? - Delrius Euphoria

12

可能有一个优雅的内置函数(但我还没有找到)。您可以编写一个函数:

# reorder columns
def set_column_sequence(dataframe, seq, front=True):
    '''Takes a dataframe and a subsequence of its columns,
       returns dataframe with seq as first columns if "front" is True,
       and seq as last columns if "front" is False.
    '''
    cols = seq[:] # copy so we don't mutate seq
    for x in dataframe.columns:
        if x not in cols:
            if front: #we want "seq" to be in the front
                #so append current column to the end of the list
                cols.append(x)
            else:
                #we want "seq" to be last, so insert this
                #column in the front of the new column list
                #"cols" we are building:
                cols.insert(0, x)
return dataframe[cols]

例如: set_column_sequence(df, ['x','y']) 将返回所需的输出。

如果您想要序列位于 DataFrame 的末尾,只需传入“front=False”参数即可。


希望我能找到Pandas内置的“set_column_sequence(df,col_list,assign_col_seq)”函数,这样我就可以使用“set_column_sequence(df,['x','y'],[0,1])”来完成任务。 - bigbug
希望如此!如果我找到了,我会更新我的回答...在那之前,这应该可以工作。 - Andy Hayden
怎么样加入一个列表推导式的版本来提高速度? - pylang
@pylang 我不认为这会加速它(我认为这不是主要的性能问题),但一个好的编写方式是:s = {col: i for i, col in enumerate(first_cols)}; sorted(df.columns, key=lambda c: s.get(c, len(s)))。即使到现在(4年后)这仍然有点笨拙,我想也许有一个用sort_index的技巧,但似乎并没有。嗯 - Andy Hayden
@pylang 可能可以这样做:df[df.columns[df.columns.map(lambda col: s.get(col, len(s))).argsort()]] 但是这样很丑陋。虽然比旧答案好,所以我可能会编辑它... - Andy Hayden

7
你可以做以下事情:
df =DataFrame({'a':[1,2,3,4],'b':[2,4,6,8]})

df['x']=df.a + df.b
df['y']=df.a - df.b

您可以按照以下方式自由创建列标题,顺序不限:

column_titles = ['x','y','a','b']

df.reindex(columns=column_titles)

这将为您提供所需的输出。

我的首选方式是因为它可以与数据框的其他方法链接使用。 - Rabeez Riaz

3
def _col_seq_set(df, col_list, seq_list):
    ''' set dataframe 'df' col_list's sequence by seq_list '''
    col_not_in_col_list = [x for x in list(df.columns) if x not in col_list]
    for i in range(len(col_list)):
        col_not_in_col_list.insert(seq_list[i], col_list[i])

    return df[col_not_in_col_list]
DataFrame.col_seq_set = _col_seq_set

1
我建议您编写一个函数来执行您所说的操作,可能使用drop(删除列)和insert(在位置插入列)。目前没有现成的API函数可以实现您所描述的功能。

0

如果原索引的顺序很重要,那么可以放心地忽略这个解决方案,因为从列表中减去一个索引不会保留原始索引的顺序。

In [61]: df.reindex(columns=pd.Index(['x', 'y']).append(df.columns - ['x', 'y']))
Out[61]: 
    x  y  a  b
0   3 -1  1  2
1   6 -2  2  4
2   9 -3  3  6
3  12 -4  4  8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接