將 CSV 與一些共享列連接起來
我有兩個大文件~9GB。CSV 文件 1 有列
A, B, C, D, E
,CSV 文件 2 有列B, C, F, G
。所需的輸出是A, B, C, D, E, F, G
。我所能找到的只是加入相似的列並與相同的列連接,但是這裡有些匹配,有些不匹配。範例輸出看起來類似於以下內容:A B C D E F G 1 2 3 4 5 6 7 NaN 1 2 NaN 1 2 1
因此,如果該列的值不存在,因為它不存在,我只希望它有一個
NaN
值。我希望我已經很好地解釋了這個問題。謝謝!編輯:通常我會這樣做,
Python
但是這些龐大的文件使得迭代塊然後在最後連接起來更加煩人。似乎有一種bash
我不知道的更直接的使用方式。謝謝!
這基於以下事實:
(a)所有欄位都嚴格用製表符分隔
(b)兩個文件(B 和 C)中的公共列具有相同的值
$ join --nocheck-order -eNaN -13 -22 -t$'\t' -o 1.1 1.2 1.3 1.4 1.5 2.3 2.4 b.txt c.txt A B C D E F G 1 2 3 4 5 6 7 NaN 1 2 NaN 1 2 1
文件樣本:
$ cat b.txt A B C D E 1 2 3 4 5 1 2 1 $ cat c.txt B C F G 2 3 6 7 1 2 2 1
連接選項:
-13 -22:連接基於 file1 column3 (C) = file2 column2 (C)
-t$’\t’:輸入和輸出的製表符分隔符
-o:輸出格式。1.1 表示 file1、column1 等。
-e :用 NaN 填充空值
有關更多資訊,請參閱
man join
甚至更好info join
AWK 的替代解決方案
PS:在 awk 中請耐心等待,我是 awk 的新學習者。
$ awk -F"\t" '{a[1]="";{for (i=1;i<=NF;i++) if (i==6 ||i==7) continue;else \ if ($i!="") a[1]=a[1]FS$i;else a[1]=a[1]FS"NaN";print a[1]}}' <(paste b.txt c.txt)
更新逗號分隔的輸入欄位
正如您在評論中所建議的那樣,由於 csv 文件由逗號分隔,因此此解決方案將用逗號分隔輸入欄位,並將使用選項卡輸出結果以提高可讀性。
awk 'BEGIN {FS=",";OFS="\t"}{a[1]="";{for (i=1;i<=NF;i++) if (i==6 ||i==7) continue;else \ if ($i!="") a[1]=a[1]OFS$i;else a[1]=a[1]OFS"NaN";print a[1]}}' <(paste b.txt c.txt)
如果您還需要用逗號列印輸出,只需將 begine 部分替換為
{FS=OFS=","}
儘管仍不清楚您打算如何處理公共列/不同的值。
您可以移除零件
if (i==6 ||i==7) continue;else
以查看結果是否符合您的需求。此條件檢查實際上跳過了欄位 6(文件 2 的 B 列)和欄位 7(文件 2 的 C 列),因為到目前為止,文件 2 的這兩列被認為與文件 1 的列相同。對於連接解決方案:
替換
-t$'\t'
為-t','
以讀取逗號分隔的欄位對於常見的列,您可以使用此輸出格式:
join --nocheck-order -eNaN -13 -22 -t',' -o 1.1 1.2 2.1 1.3 2.2 1.4 1.5 2.3 2.4 b.txt c.txt