두 개의 파일이 있습니다. 파일 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 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
매칭이 더 쉬울거에요좋아요열 대신. 예를 들어 다음을 사용하여 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
이를 사용하여 행렬에 있는 벡터의 열 벡터 뺄셈을 수행한 다음 모든 행이 0인 위치를 계산하는 것을 고려할 수 있습니다.
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))