Compare uma coluna de um arquivo com todas as colunas em outro arquivo

0

Eu tenho dois arquivos. O arquivo 1 tem um padrão na forma de uma única coluna que eu quero comparar com todas as colunas no arquivo 2 para, finalmente, contar quantas colunas no arquivo 2 mostram esse padrão. O número de colunas no arquivo 2 é muito grande (~ 300.000 colunas). Não tenho certeza se a solução Unix é a melhor maneira de lidar com esse grande número de colunas. Eu só fui capaz de descobrir como corresponder a coluna 1 do arquivo 1 com uma coluna específica no arquivo 2 usando o awk. Como faço para comparar a coluna 1 no arquivo 1 a todas as colunas no arquivo 2?

Exemplo: Arquivo 1

0
0
0
0
1
1
0
0
0
0

Arquivo 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

Gostaria de armazenar as colunas correspondentes em um arquivo separado e contar o número de colunas nesse novo arquivo. Portanto, para o exemplo acima, somente a coluna 3 do arquivo 2 corresponde ao arquivo 1 e a saída seria a coluna 3 em um novo arquivo e a contagem seria 1.

    
por user210432 02.07.2018 / 22:30

2 respostas

0

Será mais fácil combinar linhas do que as colunas. Então, por exemplo, usando rs para transpor o conteúdo de ambos os arquivos

$ rs -T <File1 | grep -Ff- <(rs -T <File2) | rs -T
0
0
0
0
1
1
0
0
0
0

Para contar ocorrências, não é necessário salvá-las em um arquivo - você pode usar grep -c :

$ rs -T <File1 | grep -cxFf- <(rs -T <File2)
1

Ou se octave estiver disponível, você pode considerar usar isso, onde é possível fazer uma subtração em vetor em coluna do vetor a partir da matriz e, em seguida, contar onde todas as linhas são zero:

x = dlmread('File1',' ');
A = dlmread('File2',' ');
sum(all(~(A-x)))

Isso pode funcionar melhor para arquivos grandes - se você precisar executá-lo de forma não interativa, poderá fazê-lo, por exemplo, a partir do shell usando um documento here:

$ octave --no-gui --norc --quiet << \EOF
x = dlmread('File1','\t');
A = dlmread('File2','\t');
sum(all(~(A-x)))
EOF

(delimitadores alterados para guias com base em comentários).

Se a sua versão do Octave não suportar a expansão implícita de matrizes com tamanhos compatíveis, talvez seja necessário alterar A-x para bsxfun(@minus,A,x) ou A-repmat(x,1,size(A,2))

    
por 02.07.2018 / 23:03
1

Como as estão nas tags, aqui está uma solução pythonic, usando Somente o stdlib do Python 3 e usando numpy . O núcleo de numpy é implementado em C, portanto, é muito mais rápido em operações em grandes matrizes de dados do que em Python puro.

stdlib

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)

Dados de teste

Para teste, geramos 1.000.000 de colunas de uns e zeros com o seguinte gerador:

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')

Tempo de medição:

$ 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
    
por 03.07.2018 / 18:07

Tags