2つのファイルがあります。ファイル1には単一の列形式のパターンがあり、これをファイル2のすべての列と比較して、最終的にファイル2の列数にパターンが表示されるかどうかを計算したいと思います。ファイル2の列数が非常に多い(約300,000列)。 Unixソリューションがこのように大量の列を処理する最良の方法であるかどうかはわかりません。 awk を使用して、ファイル 1 の列 1 をファイル 2 の特定の列と一致させる方法のみを調べることができます。ファイル1の列1をファイル2のすべての列とどのように比較しますか?
例: ファイル 1
0
0
0
0
1
1
0
0
0
0
ファイル2:
0 0 0 0
0 0 0 1
0 0 0 0
0 0 0 1
0 1 1 0
0 0 1 1
0 1 0 0
0 0 0 0
0 0 0 0
0 0 0 1
一致する列を別々のファイルに保存し、この新しいファイルの列数を計算したいと思います。したがって、上記の例では、ファイル2の列3のみがファイル1と一致し、出力は新しいファイルの列3になり、数は1になります。
答え1
~からPythonタグ内のこれはPython 3のstdlibのみを使用しますnumpy
。numpy
標準ライブラリ
with open('needle') as f:
needle = [int(line.strip()) for line in f]
with open('haystack') as f:
haystack = [[int(val) for val in line.strip().split()] for line in f]
# transpose
haystack = [list(row) for row in zip(*haystack)]
count = haystack.count(needle)
indices = [i for i, row in enumerate(haystack) if row == needle]
print('count:', count)
print('indices:', indices)
numpy
import numpy
needle = numpy.loadtxt('needle', dtype=int)
haystack = numpy.loadtxt('haystack', dtype=int).transpose()
match = (haystack == needle).all(-1)
count = numpy.count_nonzero(match)
indices = numpy.where(match == 1)[0]
print('count:', count)
print('indices:', indices)
テストデータ
テストのために、次のジェネレータを使用して1,000,000列1と0を生成しました。
import numpy
arr = numpy.random.choice([0, 1], size=(10, 1000000))
mat = numpy.matrix(arr)
with open('generated', 'wb') as f:
for line in mat:
numpy.savetxt(f, line, fmt='%i', delimiter='\t')
測定時間:
$ uname -a
Linux localhost 3.10.103-g35adc8d #1 SMP PREEMPT Wed Jun 27 20:11:35 UTC 2018 aarch64 GNU/Linux
$ time python search_stdlib.py >/dev/null
real 0m16.326s
user 0m14.867s
sys 0m0.617s
$ time python search_numpy.py >/dev/null
real 0m11.006s
user 0m10.487s
sys 0m0.307s
答え2
マッチングが簡単です。いいね列の代わりに。たとえば、次のように2つのrs
ファイルの内容を置き換える場合
$ rs -T <File1 | grep -Ff- <(rs -T <File2) | rs -T
0
0
0
0
1
1
0
0
0
0
ファイルに保存せずに発生回数を数えるには、次のようにしますgrep -c
。
$ rs -T <File1 | grep -cxFf- <(rs -T <File2)
1
あるいは、可能であれば、octave
これを使用して行列内のベクトルの列ベクトルを減算し、すべての行がゼロの位置を計算することを検討できます。
x = dlmread('File1',' ');
A = dlmread('File2',' ');
sum(all(~(A-x)))
これは、大容量ファイルの場合より効率的です。非対話式で実行する必要がある場合は、ここでドキュメントを使用してシェルで実行できます。
$ octave --no-gui --norc --quiet << \EOF
x = dlmread('File1','\t');
A = dlmread('File2','\t');
sum(all(~(A-x)))
EOF
(コメントに従って区切り文字がタブに変更されました。)
使用しているOctaveのバージョンが互換性のあるサイズの配列の暗黙的な拡張をサポートしていない場合は、変更する必要があります。 A-x
誰にでも bsxfun(@minus,A,x)
または A-repmat(x,1,size(A,2))