Python 读入并合并或合并多个文件到公共ID列上的一个数据帧中

Python 读入并合并或合并多个文件到公共ID列上的一个数据帧中,python,pandas,csv,Python,Pandas,Csv,我试图在一个目录中连接多个文件。我能够连接文件,但是我得到了重复的行和列。如果输入文件中不存在字段,则输出文件最好显示NaN或null 理想情况下,输出如下所示: Merged.csv ItemID Price Discount ItemName Desc Barcode 0 1 4 2.0 Toy For kids 667865 1 2 10 1.0 Game

我试图在一个目录中连接多个文件。我能够连接文件,但是我得到了重复的行和列。如果输入文件中不存在字段,则输出文件最好显示NaN或null

理想情况下,输出如下所示:

Merged.csv

   ItemID  Price  Discount ItemName          Desc  Barcode
0       1      4       2.0      Toy      For kids   667865
1       2     10       1.0     Game    For adults   998364
2       3      8       NaN      NaN  For everyone    43831
file1.csv

   ItemID  Price  Discount
0       1      4       2.0
1       2     10       1.0
2       3      8       NaN
文件2.csv

   ItemID ItemName          Desc
0       1      Toy      For kids
1       2     Game    For adults
2       3      NaN  For everyone
文件3.CSV

   ItemID  Barcode
0       1   667865
1       2   998364
2       3    43831
以下是我正在编写的代码:

import glob , os
import pandas as pd

path = '/location/test/'
all_files = glob.glob(os.path.join(path, "*.csv"))
pd.concat([pd.read_csv(f, sep=';').assign(file=os.path.basename(f)) for f in all_files]).to_csv('merged.csv', index=False)
  • 您可以将
    axis=1
    传递到
    pd.concat
    并使用
    。设置索引('ItemID')
    ,以便
    ItemID
    上的
    concat
    。最后只需重置索引()
  • 您可以使用
    merge
    functools
    中使用
    reduce
  • 我更喜欢前者,因为前者稍微干净一点,但我会加入
    reduce
    解决方案,以防性能更高,或者您想使用
    独有的一些附加功能。merge

    import pandas as pd
    import glob , os
    
    path = 'Downloads\\'
    base_file = os.path.join(path, "EVS1CPP.csv")
    all_files = glob.glob(os.path.join(path, "*1CPP.csv"))
    all_files.remove(base_file)
    df_base = pd.read_csv(base_file, sep=';').set_index('ARTICLE_ID')
    dfs = pd.concat([pd.read_csv(f, sep=';').set_index('ARTICLE_ID') for f in all_files], axis=1)
    df = df_base.join(dfs, how='outer').rename_axis('ARTICLE_ID').reset_index()
    df
    
    设置:

    import glob , os
    import pandas as pd
    from functools import reduce
    
    path = '/location/test/'
    all_files = glob.glob(os.path.join(path, "*.csv"))
    
    方法1*(请参见答案末尾关于此方法的注释):

    方法2:

    (reduce(lambda  left,right: pd.merge(left,right,on=['ItemID'], how='left'),
        [pd.read_csv(f, sep=';') for f in all_files]).to_csv('merged.csv', index=False))
    
    .csv文件中的输出如下所示:

    Out[1]:
    
       ItemID  Price  Discount ItemName          Desc  Barcode
    0       1      4       2.0      Toy      For kids   667865
    1       2     10       1.0     Game    For adults   998364
    2       3      8       NaN      NaN  For everyone    43831
    
    对于方法#1,这不是一个通用的解决方案,因为所有数据帧中都存在用于连接数据的同一列。例如,如果您有一个具有非唯一值的基文件,您正试图将其他具有唯一值的数据连接到该基文件,则其他文件将连接在一起,但该基文件不会连接到其他文件,您将收到一个
    ValueError
    。下面,我首先阅读基本文件。然后I
    concat
    除基本文件外的所有其他文件。然后,我将基本文件和其他文件与
    join
    一起联接,但是如果键中存在非唯一值,则pd.concat将不起作用,因此最好使用
    join
    merge

    import pandas as pd
    import glob , os
    
    path = 'Downloads\\'
    base_file = os.path.join(path, "EVS1CPP.csv")
    all_files = glob.glob(os.path.join(path, "*1CPP.csv"))
    all_files.remove(base_file)
    df_base = pd.read_csv(base_file, sep=';').set_index('ARTICLE_ID')
    dfs = pd.concat([pd.read_csv(f, sep=';').set_index('ARTICLE_ID') for f in all_files], axis=1)
    df = df_base.join(dfs, how='outer').rename_axis('ARTICLE_ID').reset_index()
    df
    

    与concat在arguments.IIUC中使用pd.merge和pass on=ItemID不同,您需要一个merge或join
    try pd.merge(left,right,on='ItemID')
    这是否回答了您的问题@r_hudson希望这行代码如下:``pd.merge(how=“right”,on='ITEM_ID'[pd.read_csv(f,sep=”)。在所有文件中为f分配(file=os.path.basename(f))。到_csv('merged.csv',index=False)``感谢您对每个方法的解释!