Combinar duas colunas principais ao mesmo tempo entre arquivos e colar colunas suplementares no arquivo de saída quando essas colunas principais corresponderem

2

Eu tenho 3 arquivos, cada um com um número exclusivo de colunas, todos separados por tabulações, mas algumas colunas são compartilhadas entre os três arquivos. São as colunas compartilhadas entre os três arquivos que eu quero usar para criar algum tipo de arquivo "agregado".

As imagens abaixo mostram exemplos de como os arquivos podem ser. Basicamente, quero corresponder as colunas MAIN1 e MAIN2 entre os arquivos. Ambas as colunas entre os três arquivos precisam corresponder.

Eu quero adicionar a coluna "minor8" do arquivo2 ao lado direito da tabela no arquivo1 para essas linhas quando MAIN1 e MAIN2 entre os dois arquivos corresponderem. Posteriormente, eu quero adicionar "minor9" do arquivo3 no lado direito da tabela file1 para esses casos quando MAIN1 e MAIN2 entre os dois arquivos correspondem. Porque "minor8" deve ir imediatamente ao lado da coluna mais à direita do arquivo1 (nome da coluna: "minor3"), gostaria que "minor9" fosse ao lado de "minor8" no novo arquivo OUTPUT. O arquivo OUTPUT dá uma idéia de como deve ficar o meu arquivo final ideal (embora esse exemplo de OUTPUT tenha algumas inconsistências).

Eu tentei fazer um arquivo de cada vez usando algum comando do awk, mas eu tenho aprendido um pouco sobre o awk desde hoje.

Eu tentei coisas como:

awk 'NR==FNR{a[$1$3]++;next} $1$3 in a {$1$3==$2$3 FS a[$1$3]; print}' file1 file2 > OUTPUT

mas obviamente sem sucesso porque várias coisas provavelmente estão faltando ou são flagrantemente erradas.

E essa linha não levaria o arquivo3 em consideração ainda.

Se alguém tiver sugestões sobre como obter um arquivo OUTPUT usando file1, file2 e file3, isso seria ótimo. Espero aprender com suas sugestões. Se for muito difícil combinar 3 arquivos em um arquivo de saída em um único passo (eu certamente não poderia pensar em como fazer isso), por favor, deixe-me saber como fazer isso para um arquivo de cada vez. Explicações detalhadas são muito bem-vindas.

Muito obrigado!

Com base nos primeiros comentários, percebo que as imagens postadas não ajudaram muito, embora eu tenha obtido uma solução muito útil de um usuário.

Basicamente, estes são exemplos de 3 arquivos (as "guias" são um pouco confusas)

arquivo1:

MAIN1   minor1  MAIN2   minor3
1  bla1    a    blabla1
1  bla2    b    blabla2
1  bla3    c    blabla3
2  bla4    a    blabla4
2  bla5    d    blabla5
3  bla6    e    blabla6
4  bla7    f    blabla7
5  bla8    a    blabla8
5  bla9    g    blabla9

arquivo2:

minor8  MAIN1   MAIN2
yes1    2   d
yes2    3   e
yes3    4   f
yes4    5   a
yes5    5   g
yes6    1   a
yes7    1   b
yes8    1   c
yes9    2   a

arquivo3:

MAIN1   MAIN2   minor9
5   a   sure1
5   g   sure2
1   a   sure3
1   b   sure4
1   c   sure5
2   a   sure6
2   d   sure7
3   e   sure8
4   f   sure9

arquivo OUTPUT desejado:

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1   bla1    a   blabla1 yes6    sure3
1   bla2    b   blabla2 yes7    sure4
1   bla3    c   blabla3 yes8    sure5
2   bla4    a   blabla4 yes9    sure6
2   bla5    d   blabla5 yes1    sure7
3   bla6    e   blabla6 yes2    sure8
4   bla7    f   blabla7 yes3    sure9
5   bla8    a   blabla8 yes4    sure1
5   bla9    g   blabla9 yes5    sure2

O código do G-Man conseguiu recriar esse arquivo OUTPUT, então obrigado G-Man!

Uma coisa que esqueci de mencionar, que seu código não é capaz de fazer (até onde eu vi), é que ele removerá linhas do arquivo1 se não houver correspondência.

Basicamente, preciso manter essas linhas do arquivo 1, mesmo se os arquivos 2 e 3 não tiverem uma correspondência exata entre as colunas MAIN1 e MAIN2. Se não houver correspondência, gostaria apenas de ver uma entrada de coluna vazia para essa combinação específica de MAIN1, MAIN2 ...

Espero que minha maneira de explicar isso seja clara o suficiente.

De qualquer forma, eu aprecio muito a ajuda de vocês. Espero que em algum momento no futuro próximo eu possa contribuir para este fórum, além de simplesmente pedir ajuda ...

Assim, por exemplo (se os arquivos 2 e 3 tiverem 1 combinação ausente de MAIN1, MAIN2, o OUTPUT poderá ter esta aparência):

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1   bla1    a   blabla1 yes6    sure3
1   bla2    b   blabla2 yes7    sure4
1   bla3    c   blabla3         sure5
2   bla4    a   blabla4 yes9    sure6
2   bla5    d   blabla5 yes1    sure7
3   bla6    e   blabla6 yes2    sure8
4   bla7    f   blabla7 yes3    
5   bla8    a   blabla8 yes4    sure1
5   bla9    g   blabla9 yes5    sure2

Você tem alguma sugestão sobre como o código do G-Man deve ser editado para tornar isso possível?

    
por Noobie123 15.12.2015 / 23:13

1 resposta

1

Crie os seguintes arquivos:

merge21 :

BEGIN {
        IFS = "\t"
        OFS = "\t"
}
NR==FNR {               # file2
        key = $2 "," $3
        present[key] = 1
        minor8[key] = $1
        next
}
{                       # file1
        key = $1 "," $3
        if (present[key]) print $1, $2, $3, $4, minor8[key]
}

merge312 :

BEGIN {
        IFS = "\t"
        OFS = "\t"
}
NR==FNR {               # file3
        key = $1 "," $2
        present[key] = 1
        minor9[key] = $3
        next
}
{                       # file1 + file2
        key = $1 "," $3
        if (present[key]) print $1, $2, $3, $4, $5, minor9[key]
}

Eles são quase idênticos; Eu corrijo as diferenças. Agora digite o comando

awk -f merge21 file2 file1 | awk -f merge312 file3 -

Isso pressupõe que nenhum dos seus dados inclui vírgula (s), mas realmente depende apenas de haver alguma string que não aparece nos dados. Seria trivial estender isso para suportar mais colunas; Espero que isso seja óbvio. Isso poderia ser aprimorado para fazer tudo em uma única execução de awk , mas isso seria um pouco mais complexo, e (IMNSHO) não vale o esforço.

Isso produz o que é chamado de “junção interna” dos dados em seus arquivos; consulte Diferença entre o INNER e o OUTER junta-se ao Stack Overflow para algumas definições. Se você quiser mudar isso para uma "junção externa esquerda", que é definida no aceito (e obscenamente votado para cima) responder a essa pergunta como (parafraseado) «todas as linhas na primeira tabela, mais quaisquer linhas comuns na (s) outra (s) tabela (s) », substitua a última instrução em merge21 por

        if (present[key]) print $1, $2, $3, $4, minor8[key]
        else              print $1, $2, $3, $4, "-"

e da mesma forma em merge312 . Supondo que você tenha excluído a linha " 1 c " de file2 e a linha " 4 f " de file4 , sua saída será

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1       bla1    a       blabla1 yes6    sure3
1       bla2    b       blabla2 yes7    sure4
1       bla3    c       blabla3 -       sure5
2       bla4    a       blabla4 yes9    sure6
2       bla5    d       blabla5 yes1    sure7
3       bla6    e       blabla6 yes2    sure8
4       bla7    f       blabla7 yes3    -
5       bla8    a       blabla8 yes4    sure1
5       bla9    g       blabla9 yes5    sure2

e, obviamente, você pode remover os caracteres - com sed . (E, claro, se os dados reais incluírem hífens, escolha algum caractere não usado ou string como o espaço reservado para dados ausentes.)

    
por 16.12.2015 / 13:00