我有两个文件。文件 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位于标签中,这是一个Pythonic解决方案,仅使用Python 3的stdlib并使用numpy
.核心numpy
是用C实现的,所以在大数据数组的操作上比纯python要快很多。
标准库
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
可用,您可以考虑使用它,您可以在其中对矩阵中的向量进行列向量减法,然后对所有行为零的位置进行计数:
x = dlmread('File1',' ');
A = dlmread('File2',' ');
sum(all(~(A-x)))
这对于大文件可能更有效 - 如果您需要以非交互方式运行它,您可以使用此处文档从 shell 中执行此操作:
$ 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))