【问题标题】:How to reorder columns in a Pandas dataframe based on other dataframe columns如何根据其他数据框列重新排序 Pandas 数据框中的列
【发布时间】:2020-10-02 19:48:19
【问题描述】:

假设这些数据帧:

import pandas as pd

df_one = pd.DataFrame({'col_1':[1, 2, 3, 4], 'col_2':[5,6,7,8], 'col_3':[9,10,11,12]})
df_two = pd.DataFrame({'col_1':[1, 2, 3, 4], 'col_3': [9,10,11,12], '2_col':[5, 6, 7, 8]})

实际上,这些数据框来自不同的 txt 文件,因此每列的概念是相同的,但列的顺序不同,并且某些列的名称略有不同。两个数据集都有 33 列代表相同的概念,但顺序不同。

如何以与第一个 df 相同的结构重新排序第二个 df?表示与 df_one 相同的列顺序和相同的列名...

最终目标是将两个 df 合并为一个合并的。

我试过这个:

cols = df_one.columns.to_list()  # get columns names from df_one
df_two = df_two.reindex(columns=cols)

但这会在 'col_2' 中获得 NaN 值:

col_1   col_2   col_3
0   1   NaN 9
1   2   NaN 10
2   3   NaN 11
3   4   NaN 12

我也尝试先更改 df_two 中的 col 名称,然后重新排序:

df_two.columns = cols
df_two = df_two.reindex(columns=cols)

但这也是错误的(col_2 现在具有 col_3 的值):

col_1   col_2   col_3
0   1   9   5
1   2   10  6
2   3   11  7
3   4   12  8

感谢您的建议。

根据评论进行编辑:

实际的列名更像是:“Date”和“iDate”、“Contract”和“nContract”、“Premium”和“iPremium”。我以问题中的数字为例(可能是个坏主意),但相关数字不是名称的一部分。

如何映射 df_two 中的列顺序? (例如,df_1 的 col 1 与 df_2 中的 col 1 相同,df_1 的 col 2 是 df_2 的 col_3,df_1 的 col_3 是 df_2 的 col_2) - 然后我将 df_2 中的列重命名为 df_1 中的列。

【问题讨论】:

  • 首先重命名列,使df_onedf_two 具有相同的列名(使用df_one.rename(columns={'col_one':'col_two', ...}))。然后df_one[df_two.columns] 将完成这项工作。
  • 列之间的共同点是什么,都是编号的吗?
  • 所以,我最终按照@pythonic833 的建议手动重命名列(实际上将名称赋予 read_csv 函数中的 'name' 参数,然后将两个 dfs 与 pd.concat 连接起来。

标签: python pandas dataframe


【解决方案1】:

我认为所有列名都至少有一个数字,因此,您可以根据数字订购 df_two,然后重命名列。你可以试试这样的:

import pandas as pd
import re
df_one = pd.DataFrame({'col_1':[1, 2, 3, 4], 'col_2':[5,6,7,8], 'col_3':[9,10,11,12]})
df_two = pd.DataFrame({'col_1':[1, 2, 3, 4], 'col_3': [9,10,11,12], '2_col':[5, 6, 7, 8]})


print('df_two old:\n\n',df_two,'\n')  

def findnum(col):
    return int(re.findall('\d+',col)[0])

df_two =df_two[sorted(df_two.columns, key=findnum)]
df_two.columns=df_one.columns

print('df_two new: \n')
print(df_two)

输出:

df_two old:

    col_1  col_3  2_col
0      1      9      5
1      2     10      6
2      3     11      7
3      4     12      8 

df_two new: 

   col_1  col_2  col_3
0      1      5      9
1      2      6     10
2      3      7     11
3      4      8     12

如果你的常用参数像你说的'Contract' & 'ContractNum',你可以试试这样:

import pandas as pd
df_one = pd.DataFrame({'Contract':[1, 2, 3, 4], 'Date':[5,6,7,8], 'Provider':[9,10,11,12]})
df_two = pd.DataFrame({'iDate':[1, 2, 3, 4], 'ContractNum': [9,10,11,12], 'nProvider':[5, 6, 7, 8]})

print('df_one:\n', df_one,'\n')
print('df_two:\n', df_two,'\n')

def func(pal):
    for i,val in enumerate(df_one.columns):
        if val.lower() in pal.lower():
            return int(i)

df_two=df_two[sorted(df_two.columns, key=func)]
print('df_two sorted: ')
print(df_two,'\n')
df_two.columns=df_one.columns

print('df_two new colnames: ')
print(df_two,'\n')

输出:

df_one:
    Contract  Date  Provider
0         1     5         9
1         2     6        10
2         3     7        11
3         4     8        12 

df_two:
    iDate  ContractNum  nProvider
0      1            9          5
1      2           10          6
2      3           11          7
3      4           12          8 

df_two sorted: 
   ContractNum  iDate  nProvider
0            9      1          5
1           10      2          6
2           11      3          7
3           12      4          8 

df_two new colnames: 
   Contract  Date  Provider
0         9     1         5
1        10     2         6
2        11     3         7
3        12     4         8

【讨论】:

  • 这是一个很好的答案,但名字只是一个例子(可能很糟糕)。实际名称更像是“Contract”和“ContractNum”、“Date”和“iDate”、“Provider”和“nProvider”。
  • 好的,我刚刚编辑了我对那个案例的回答,@naccode。希望它会有所帮助。
【解决方案2】:

如果数字是列之间的公共参数,我们可以提取它们并将它们传递给.map 函数,然后使用自定义字典重新分配它们。

df_two.columns = df_two.columns.str.extract("(\d+)")[0].map(
    {col.split("_")[1]: col for col in df_one.columns}
).tolist()
#{'1': 'col_1', '2': 'col_2', '3': 'col_3'} <- dict
#['col_1', 'col_3', 'col_2'] <- map output that we re-assign.

print(df_two)

   col_1  col_3  col_2
0      1      9      5
1      2     10      6
2      3     11      7
3      4     12      8

那你可以merge/concatpd.concat([df_one,df_two])

【讨论】:

    【解决方案3】:

    我们可以的

    df[['col_2','col_3']]=-np.sort(-df[['col_2','col_3']].values,axis=1)
    df
       col_1  col_2  col_3
    0      1      9      5
    1      2     10      6
    2      3     11      7
    3      4     12      8
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-12
      • 1970-01-01
      • 2017-01-03
      • 2020-03-16
      相关资源
      最近更新 更多