将一个文件中的一列与另一文件中的所有列进行比较

将一个文件中的一列与另一文件中的所有列进行比较

我有两个文件。文件 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

自从位于标签中,这是一个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))

相关内容