簡體   English   中英

如何基於其他 dataframe 列對 Pandas dataframe 中的列重新排序

[英]How to reorder columns in a Pandas dataframe based on other dataframe columns

假設這些數據幀:

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合並為一個合並的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'。 我以問題中的數字為例(可能是個壞主意),但相關數字不是名稱的一部分。

我怎樣才能 map 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_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)

Output:

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')

Output:

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

我們可以做的

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

如果數字是列之間的公共參數,我們可以提取它們並將它們傳遞到.map function 然后使用自定義字典重新分配它們。

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 / concat pd.concat([df_one,df_two])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM