我有两组数据。我想通过两个键值(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