【问题标题】:Merge Multiple CSV with different column name but same definition合并具有不同列名但定义相同的多个 CSV
【发布时间】:2019-04-20 21:34:45
【问题描述】:

我有类似数据集的不同来源 (CSV),我想将它们合并为单个数据并将其写入我的数据库。由于数据来自不同的来源,他们在 CSV 中使用不同的标题,我想将这些列与逻辑含义合并。

到目前为止,我已经尝试先读取所有标题并重新读取文件以首先将所有数据放在一个数据框中,然后执行 if else 以将具有相同含义的列合并在一起。理想情况下,我想创建一个映射文件,每列包含所有可能的列名,然后使用该映射读取 CSV。数据在文件之间没有排序或排序。列数也可能不同,但它们都有我感兴趣的列。

样本数据:
文件 1:
id、名称、total_amount...
1、“测试”,123..

文件 2:
member_id,tot_amnt,名称
2,“test2”,1234 ..

我希望这个看起来像

id、名称、total_amount...
1、“测试”、123...
2、“test2”、1234...
...

我想不出一种优雅的方式来做到这一点,如果能得到一些指导或帮助,那就太好了。

谢谢

【问题讨论】:

  • 如果架构相同且顺序保持不变,只需将新的标头列表分配给df.columns?
  • 然后您就可以使用pd.mergepd.concat,请参阅this post... 中的“合并多个DataFrames”部分。
  • 架构相同,但顺序从一个文件更改为另一个文件。我认为您指向我的帖子可能会起作用,检查我是否可以使它起作用。谢谢

标签: python python-3.x pandas numpy


【解决方案1】:

使用skiprowsheader=None 跳过标题,使用names 指定您自己的列名列表,使用concat 合并到单个df。即

import pandas as pd

pd.concat([
    pd.read_csv('file1.csv',skiprows=1,header=None,names=['a','b','c']),
    pd.read_csv('file2.csv',skiprows=1,header=None,names=['a','b','c'])]
)

编辑:如果不同的文件仅在列顺序上有所不同,您可以为names 指定不同的列顺序,如果您想选择列的子集,请使用usecols。但是你需要提前做这个映射,要么通过探测文件,要么通过其他规则。

这需要以某种方式将文件映射到处理程序

file1.csv

id, name, total_amount
1, "test", 123

file2.csv

member_id, tot_amnt, ignore, name
2, 1234, -1, "test2"

以下选择常见的3列并重命名/重新排序。

import pandas as pd

pd.concat([
    pd.read_csv('file1.csv',skiprows=1,header=None,names=['id','name','value'],usecols=[0,1,2]),
    pd.read_csv('file2.csv',skiprows=1,header=None,names=['id','value','name'],usecols=[0,1,3])],
    sort=False
)

编辑 2:

一个很好的应用方法是使用 lambda 和映射 - 即

parsers = {
   "schema1": lambda f: pd.read_csv(f,skiprows=1,header=None,names=['id','name','value'],usecols=[0,1,2]),
   "schema2": lambda f: pd.read_csv(f,skiprows=1,header=None,names=['id','value','name'],usecols=[0,1,3]) 
}

map = {
    "file2.csv": "schema2",
    "file1.csv": "schema1"}

pd.concat([parsers[v](k) for k,v in map.items()], sort=False)

【讨论】:

  • 如果我的列没有在不同的工作表之间排序,这将如何工作
  • 不会。您的示例以相同的顺序排列它们 - 如果不是这种情况,您可能应该更新问题以更清楚地表明不同文件中的列顺序不同。
  • 我已经更新了答案,但我认为没有真正优雅的方法来做到这一点
  • 我同意,我认为这是迄今为止我见过的最干净的解决方案。感谢你的帮助。谢谢
【解决方案2】:

这是我最终做的,并发现是最干净的解决方案。感谢大卫的帮助。

dict1= {'member_number': 'id', 'full name': 'name', …}
dict2= {'member_id': 'id', 'name': 'name', …}
parsers = {
   "schema1": lambda f, dict: pd.read_csv(f,index_col=False,usecols=list(dict.keys())),
   "schema2": lambda f, dict: pd.read_csv(f,index_col=False,usecols=list(dict.keys())) 
}      
map = {
    'schema1': (a_file.csv,dict1),
    'schema2': (b_file.csv,dict2)
}
total = []
for k,v in map.items():
    d = parsers[k](v[0], v[1])
    d.rename(columns=v[1], inplace=True)
    total.append(d)
final_df = pd.concat(total, sort=False)

【讨论】:

    猜你喜欢
    • 2020-11-17
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    • 1970-01-01
    • 2015-01-25
    • 2021-10-04
    相关资源
    最近更新 更多