簡體   English   中英

Pandas 根據 2 個數據幀中不同的列數(2 和 1)合並兩個文件時出錯

[英]Pandas error in merging two files based on different number of columns (2 and 1) in 2 dataframes

我有兩個文件,其結構如下:

df1

intA,intB
4933401J01Rik,Gm37180
Gm37686,Gm37363

df2

chr,gene_type,gene_symbol
chr1,TEC,4933401J01Rik
chr2,TEC,Gm37180
chr3,TEC,Gm37363
chr4,TEC,Gm37686

我正在嘗試合並這兩個文件。 所以基本上我需要從df2中提取df1intAintB列的信息。 在最終的 output 中,對於df1的每一列,應該有兩個額外的列報告基於df2chrgene_type 最終的 output 應該是這樣的:

結果

intA,intB,chr,chr,gene_type,gene_type
4933401J01Rik,Gm37180,chr1,chr2,TEC,TEC
Gm37686,Gm37363,chr4,chr3,TEC,TEC

我運行此代碼,但出現錯誤Can only merge Series or DataFrame objects, a <class 'str'> was passed

df1 = pd.read_csv(df1)
df2 = pd.read_csv(df2)

   
result = pd.merge(df1, df2, how='left', left_on=['intA','intB'], right_on = ['gene_symbol'])

print(result)

感謝您的幫助 - 謝謝。

您可以按照慣用的/熊貓風格的方式進行操作,如下所示:

由於您打算將df1中 2 列( intAintB )的內容與另一個 dataframe df2合並,並且僅在一列( gene_symbol )上匹配,因此您不能直接合並它們。 這是因為要匹配的列數不同。 將導致錯誤ValueError: len(right_on) must equal len(left_on)

相反,您必須先將intAintB兩列轉換為一列,然后在合並之前先將它們的內容放在不同的行中。

1. 將df1intAintB組合成一列,內容在不同的行中:

df1a = df1.copy()
df1a.columns = df1a.columns.str.split(r'(int)', expand=True)   # split column labels
df1a = df1a.droplevel(level=0, axis=1)
df1a = df1a.stack().rename_axis(index=['index', 'int_type']).reset_index()

2. 合並來自df1的新列int (組合intAintB )和df2gene_symbol

現在,我們可以合並 2 個數據框中相同數量的列:

df_merge = pd.merge(df1a, df2, how='left', left_on='int', right_on='gene_symbol')

# remove column 'gene_symbol' which has same duplicated info as 'int'
df_merge2 = df_merge.drop('gene_symbol', axis=1)    

3. Pivot 將intAintB放回2個單獨的列:

df_out = df_merge2.pivot(index='index', columns='int_type')

df_out.columns = df_out.columns.map(''.join)       # combine column labels 

結果:

print(df_out)

                intA     intB  chrA  chrB gene_typeA gene_typeB
index                                                          
0      4933401J01Rik  Gm37180  chr1  chr2        TEC        TEC
1            Gm37686  Gm37363  chr4  chr3        TEC        TEC

可能有一種更像熊貓的方式來做到這一點,但這會做你想做的:

import pandas as pd

df1 = pd.read_csv('a')
df2 = pd.read_csv('b')

df3 = pd.DataFrame(columns=['intA', 'intB', 'chrA', 'chrB', 'gene_typeA', 'gene_typeB'])

for index, row in df1.iterrows():
    aMatch = df2.loc[df2['gene_symbol'] == row['intA']]
    bMatch = df2.loc[df2['gene_symbol'] == row['intB']]
    
    if aMatch.empty or bMatch.empty:
        # malformed data somehow
        print("malformed data")

    
    df3 = df3.append( { 'intA': row['intA'], 
                        'intB': row['intB'],
                        'chrA': aMatch['chr'].values[0], 
                        'chrB': bMatch['chr'].values[0],
                        'gene_typeA': aMatch['gene_type'].values[0],
                        'gene_typeB': bMatch['gene_type'].values[0]
                      }, ignore_index=True)

結果:

            intA     intB  chrA  chrB gene_typeA gene_typeB
0  4933401J01Rik  Gm37180  chr1  chr2        TEC        TEC
1        Gm37686  Gm37363  chr4  chr3        TEC        TEC

暫無
暫無

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

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