用键值连接两个 csv 文件

Posted

技术标签:

【中文标题】用键值连接两个 csv 文件【英文标题】:join two csv files with key value 【发布时间】:2014-11-10 14:13:05 【问题描述】:

我有两个 csv 文件,我想使用键值(城市的列)加入它们。

一个csv文件,d01.csv有这种形式,

Barcelona, 19.5, 29.5
Tarragona, 20.4, 31.5 
Girona, 17.2, 32.5
Lleida, 16.5, 33.5 
Vic, 17.5, 31.4

另一个,d02.csv,具有下一个结构,

City, Data, TMax, TMin
Barcelona, 20140916, 19.9, 28.5
Tarragona, 20140916, 21.4, 30.5  
Lleida, 20140916, 17.5, 32.5 
Tortosa, 20140916, 20.5, 30.4

我需要一个新的 csv 文件,其中有一列城市出现在 2 个 csv 文件中。

City, Tmin, Tmax, Date, Tmin1, Tmax1
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5
Tarragona, 20.4, 31.5, 20140916, 21.4, 30.5
Girona, 17.2, 32.5, 20140916, 17.5, 32.5
Lleida, 16.5, 33.5, 20140916, 20.5, 30.4

我试图这样做

join -j 2 -t ',' d01.csv d02.csv | awk -F "," 'print $1, $2, $3, $4, $5 > d03.csv

但它不完整...我如何订购键值?

【问题讨论】:

这些是实际文件中的前导数字吗?该连接命令的输出是什么?作为此过程的一部分,您是否真的试图反转 TminTmax 列顺序? d01.csv 真的没有标题行吗? Tmax 值是否应该小于输入文件中的 Tmin 值? @Jotne 我没有进行该编辑,因为我不确定第一个文件中的前导逗号是否有误。毕竟,OP 在join 命令中使用了-j 2 OP 如果编辑有误,请更正。 【参考方案1】:

下面是如何在 bash 中使用 join:


  echo "City, Tmin, Tmax, Date, Tmin1, Tmax1"
  join -t, <(sort d01.csv) <(sed 1d d02.csv | sort)
 > d03.csv
cat d03.csv
City, Tmin, Tmax, Date, Tmin1, Tmax1
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5
Lleida, 16.5, 33.5 , 20140916, 17.5, 32.5 
Tarragona, 20.4, 31.5 , 20140916, 21.4, 30.5  

请注意,join 仅输出两个文件中都存在键的记录。要获取所有这些,请指定您想要两个文件中的缺失记录,指定您想要的字段,并为缺失的字段提供默认值:

join -t, -a1 -a2 -o 0,1.2,1.3,2.2,2.3,2.4 -e '?' <(sort d01.csv) <(sed 1d d02.csv | sort)
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5
Girona, 17.2, 32.5,?,?,?
Lleida, 16.5, 33.5 , 20140916, 17.5, 32.5 
Tarragona, 20.4, 31.5 , 20140916, 21.4, 30.5  
Tortosa,?,?, 20140916, 20.5, 30.4
Vic, 17.5, 31.4,?,?,?

【讨论】:

史诗般的脚本,谢谢!就我而言,它似乎确实添加了一些杂散的回车(在 vi 中显示为 ^M),但这可能与我的源数据有关。下面的快速 vi 命令可以解决这个问题::%s/\r//g. 该命令不会添加任何回车符。它们可能来自您的输入文件。【参考方案2】:

我建议 CSV Cruncher 将 CSV 文件作为 SQL 表,然后允许 SQL 查询,从而生成另一个 CSV 文件。

例子:

crunch input.csv output.csv \
   "SELECT AVG(duration) AS durAvg FROM (SELECT * FROM indata ORDER BY duration LIMIT 2 OFFSET 6)"

该工具需要 Java 5 或更高版本。

一些优点:

您确实获得了 CSV 支持,而不仅仅是“假设数据正确”。 您可以加入多个键。 比基于join 的解决方案更易于使用和理解。 您可以合并 2 个以上的 CSV 文件。 您可以通过 SQL 表达式连接 - 值不必相同。

免责声明:我编写了该工具。未知的项目状态 - 谷歌代码已关闭,我没有尽快转移它。如果有人感兴趣,我可能会看看它。

【讨论】:

【参考方案3】:

这个awk 可能会:

awk 'FNR==NR a[$1]=$2FS$3FS$4;next $1 in a print $0,a[$1]' OFS=", " d02,csv d01csv
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5
Tarragona, 20.4, 31.5 , 20140916, 21.4, 30.5
Lleida, 16.5, 33.5 , 20140916, 17.5, 32.5

【讨论】:

它也可以运行,但你能解释一下这个结构吗?我会欣赏它 @EnricAgudPique FNR==NR 为第一个文件 d02.csv 运行此操作(将数据从文件存储到数组 a 使用第一个字段作为索引。然后如果在下一个文件中找到第一个字段 @987654326 @print 需要输出。这是处理awk 中两个文件的常用方法。

以上是关于用键值连接两个 csv 文件的主要内容,如果未能解决你的问题,请参考以下文章

.properties属性文件 笔记

如何连接两个csv文件然后按python排序

如何连接两个csv文件?

使用python连接两个CSV文件

根据 Pandas 中的列内容连接两个 csv 文件

如何使用 csv 文件在 XSL 中构建键值对映射?