Mesclando várias tabelas delimitadas por tabulação com base em colunas comuns

2

Sou novo no campo e quero comparar e mesclar 500 arquivos delimitados por tabulações, cada um com duas colunas ("Posição" e "Poli"). Exemplos de arquivo1 e arquivo2 (e outros arquivos) e a saída final que estou procurando são os seguintes -

Arquivo1:

Position Poly
100001  C
228201  T
341791  T
380441  C
392640  T
459055  A
459079  T
480253  T
570405  T
492633  A

Arquivo2:

Position        Poly
100001  C
312002  C
341791  T
380441  C
412640  A
459055  A
459079  T
464056  T
570405  T
492633  A

Saída:

Position        File1 File2
100001  C       C
228201  T       -
312002  -       C
341791  T       T
380441  C       C
392640  T       -
412640  -       A
459055  A       A
459079  T       T
480253  T       -
464056  -       T
570405  T       T
492633  A       A

Basicamente, quero convertê-los em uma matriz única e colocar traço se uma posição estiver faltando em qualquer arquivo.

    
por user68902 29.05.2014 / 09:15

3 respostas

2

A função join do GNU coreutils faz quase o que você quer - não consigo encontrar uma forma de lidar com as omissões de ambos os arquivos de uma só vez, mas

sort -u \
<(join --header --nocheck-order -t$'\t' -a1 -o 1.1,1.2,2.2 -11 -21 -e'-' file1 file2) \ 
<(join --header --nocheck-order -t$'\t' -a2 -o 2.1,1.2,2.2 -11 -21 -e'-' file1 file2)
100001  C       C
228201  T       -
312002  -       C
341791  T       T
380441  C       C
392640  T       -
412640  -       A
459055  A       A
459079  T       T
464056  -       T
480253  T       -
492633  A       A
570405  T       T
Position        Poly    Poly

A linha de cabeçalho é classificada na parte inferior - se isso for um problema, você pode retirá-la passando por sed '$d' ou head -n -1 . Como alternativa, se a saída não classificada for aceitável, você poderá remover duplicatas com awk em vez de sort -u , ou seja,

awk '!a[$1]++' \
<(join --header --nocheck-order -t$'\t' -a1 -o 1.1,1.2,2.2 -11 -21 -e'-' file1 file2) \
<(join --header --nocheck-order -t$'\t' -a2 -o 2.1,1.2,2.2 -11 -21 -e'-' file1 file2)
Position        Poly    Poly
100001  C       C
228201  T       -
341791  T       T
380441  C       C
392640  T       -
459055  A       A
459079  T       T
480253  T       -
570405  T       T
492633  A       A
312002  -       C
412640  -       A
464056  -       T
    
por 29.05.2014 / 16:32
0

Uma solução gawk , trabalha com todos os dois arquivos e você não se importa com a ordem de saída:

$ awk '
    FNR == NR {
        if (FNR == 1) {header = "Position "FILENAME;next}
        a[$1] = $2;
        next;
    }
    {
        if (FNR == 1) {header = header" "FILENAME;next}
        if ($1 in a) {
            a[$1] = a[$1]" "$2;
        }
        else {
            a[$1] = "- "$2;
        }
    }
    END {
        print header;
        for (i in a) {
            print i,length(a[i]) == 1 ? a[i]" -" : a[i];
        }
    }
' file1 file2
Position file1 file2
412640 - A
380441 C C
392640 T -
570405 T T
341791 T T
459079 T T
464056 - T
228201 T -
312002 - C
100001 C C
480253 T -
492633 A A
459055 A A
    
por 29.05.2014 / 10:25
0

Se python estiver ok e nenhum problema na ordem de saída funcionar com dois arquivos:

f = open("path to file1", "r")
g = open("path to file2", "r")
pos_1 = []
pos_2 = []
poly_1 = []
poly_2 = []
for line in f:
    line = line.strip('\n')
    a, b = line.split(' ')
    pos_1.append(a)
    poly_1.append(b)
for line in g:
    line = line.strip('\n')
    a, b = line.split(' ')
    pos_2.append(a)
    poly_2.append(b)
res = pos_1 + pos_2
result = []
for pos in res:
    val1 = "-"
    val2 = "-"
    if pos in pos_1:
        val1 = poly_1[pos_1.index(pos)]
    if pos in pos_2:
        val2 = poly_2[pos_2.index(pos)]
    t = (pos, val1, val2)
    result.append(t)
result = set(result) // to remove duplicates
for val in result:
    pos = val[0]
    val1 = val[1]
    val2 = val[2]
    ans = str(pos)+" "+str(val1)+" "+str(val2)
    print ans

Isto está no python 2.7 e para o python 3 substitua print pela função print ().

    
por 29.05.2014 / 10:39