2つの大きなCSVファイル(それぞれ90 GB)を比較し、別のCSVに出力します。

2つの大きなCSVファイル(それぞれ90 GB)を比較し、別のCSVに出力します。

これはあなたのフォローアップの質問です。大容量CSVファイル(90 GB)をソート中にディスククォータを超えました。。これで、file1.csvやfile2.csvなど、2つのCSVファイルが並べ替えられます。各CSVファイルには、次の4つの列があります。

ファイル1:

ID Date Feature Value
01 0501 PRCP    150
01 0502 PRCP    120
02 0501 ARMS    5.6
02 0502 ARMS    5.6

ファイル2:

ID Date Feature Value
01 0501 PRCP    170
01 0502 PRCP    120
02 0501 ARMS    5.6
02 0502 ARMS    5.6

理想的には、2つのファイルの2行に同じID、日付、および機能がありますが、値が異なる場合、出力は2つのファイルを次のように比較したいと思います。

ID Date Feature Value1 Value2

もちろん、この要件はやや高いかもしれません。それはまるで

ID1 Date1 Feature1 Value1       ID2 Date2 Feature2 Value2

また動作します。上記の例で出力したいと思います。

01 0501 PRCP    150 170

または

01 0501 PRCP    150 01 0501 PRCP    150

このように比較する方法とcsvファイルに出力する方法が最大の問題のようです。ありがとうございます。

Gillesの答えの出力例:commの出力は次のとおりです。

$ head -20 comm_output.txt ACW00011604,19490101,PRCP,0 AE000041196,20070402,TAVG,239 AE000041196,20070402,TAVG,244 AE000041196,20080817,TMIN,282 AE000041196,20130909,TAVG,350 AE000041196,20130909,TMAX,438 AE000041196,20130909,TMIN,294 AE000041196,20130910,TAVG,339 AE000041196,20130910,TAVG,341 AE000041196,20150910,TAVG,344awkの出力は次のようになります。

$ head awk_output.csv , ACW00011604,19490101,PRCP,0,,, AE000041196,20070402,TAVG,239,,, AE000041196,20070402,TAVG,244,,, AE000041196,20080817,TMIN,282,,, AE000041196,20130909,TAVG,350,,, AE000041196,20130909,TMAX,438,,, AE000041196,20130909,TMIN,294,,, AE000041196,20130910,TAVG,339,,, AE000041196,20130910,TAVG,341,,, AE000041196,20150910,TAVG,344,,, 主張する場合、サンプル入力は次のようになります。

head file1.csv

ACW00011604,19490101,PRCP,0 ACW00011604,19490101,SNOW,0 ACW00011604,19490101,SNWD,0 ACW00011604,19490101,TMAX,289 ACW00011604,19490101,TMIN,217 ACW00011604,19490102,PRCP,30 ACW00011604,19490102,SNOW,0 ACW00011604,19490102,SNWD,0 ACW00011604,19490102,TMAX,289 ACW00011604,19490102,TMIN,228

 head file2.csv

ACW00011604,19490101,SNOW,0 ACW00011604,19490101,SNWD,0 ACW00011604,19490101,TMAX,289 ACW00011604,19490101,TMIN,217 ACW00011604,19490102,PRCP,30 ACW00011604,19490102,SNOW,0 ACW00011604,19490102,SNWD,0 ACW00011604,19490102,TMAX,289 ACW00011604,19490102,TMIN,228 ACW00011604,19490102,WT16,1

ベストアンサー1

2つのファイルを1行ずつ結合するツールを見てみましょう。

  • 生地内容を気にせずに2つのファイルを1行ずつ結合します。
  • コミュニケーションソートされたファイルをマージし、同じ行を記録します。これにより同じ行を消去できますが、異なる行を結合するには別のツールが必要です。
  • 参加するソートされたファイルを結合して同じフィールドに一致させます。
  • タイプ2つのファイルをマージできます。
  • awkは、ユーザーが指定した規則に従って複数のファイルを結合できます。しかし、このような大きなファイルでは、汎用ツールではなく、最も適切なプロフェッショナルツールを使用すると、最高のパフォーマンスが得られます。

重複がないと仮定します。つまり、同じID、日付、および機能を持つ2つの行が1つのファイルに存在しません。重複項目がある場合、処理方法は処理方法によって異なります。また、ファイルがソートされていると仮定します。私もあなたの殻プロセスの交換、通常のshの代わりにbashまたはkshのようなもので、GNU coreutilsがあります(含まれていないLinuxおよびCygwinの場合)。

区切り文字が空白なのかタブなのかわかりません。空白があるとします。区切り文字が常に正確にタブの場合、タブを区切り記号(cut -d $'\t'、、、)として宣言し、代わりに\ tを使用するとパフォーマンスがわずかに低下します。join -t $'\t'sort -t $'\t'[ \t]\+

LC_ALL=Cマルチバイト文字に関連するパフォーマンスの低下を防ぐには、ロケールを通常のASCII()に設定します。

行は1つのフィールドに基づいてのみ結合できるため、フィールドjoin1〜3を単一のフィールドにまとめる必要があります。これを行うには、区切り文字を1と2の間、2と3の間、3と4の間に変更します。スペースを置き換えるために1-3を変更します;。これにより、同じかどうかに関係なく、すべての行の組み合わせを取得できます。その後、sedを使用して同じ値を持つ行を削除できます。

join -a 1 -a 2 <(sed 's/[ \t]\+/;/; s/[ \t]\+/;/' file1.csv) <(sed 's/[ \t]\+/;/; s/[ \t]\+/;/' file2.csv) |
sed '/[ \t]\(.*\)[ \t]\+\1$/d' |
tr ';' '\t'

ペアリングできない行は4列の行で終わり、その行がファイル1にあるかファイル2にあるかは表示されません。ペアリングできないすべての回線を抑制するには、削除してください-a 1 -a 2

ほとんど同じ行がある場合、それをリンクして消去するのに時間がかかります。別の方法は、をcomm -3使用して同じ行を消去することです。これにより、行は順番に並べ替えられますが、ファイル2の行には前のタブを持つ出力ストリームが生成されます。その後、awkを使用して、同じフィールド1〜3を持つ2つのファイルの連続した行をマージできます。これにはawkが含まれているため、他の行が多いと遅くなる可能性があります。

comm -3 file1.csv file2.csv |
awk '
    $1 "\t" $2 "\t" $3 == k { if ($4 != v) print k "\t" v "\t" $4; next; }
    { print k "\t" v }
    { k=$1 "\t" $2 "\t" $3; v=$4; }
'

おすすめ記事