创建新的DataFrame作为其他DataFrames的有序混合列

时间:2017-06-28 09:57:59

标签: python pandas dataframe merge reshape

我有这种DataFrames

import pandas as pd

df1 = pd.DataFrame({'a':[1.1,1.1,1.1], 'b':[2.1,2.1,2.1], 'c':[3.1,3.1,3.1]})
df2 = pd.DataFrame({'aa':[1.2,1.2,1.2], 'bb':[2.2,2.2,2.2], 'cc':[3.2,3.2,3.2]})
df3 = pd.DataFrame({'aaa':[1.3,1.3,1.3], 'bbb':[2.3,2.3,2.3], 'ccc':[3.3,3.3,3.3]})

这些框架总是具有相同的形状(列名称并不总是符合字母顺序)。我想找出在结果框架中组合其列的最佳方法,如下所示:

     a   aa  aaa    b   bb  bbb    c   cc  ccc
0  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
1  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
2  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3

我的方法是嵌套循环并按列填充新的框架:

df_new = pd.DataFrame()

for i in range(df1.shape[1]):
    for df in [df1, df2, df3]:
        df_new[df.columns[i]] = df.iloc[:, i]

print(df_new)

它有效,但我认为有更可靠的方法来做到这一点。

编辑:在pd.concat的帮助下(感谢@Tbaki),还可以完成两个步骤:

df_new = pd.concat([df1,df2,df3],axis=1)

small = df1.shape[1]
big = df_new.shape[1]

#create correct order
new_order = []

for i in range(small):
    new_order.extend(list(range(i, big, small)))

df_new.iloc[:, new_order]

谢谢!

4 个答案:

答案 0 :(得分:3)

IIUC:

In [17]: pd.concat([df1,df2,df3],axis=1) \
           .loc[:, np.concatenate([t for t in zip(df1.columns,df2.columns,df3.columns)])]
Out[17]:
     a   aa  aaa    b   bb  bbb    c   cc  ccc
0  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
1  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
2  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3

答案 1 :(得分:2)

您可以使用concat + sort_index

df = pd.concat([df1,df2,df3],axis=1).sort_index(axis=1)
print (df)
     a   aa  aaa    b   bb  bbb    c   cc  ccc
0  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
1  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
2  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3

稍微改善了另一个答案:

dfs= [df1,df2,df3]
cols = np.concatenate(list(zip(df1.columns,df2.columns,df3.columns)))
df = pd.concat(dfs,axis=1).reindex_axis(cols, axis=1)
print (df)
     a   aa  aaa    b   bb  bbb    c   cc  ccc
0  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
1  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
2  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3

或者:

from  itertools import chain

dfs= [df1,df2,df3]
cols = chain.from_iterable(list(zip(df1.columns,df2.columns,df3.columns)))
df = pd.concat(dfs,axis=1).reindex_axis(cols, axis=1)
print (df)
     a   aa  aaa    b   bb  bbb    c   cc  ccc
0  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
1  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
2  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3

答案 2 :(得分:1)

您可以使用concat然后reindex_axis

df = pd.concat([df1,df2,df3],axis=1)
df.reindex_axis(sorted(df.columns), axis=1)

输出

     a   aa  aaa    b   bb  bbb    c   cc  ccc
0  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
1  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
2  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3

答案 3 :(得分:0)

通过按顺序添加三个数据框中的所有列来创建新数据框。这是解决方案。

import pandas as pd
df1 = pd.DataFrame({'a':[1.1,1.1,1.1], 'b':[2.1,2.1,2.1], 'c':[3.1,3.1,3.1]})
df2 = pd.DataFrame({'aa':[1.2,1.2,1.2], 'bb':[2.2,2.2,2.2], 'cc':[3.2,3.2,3.2]})
df3 = pd.DataFrame({'aaa':[1.3,1.3,1.3], 'bbb':[2.3,2.3,2.3], 'ccc':[3.3,3.3,3.3]})

df = pd.DataFrame()
for i,name in enumerate(df2.columns.values):
    df[df1.columns[i]]= df1[df1.columns[i]]
    df[name]= df2[name]
    df[df3.columns[i]]= df3[df3.columns[i]]
print(df)

输出:

     a   aa  aaa    b   bb  bbb    c   cc  ccc
0  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
1  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3
2  1.1  1.2  1.3  2.1  2.2  2.3  3.1  3.2  3.3

这是您最感兴趣的部分!

for i,name in enumerate(df2.columns.values):
        df[df1.columns[i]]= df1[df1.columns[i]]
        df[name]= df2[name]
        df[df3.columns[i]]= df3[df3.columns[i]]

所以我基本上做的是

df[df1.columns[i]]= df1[df1.columns[i]]

使用df[column_name]创建一个新的数据框,其中column_name df1.columns[i] - > df1.columns[0] - > a

同样的, df3.columns[i] - > df3.columns[0] - > aaa

但是,我使用name从第二个数据框df2获取了列df2.columns.values。所以在这种情况下

df[name]= df1[name]

就够了。