【问题标题】:Merge two CSV files using bash/python使用 bash/python 合并两个 CSV 文件
【发布时间】:2020-08-22 00:52:29
【问题描述】:

我有两个 CSV 文件需要帮助映射/合并:

CSV 文件 1:

"ID","Name","Flavor"
"45fc754d-6a9b-4bde-b7ad-be91ae60f582","test1","m1.medium"
"83dbc739-e436-4c9f-a561-c5b40a3a6da5","test2","m1.tiny"
"ef68fcf3-f624-416d-a59b-bb8f1aa2a769","test3","m1.medium"

CSV 文件 2:

"Name","RAM","Disk","VCPUs"
"m1.medium",4096,40,2
"m1.xlarge",16384,160,8
"m1.tiny",128,1,1

理想的输出是:

"ID","Name","Flavor","RAM","Disk","VCPUs"
"45fc754d-6a9b-4bde-b7ad-be91ae60f582","test1","m1.medium",4096,40,2
"83dbc739-e436-4c9f-a561-c5b40a3a6da5","test2","m1.tiny",128,1,1
"ef68fcf3-f624-416d-a59b-bb8f1aa2a769","test3","m1.medium",4096,40,2

请注意,CSV 文件 1 中的 Flavor 和 CSV 文件 2 中的 Name 相同。名称上的差异是由于用于提取信息的工具不同造成的。

另请注意,CSV File2 有一个 flavor/name m1.xlarge。如上所述,如果在 CSV File1 中未找到 m1.xlarge flavor/name,则应将其从合并输出中丢弃。

我整天都在做这件事,结果好坏参半。任何想法将不胜感激。

【问题讨论】:

  • 你的问题是你没有指定除'mapping/merging'以外的操作。您是否只是在 CSV2 中搜索第一个(?)也有“m1.medium”的行?还是最后一次? CSV2 中的第一个字段是唯一的吗?等等。我想为 /yourself/ 指定“映射/合并”操作至少完成了 50% 的工作。
  • 到底是什么问题?请更具体。请参阅How to Ask、help center。
  • @Javier 您希望 CSV 在名称/风味列上加入,还是将所有列合并到一个文件中,将行保留在原处?

标签: python bash shell csv export-to-csv


【解决方案1】:

你可以使用这个awk:

awk -v hdr='"ID","Name","Flavor","RAM","Disk","VCPUs"' 'BEGIN {
   FS=OFS=","
   print hdr
}
NR == FNR {
   a[$1] = $2 FS $3 FS $4
   next
}
$3 in a {
   print $0, a[$3]
}' file2.csv file1.csv

"ID","Name","Flavor","RAM","Disk","VCPUs"
"45fc754d-6a9b-4bde-b7ad-be91ae60f582","test1","m1.medium",4096,40,2
"83dbc739-e436-4c9f-a561-c5b40a3a6da5","test2","m1.tiny",128,1,1
"ef68fcf3-f624-416d-a59b-bb8f1aa2a769","test3","m1.medium",4096,40,2

【讨论】:

    【解决方案2】:

    类似这样,但您必须使用引用选项才能看到您喜欢什么。

    #!/usr/bin/env python3
    
    import csv
    
    by_name = {}
    with open('b.csv') as b:
        for row in csv.DictReader(b):
            name = row.pop('Name')
            by_name[name] = row
    
    with open('c.csv', 'w') as c:
        w = csv.DictWriter(c, ['ID', 'Name', 'Flavor', 'RAM', 'Disk', 'VCPUs'])
        w.writeheader()
    
        with open('a.csv') as a:
            for row in csv.DictReader(a):
                try:
                    match = by_name[row['Flavor']]
                except KeyError:
                    continue
    
                row.update(match)
    
                w.writerow(row)
    

    输出:

    ID,Name,Flavor,RAM,Disk,VCPUs
    45fc754d-6a9b-4bde-b7ad-be91ae60f582,test1,m1.medium,4096,40,2
    83dbc739-e436-4c9f-a561-c5b40a3a6da5,test2,m1.tiny,128,1,1
    ef68fcf3-f624-416d-a59b-bb8f1aa2a769,test3,m1.medium,4096,40,2
    

    【讨论】:

      【解决方案3】:

      如果我正确理解了您的问题并且您希望根据Flavor 列中的字符串将第一个文件中的行与第二个csv 中Name 列中具有该值的行进行匹配,那么这个使用xsv 很容易做到(你可能需要install first):

      $ xsv join "Flavor" file1.csv "Name" file2.csv
      ID,Name,Flavor,Name,RAM,Disk,VCPUs
      45fc754d-6a9b-4bde-b7ad-be91ae60f582,test1,m1.medium,m1.medium,4096,40,2
      83dbc739-e436-4c9f-a561-c5b40a3a6da5,test2,m1.tiny,m1.tiny,128,1,1
      ef68fcf3-f624-416d-a59b-bb8f1aa2a769,test3,m1.medium,m1.medium,4096,40,2
      

      您还必须删除重复的 Name 列,您可以再次使用 xsv 执行此操作:

      $ xsv join "Flavor" file1.csv "Name" file2.csv | xsv select ID,Name,Flavor,RAM,Disk,VCPUs
      ID,Name,Flavor,RAM,Disk,VCPUs
      45fc754d-6a9b-4bde-b7ad-be91ae60f582,test1,m1.medium,4096,40,2
      83dbc739-e436-4c9f-a561-c5b40a3a6da5,test2,m1.tiny,128,1,1
      ef68fcf3-f624-416d-a59b-bb8f1aa2a769,test3,m1.medium,4096,40,2
      

      【讨论】:

        猜你喜欢
        • 2013-04-22
        • 2020-11-22
        • 2017-09-06
        • 2020-03-18
        • 2012-08-12
        • 2019-02-22
        • 2019-03-27
        • 1970-01-01
        • 2019-12-21
        相关资源
        最近更新 更多