Como comparar 2 arquivos com colunas comuns e, em seguida, obter o arquivo de saída com colunas de cada arquivo

1

Existem dois arquivos de entrada; ambos são formatados como TSV.

File1: treated.bam.tsv 
File2: untreated.bam.tsv

Ambos os arquivos possuem os mesmos campos, conforme listado abaixo. (Eu aumentei para fins de apresentação) - cada arquivo tem 23 campos.

1chrom           9mismatches_pp       17C_pp
2pos             10deletions          18T
3ref             11deletions_pp       19T_pp
4reads_all       12insertions         20G
5reads_pp        13insertions_pp      21G_pp
6matches         14A                  22N
7matches_pp      15A_pp               23N_pp
8mismatches      16C

Se os valores nas colunas 1 e 2 (chrom, pos) forem os mesmos em ambos os arquivos, eu quero extrair alguns dos campos nos registros e, em seguida, criar um novo arquivo de saída como este abaixo. O arquivo de saída possui 15 campos, combinando dados dos dois arquivos de entrada, conforme abaixo.

From file1:
  1chrom
  2pos
  3ref
  4reads_all
  8mismatches
  10deletions
  12insertions
  pct_file1 (the values from file1: (8mismatches+10deletions+12insertions)/4reads_all)
From file2:
  3ref
  4reads_all
  8mismatches
  10deletions
  12insertions
  pct_file2 (the values from file2: (8mismatches+10deletions+12insertions)/4reads_all)
-New values from extractions.
  pct_sub  (the values from pct_file1 - pct_file2: ((8mismatches+10deletions+12insertions)/4reads_all) - ((8mismatches+10deletions+12insertions)/4reads_all))

No arquivo de saída, as oito primeiras colunas vêm do Arquivo1, treated.bam.tsv (a 8ª coluna é o valor calculado com 8mismatches, 10deletions, 12insertions e 4reads_all do arquivo1).

O restante deles vem do Arquivo2, untreated.bam.tsv e a 13ª coluna também é o valor calculado com 8mismatches, 10deletions, 12insertions e 4reads_all do arquivo2.

O último campo, pct_sub , é calculado a partir do valor de subtração com campos do Arquivo1 ((8mismatches + 10deletions + 12insertions) / 4reads_all) e do File2 ((8mismatches + 10deletions + 12insertions) / 4reads_all).

E como posso adicionar novos nomes de colunas em arquivos de saída, como pct_file1 , pct_file2 , pct_sub ?

Isso é o que eu fiz para o arquivo de saída acima. (Arquivos de entrada e saída têm todo o mesmo formato: TSV.)

awk 'FNR==NR{array[$1,$2]=$0;next} { if ( $1 $2 in array ) print $1, $2, array[$3], array[$4], array[$8], array[$10], array[$12], (array[$8]+array[$10]+array[$12])/array[$4], $3, $4, $8, $10, $12, ($8+$10+$12)/$4, ((array[$8]+array[$10]+array[$12])/array[$4])-(($8+$10+$12)/$4) > "awkoutput.bam.tsv" }' treated.bam.tsv untreated.bam.tsv

(Actually, $1, $2 are not a problem from File1 or File2)

FILE1 ( treated )

chrom pos ref reads_all reads_pp matches matches_pp mismatches mismatches_pp deletions deletions_pp insertions insertions_pp A A_pp C C_pp T T_pp G G_pp N N_pp

chrY 59363551 G 8 0 7 0 0 0 1 0 5 0 0 0 0 0 0 0 7 0 0 0
chrY 59363552 G 7 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0
chrY 59363553 T 7 0 7 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0
chrY 59363554 G 7 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0
chrY 59363555 T 7 0 7 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0

FILE2 ( untreated )

chrom pos ref reads_all reads_pp matches matches_pp mismatches mismatches_pp deletions deletions_pp insertions insertions_pp A A_pp C C_pp T T_pp G G_pp N N_pp
chrY 59363551 G 2 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0
chrY 59363552 G 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
chrY 59363553 T 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
chrY 59363554 G 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
chrY 59363555 T 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0

OUTPUT

chrom pos ref reads_all mismatches deletions insertions pct_file1 ref reads_all mismatches deletions insertions pct_file2 pct_sub
chrY 59363551 G 8 0 1 5 0.75 G 2 0 0 1 0.5 0.25
chrY 59363552 G 7 0 0 0 0 G 1 0 0 0 0 0
chrY 59363553 T 7 0 0 0 0 T 1 0 0 0 0 0
chrY 59363554 G 7 0 0 0 0 G 1 0 0 0 0 0
chrY 59363555 T 7 0 0 0 0 T 1 0 0 0 0 0
    
por Jan Bright 17.10.2016 / 18:10

2 respostas

0
  1. if ( $1 $2 in array ) não funciona; você tem que fazer if (($1,$2) in array) .
  2. Você não pode usar array[$3] e array[$4] desse jeito. Seu array parece com
    array[chrY,59363551]=“chrY 59363551 G 8 0 7 0 0 0 1 0 5 0 0 0 0 0 0 0 7 0 0 0”
    array[chrY,59363552]=“chrY 59363552 G 7 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0”
                 ︙
    e quando você diz array[$3] e array[$4] , você está se referindo a array[G] e array[2] , etc. que não existem.
  3. A capacidade de especificar > "filename" no código awk é um ótimo recurso quando você deseja gravar em vários arquivos. Não é tão útil quando você tem apenas um arquivo de saída - por que você não apenas redireciona a saída do comando awk ?
  4. Linhas longas são ruins. Quebre comandos longos em linhas curtas. Reduza a duplicação reutilizando as variáveis.
  5. Não use uma matriz chamada array . Isso é como ter uma variável chamada variable , um arquivo chamado file , uma pessoa chamada Person etc. Use nomes descritivos.

OK, isso dito,

awk 'FNR==NR {file1data[$1,$2]=$0; next}
        {       if (($1,$2) in file1data) {
                        # Save desired values from file2.
                        file2arg03=$3
                        file2arg04=$4
                        file2arg08=$8
                        file2arg10=$10
                        file2arg12=$12
                        pct_file2=($8+$10+$12)/$4
                        # Get data from file1.
                        $0=file1data[$1,$2]
                        pct_file1=($8+$10+$12)/$4
                        print $1, $2, $3, $4, $8, $10, $12, pct_file1, \
                                file2arg03, file2arg04, file2arg08, file2arg10, file2arg12, \
                                pct_file2, pct_file1-pct_file2
                } else printf "(%s,%s) in file2 but not file1.%s", $1, $2, ORS
        }' treated.bam.tsv untreated.bam.tsv > awkoutput.bam.tsv

Assim como sua versão, isso salva os dados do arquivo1 em uma matriz e depois faz todo o trabalho / saída enquanto lê o arquivo2. Ao receber uma linha do arquivo 2, salva os campos desejados daquela linha em variáveis nomeadas (também podemos usar outro array, cinco elementos de comprimento) e, em seguida, restaura os dados da linha correspondente no arquivo1. Atribuindo a linha inteira a $0 , isso causa $1 , $2 , $3 , $4 , etc. para ser restaurado aos seus valores originais.

Você está realmente tendo problemas para escrever uma linha de cabeçalho na saída? Experimente:

        {       if (FNR == 1) {
                        print "chrom pos ref reads_all mismatches deletions insertions pct_file1 …"
                } else if (($1,$2) in file1data ) {
                        file2arg03=$3
                              ︙

OK, aqui está uma versão mais próxima de sua tentativa, e que lida com a linha de cabeçalho:

awk 'FNR==NR {file1line[$1,$2]=$0; next}
        {       if (FNR == 1) {
                        print "chrom pos ref reads_all mismatches deletions insertions pct_file1 ref reads_all mismatches deletions insertions pct_file2 pct_sub …"
                } else if (($1,$2) in file1line ) {
                        # Get data from file1.
                        split(file1line[$1,$2], file1arg)
                        pct_file1=(file1arg[8]+file1arg[10]+file1arg[12])/file1arg[4]
                        pct_file2=($8+$10+$12)/$4
                        print $1, $2, file1arg[3], file1arg[4], file1arg[8], \
                                file1arg[10], file1arg[12], pct_file1, \
                                $3, $4, $8, $10, $12, pct_file2, pct_file1-pct_file2
                } else printf "(%s,%s) in file2 but not file1.%s", $1, $2, ORS
        }' treated.bam.tsv untreated.bam.tsv > awkoutput.bam.tsv

Isso recupera a linha do arquivo1 (de file1line ) e passa para split para dividir em seus valores constituintes 23, que são armazenados no array file1arg . Então é possível usar file1arg[3] , file1arg[4] ,…, a maneira como você estava usando array[$3] , array[$4] ,…

    
por 18.10.2016 / 00:33
1

A bioinformática parece ser divertida. Se você está aberto a soluções não-awk, um trabalho fácil para miller :

mlr --itsv join -u -j chrom,pos --lp tr_ --rp untr_ -f treated.bam.tsv untreated.bam.tsv | # join data from treated and untreated files by fields chrom and pos
mlr put '$tr_pct=($tr_mismatches+$tr_deletions+$tr_insertions)/$tr_reads_all' | # calculate pct for treated data
mlr put '$untr_pct=($untr_mismatches+$untr_deletions+$untr_insertions)/$untr_reads_all' | # calculate pct for untreated data
mlr cut -o -f chrom,pos,tr_ref,tr_reads_all,tr_mismatches,tr_deletions,tr_insertions,tr_pct,untr_ref,untr_reads_all,untr_mismatches,untr_deletions,untr_insertions,untr_pct | # remove superfluous fields
mlr --otsv put '$pct_sub=$tr_pct-$untr_pct' # append pct subtraction field

chrom   pos tr_ref  tr_reads_all    tr_mismatches   tr_deletions    tr_insertions   tr_pct  untr_ref    untr_reads_all  untr_mismatches untr_deletions  untr_insertions untr_pct    pct_sub
chrY    59363551    G   8   0   1   5   0.750000    G   2   0   0   1   0.500000    0.250000
chrY    59363552    G   7   0   0   0   0   G   1   0   0   0   0   0
chrY    59363553    T   7   0   0   0   0   T   1   0   0   0   0   0
chrY    59363554    G   7   0   0   0   0   G   1   0   0   0   0   0
chrY    59363555    T   7   0   0   0   0   T   1   0   0   0   0   0

Parece mais assustador do que é. Realmente.

    
por 23.10.2016 / 21:37

Tags