タブで区切られた2つの大きなファイル(> 10 GB)があり、並べ替えるとその内容が同じであることがわかります。
Source
ただし、同じ「キー」(ここでキーは列に基づいてグループ化されたLocation
行として定義されています)を共有するときに、行の順序と置き換えられた行のインデックスに興味があります。
つまり、これら2つのファイル間の行は、同じグループに属している場合にのみ(つまり、同じソースと場所を共有する場合)、互いに比較する必要があります。
たとえば、次の例では、行4、5、6をfile1.tsv
次の行4、5、6と比較する必要があります。file2.tsv
注:ファイルは通常のTSVです。より見やすくするために、ここに余分なスペースを追加し、列を中央に揃えて右に揃えます。このスペースは元のファイルの一部ではありません。
ファイル1.tsv
Identifier Position Source Location
AY1:2301 87 ch1 14
BC1U:4010 105 ch1 14
AC44:1230 90 ch1 15
AJC:93410 83 ch1 16
ABYY:0001 101 ch1 16
ABC:01 42 ch1 16
HH:A9CX 413 ch1 17
LK:9310 2 ch1 17
JFNE:3410 132 ch1 18
MKASDL:11 14 ch1 18
MKDFA:9401 18 ch1 18
MKASDL1:011 184 ch2 50
LKOC:AMC02 18 ch2 50
POI:1100 900 ch2 53
MCJE:09HA 11 ch2 53
ABYCI:1123 15 ch2 53
MNKA:410 1 ch2 53
ファイル2.tsv
Identifier Position Source Location
AY1:2301 87 ch1 14
BC1U:4010 105 ch1 14
AC44:1230 90 ch1 15
ABC:01 42 ch1 16
ABYY:0001 101 ch1 16
AJC:93410 83 ch1 16
HH:A9CX 413 ch1 17
LK:9310 2 ch1 17
MKASDL:11 14 ch1 18
JFNE:3410 132 ch1 18
MKDFA:9401 18 ch1 18
MKASDL1:011 184 ch2 50
LKOC:AMC02 18 ch2 50
MNKA:410 1 ch2 53
POI:1100 900 ch2 53
ABYCI:1123 15 ch2 53
MCJE:09HA 11 ch2 53
「diff」に似ていますが、「グループ」レベルで実行したいです(行がSource
同じ合計を共有している場合にのみ比較されますLocation
)。
抽出したいオリジナル同じ「ソース/位置」内で行の順序が「交換」されると、「行番号」グループ「(またはキー)。
行全体の内容が一致する必要があります。
しかし、どうすればいいのかわかりません。私が考えることができるのはforループを書くことだけです。これは、元のデータセットに数百万の行がある場合、非常に非効率的です。
予想される結果:
Group_Source:Location df1.index df2.index
ch1:16 4 6
ch1:16 6 4
ch1:18 9 10
ch1:18 10 9
ch2:53 14 15
ch2:53 15 17
ch2:53 17 14
仮定:
- 両方のデータフレームは同じ数の行を持ちます。
- 両方のデータフレームは同じです(行の順序のみが変わるため、両方ともソース基準、位置基準、位置基準、識別子基準でソートされている場合はまったく同じです)。
- 「交換された」行は、常にすべての列の内容と正確に一致します。
ベストアンサー1
入力ファイルのサイズのため、これは私が使用できるまれなケースの1つなので、getline
> 10Gの代わりに一度に数行だけメモリに保存します。
$ cat tst.awk
BEGIN {
OFS = "\t"
print "Group_Source:Location", "df1.index", "df2.index"
}
NR != FNR { exit }
{ srcLoc = $3 ":" $4 }
srcLoc != prevSrcLoc {
if ( NR > 1 ) {
diff()
}
prevSrcLoc = srcLoc
}
{
file1[$1,$2] = FNR - 1
if ( (getline < ARGV[2]) > 0 ) {
file2[$1,$2] = FNR - 1
}
}
END { diff() }
function diff( idPos) {
for ( idPos in file1 ) {
if ( file1[idPos] != file2[idPos] ) {
print prevSrcLoc, file1[idPos], file2[idPos]
}
}
delete file1
delete file2
}
$ awk -f tst.awk file1.tsv file2.tsv
Group_Source:Location df1.index df2.index
ch1:16 6 4
ch1:16 4 6
ch1:18 10 9
ch1:18 9 10
ch2:53 17 14
ch2:53 15 17
ch2:53 14 15
もっと情報がgetline
欲しいなら読んでくださいhttp://awk.freeshell.org/AllAboutGetline。
Identifier
上記のコードは、2つのファイル間の4つのフィールドをすべて比較するため、入力中および/または繰り返される場合にも機能します。Position
例の入力に示すように、ソースとロケーションの値が2つのファイル間で同じ順序であるとします。