使用多个键连接两个文本文件

使用多个键连接两个文本文件

我有两组数据。我想通过两个键值(storm_ID,Cell_ID)将它们连接起来。

第一个数据集如下:

Storm_ID,Cell_ID,Wind_speed 
2,10236258,27 
2,10236300,58 
2,10236301,25 
3,10240400,51

第二个数据集如下:

Storm_ID,Cell_ID,Storm_surge 
2,10236299,0.27 
2,10236300,0.27 
2,10236301,0.35 
2,10240400,0.35 
2,10240401,0.81 
4,10240402,0.11

现在我想要一个类似这样的输出:

Storm_ID,Cell_ID,Wind_speed,Storm_surge 
2,10236258,27,0 
2,10236299,0,0.27 
2,10236300,58,0.27 
2,10236301,25,0.35 
2,10240400,0,0.35 
2,10240401,0,0.81 
3,10240400,51,0 
4,10240402,0,0.11

我尝试在 Linux 中使用 join 命令来执行此任务,但失败了。Join 命令跳过了数据库中不匹配的行。我可以使用 Matlab,但数据大小超过 100 GB,这使得这项任务非常困难。有人可以指导我吗?我可以使用 SQL 或 python 来完成此任务吗?

答案1

使用 awk 和 sort:

awk -F, -v OFS=, '{x = $1 "," $2} FNR == NR {a[x] = $3; b[x] = 0; next} {b[x] = $3} !a[x] {a[x] = 0} END {for (i in a) print i, a[i], b[i]}' f1 f2 | sort -n
  • -F, -v OFS=,- 将输入和输出设置为,
  • {x = $1 "," $2}保存前两个用 分隔的字段,,因为组合是公共索引。
  • FNR == NR {a[x] = $3; b[x] = 0; next}-FNR是每个文件的记录数,NR是跨文件的总记录数。对于第一个文件,它们是相等的,因此此块仅针对第一个文件运行。在这里,我将第一个文件的第三列保存在数组中a,并将相应的条目初始化b为 0。然后我跳到下一个记录。
  • {b[x] = $3} !a[x] {a[x] = 0}- 这两个是针对第二个文件运行的,将第三列保存在中b,如果在中没有相应的条目a,则将其设置为 0。
  • END {for (i in a) print i, a[i], b[i]}在两个文件的末尾,打印迄今为止获得的每一条记录

由于 awk 中循环数组会产生随机顺序,因此我们需要在最后使用以下命令对输出进行排序sort -n

$ awk -F, -v OFS=, '{x = $1 "," $2} FNR == NR {a[x] = $3; b[x] = 0; next} {b[x] = $3} !a[x] {a[x] = 0} END {for (i in a) print i, a[i], b[i]}' f1 f2 | sort -n
Storm_ID,Cell_ID,Wind_speed,Storm_surge
2,10236258,27,0
2,10236299,0,0.27
2,10236300,58,0.27
2,10236301,25,0.35
2,10240400,0,0.35
2,10240401,0,0.81
3,10240400,51,0
4,10240402,0,0.11

答案2

可能join如果您将前两个字段合并为一个键,将逗号分隔符替换为一个您确定不会出现在数据中的字符,则可以做到这一点。请注意,由于join要求在连接字段上对数据进行排序,因此只有在这样做不会改变数据的词汇顺序时,这才会起作用。

例如:

$ join -t, -a1 -a2 -e0 -o0,1.2,2.2 <(sed 's/,/;/' file1) <(sed 's/,/;/' file2) | sed 's/;/,/'
Storm_ID,Cell_ID,Wind_speed,Storm_surge
2,10236258,27,0
2,10236299,0,0.27
2,10236300,58,0.27
2,10236301,25,0.35
2,10240400,0,0.35
2,10240401,0,0.81
3,10240400,51,0
4,10240402,0,0.11

相关内容