【问题标题】:Create new DataFrame as ordered mix of columns of other DataFrames创建新的 DataFrame 作为其他 DataFrame 的列的有序组合
【发布时间】:2017-06-28 09:57:58
【问题描述】:

我有这种数据帧

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]

谢谢!

【问题讨论】:

    标签: python pandas dataframe merge reshape


    【解决方案1】:

    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
    

    【讨论】:

    • 绝妙的拉链创意!
    【解决方案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
    

    【讨论】:

    • 谢谢,但不幸的是它不适用于真实世界的列名。生病在第一篇文章中添加信息。
    【解决方案3】:

    您可以使用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
    

    【讨论】:

    • 嗨! pd.concat 有助于逐帧连接,我需要像我的示例中那样逐列完成(a aa aaa b bb bbb c cc ccc)
    • @AlexeyTrofimov 您希望列名的顺序不同吗?
    • @AlexeyTrofimov 你的意思是不管列名是什么?
    • 啊,我看到了你的版本。是的,不管。它只是一个例子,不幸的是,sorted(columns) 在某些情况下不起作用。我在开始帖子中添加了一种方法来使用您的 pd.concat 想法。
    【解决方案4】:

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

    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.

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

    df[name]= df1[name]

    就够了。

    【讨论】:

      猜你喜欢
      • 2016-02-10
      • 2021-12-30
      • 2014-02-09
      • 2020-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 2019-10-17
      相关资源
      最近更新 更多