问题 pandas.concat中的列顺序


我这样做:

data1 = pd.DataFrame({ 'b' : [1, 1, 1], 'a' : [2, 2, 2]})
data2 = pd.DataFrame({ 'b' : [1, 1, 1], 'a' : [2, 2, 2]})
frames = [data1, data2]
data = pd.concat(frames)
data


   a    b
0   2   1
1   2   1
2   2   1
0   2   1
1   2   1
2   2   1

数据列顺序按字母顺序排列。为什么会这样? 以及如何保持原始订单?


10095
2017-08-19 20:06


起源

可能重复 如何更改DataFrame列的顺序? - albert
可能重复 保留列顺序 - Python Pandas和列Concat - ayhan
Dict没有订购,所以为什么要订购这些列? - Merlin


答案:


您正在使用词典创建DataFrame。字典是无序的,这意味着密钥没有特定的顺序。所以

d1 = {'key_a': 'val_a', 'key_b': 'val_b'}

d2 = {'key_b': 'val_b', 'key_a': 'val_a'}

是相同的。

除此之外,我假设pandas默认对字典的键进行排序(不幸的是我没有在文档中找到任何提示以证明该假设)导致您遇到的行为。

因此,基本动机是对DataFrame中的列进行求助/重新排序。你可以这样做 如下

import pandas as pd

data1 = pd.DataFrame({ 'b' : [1, 1, 1], 'a' : [2, 2, 2]})
data2 = pd.DataFrame({ 'b' : [1, 1, 1], 'a' : [2, 2, 2]})
frames = [data1, data2]
data = pd.concat(frames)

print(data)

cols = ['b' , 'a']
data = data[cols]

print(data)

10
2017-08-19 20:18



这会在Python 3.7中“正常工作”吗? Dicts保证维持秩序。 - BallpointBen


您可以使用OrderedDicts创建原始DataFrame

from collections import OrderedDict

odict = OrderedDict()
odict['b'] = [1, 1, 1]
odict['a'] = [2, 2, 2]
data1 = pd.DataFrame(odict)
data2 = pd.DataFrame(odict)
frames = [data1, data2]
data = pd.concat(frames)
data


    b    a
0   1    2
1   1    2
2   1    2
0   1    2
1   1    2
2   1    2

2
2017-08-19 20:28





def concat_ordered_columns(frames):
    columns_ordered = []
    for frame in frames:
        columns_ordered.extend(x for x in frame.columns if x not in columns_ordered)
    final_df = pd.concat(frames)    
    return final_df[columns_ordered]       

# Usage
dfs = [df_a,df_b,df_c]
full_df = concat_ordered_columns(dfs)

这应该工作。


2
2018-01-02 16:57



谢谢,这对我的情况来说很不错,其中DataFrame是从已经存在的CSV文件创建的。 - Jon


你也可以像这样指定顺序:

import pandas as pd

data1 = pd.DataFrame({ 'b' : [1, 1, 1], 'a' : [2, 2, 2]})
data2 = pd.DataFrame({ 'b' : [1, 1, 1], 'a' : [2, 2, 2]})
listdf = [data1, data2]
data = pd.concat(listdf)
sequence = ['b','a']
data = data.reindex(columns=sequence)

0
2017-07-13 10:01