Unindo 2 arquivos e comparando-os [fechados]

-2

Eu tenho dois arquivos onde eu quero usar algo como uma junção à esquerda que é usada no SQL.

File1 :

column1  column2  column3  column4
Ab       Cd       100      Us
Ef       Gh       200      Us

File2 :

column1  column2  column3  column4
Ab       Cd       150      Us

Eu quero que o meu resultado fique abaixo. Preciso das 3 colunas do primeiro arquivo e do valor correspondente correspondente do segundo arquivo.

column1  column2  column3  column4 
Ab       Cd       100      150
Ef       Gh       200          

Também é possível obter diferença da saída como column5 ?

    
por user3208078 04.04.2016 / 15:48

2 respostas

2

Estritamente, tenho que concordar que a questão está no limite de uma questão puramente programática.

Ao mesmo tempo: muito tentador e desafiador, como intermediário, não para responder, e já respondemos perguntas como essa antes.

O script

#!/usr/bin/env python3import sys
import sys

files = [[l.split() for l in open(f).readlines()] for f in [sys.argv[1], sys.argv[2]]]
for item in files[0]:
    match = [line for line in files[1] if item[:2] == line[:2]]
    if match:
        try:
            calc = abs(int(int(item[2]) - int(match[0][2])))
            print(("\t").join(item[:3])+"\t"+match[0][2]+"\t", calc)
        except TypeError:
            pass

Como usar

  • Copie o script em um arquivo vazio, salve-o como analyze.py
  • Execute-o com os dois arquivos como argumentos:

    python3 /path/to/analyze.py <file1> <file2>
    

Nos exemplos da sua pergunta:

$ python3 '/home/jacob/Bureaublad/pscript_1.py' '/home/jacob/Bureaublad/map/f2' '/home/jacob/Bureaublad/map/f1' 
Ab  Cd  150 100  50

Explicação

O script:

  • procura linhas nos dois arquivos dos quais as duas primeiras colunas correspondem:

    for item in files[0]:
        match = [line for line in files[1] if item[:2] == line[:2]]
    
  • das linhas correspondentes, as duas primeiras colunas (correspondentes) são impressas, juntamente com as duas versões da terceira coluna .

    if match:
        try:
            calc = abs(int(int(item[2]) - int(match[0][2])))
            print(("\t").join(item[:3])+"\t"+match[0][2]+"\t", calc)
        except TypeError:
            pass
    
  • A diferença (absoluta) das duas últimas colunas é calculada (e impressa finalmente) na linha:

    calc = abs(int(int(item[2]) - int(match[0][2])))
    

O script assume:

  • todas as figuras são inteiros
  • Você não deseja imprimir linhas que não têm as duas primeiras colunas correspondentes
  • Cada uma das linhas tem apenas uma correspondência possível no outro arquivo
por Jacob Vlijm 04.04.2016 / 17:46
0

Usando join :

join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 file2

Se você precisar que o cabeçalho informe column4 no quarto campo:

join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 <(awk 'NR == 1 {$3 = "column4"} 1' file2)
join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 <(
    awk '
        NR == 1 {
            $3 = "column4"
        }
        1
    ' file2
)

Isto assumindo que file1 e file2 são classificados no campo # 1 como no exemplo.

  • --header : trata a primeira linha em cada arquivo como cabeçalhos de campo, imprimindo-os sem tentar emparelhá-los
  • -j1 : junta-se ao campo # 1 de file1 e ao campo # 1 de file2
  • -a1 : também imprime linhas não pareadas do arquivo file1
  • -o 1.1,1.2,1.3,2.3 : imprime os campos # 1, # 2 e # 3 de file1 seguidos pelo campo # 3 de file2
% cat file1
column1  column2  column3  column4
Ab       Cd       100      Us
Ef       Gh       200      Us
% cat file2
column1  column2  column3  column4
Ab       Cd       150      Us
% join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 file2 
column1 column2 column3 column3
Ab Cd 100 150
Ef Gh 200 
% join --header -j1 -a1 -o 1.1,1.2,1.3,2.3 file1 <(awk 'NR == 1 {$3 = "column4"} 1' file2)
column1 column2 column3 column4
Ab Cd 100 150
Ef Gh 200
    
por kos 04.04.2016 / 17:59