concatena colunas horizontalmente, se corresponder no campo anterior. Múltiplas colunas para concatenar

3

Então, eu tenho um arquivo com hits de inserções com algumas características com o seguinte aspecto (chr, start, end, chr, estrela, final, número de pares de bases sobrepostas:

    chr1    69744110    69793325    .   -1  -1  0
    chr1    82791976    82831348    chr1    82792114    82792615    501
    chr1    82791976    82831348    chr1    82816285    82817077    792
    chr1    82791976    82831348    chr1    82828015    82829891    1876
    chr1    88599340    88658398    .   -1  -1  0
    chr1    137772945   137830035   .   -1  -1  0
    chr1    137875312   137920590   .   -1  -1  0
    chr1    193433080   193446861   .   -1  -1  0
    chr10   26483800    26501370    chr10   26484794    26485295    501
    chr10   68069913    68089436    .   -1  -1  0
    chr10   95098349    95113967    .   -1  -1  0
    chr10   97310211    97335589    .   -1  -1  0
    chr10   111083097   111118237   chr10   111088928   111090274   1346
    chr10   117904141   117947090   chr10   117905334   117906320   986
    chr10   117904141   117947090   chr10   117918966   117919852   886
    chr10   117904141   117947090   chr10   117926867   117927368   501
    chr11   11521339    11587607    chr11   11523970    11524747    777
    chr11   11521339    11587607    chr11   11555497    11559868    4371
    chr11   11521339    11587607    chr11   11560639    11562128    1489
    chr11   11521339    11587607    chr11   11564617    11565370    753

Então, o que eu preciso é concatenar os valores na coluna 5 (coluna 5 / coluna 5 ...), coluna 6 (coluna 6 / coluna 6 ...) e coluna 7 (coluna / coluna 7) ... SE tiver uma correspondência nas 3 primeiras colunas. Eu também gostaria de manter a coluna 4, mas tudo bem se eu sentir falta dela.

A saída deve se parecer com:

    chr1    69744110    69793325    .   -1  -1  0
    chr1 82791976 82791976 chr1 82792114/82816285/82828015 82792615/82817077/82829891 501/792/1876
    chr1    88599340    88658398    .   -1  -1  0
    chr1    137772945   137830035   .   -1  -1  0
    chr1    137875312   137920590   .   -1  -1  0
    chr1    193433080   193446861   .   -1  -1  0
    chr10   26483800    26501370    chr10   26484794    26485295    501            (...)
    chr10   117904141   117947090   chr10 117905334/117918966/117926867 117906320/117919852/117927368   986/886/501
    (...)

Eu já estive em vários testes e o melhor que pude fazer foi:

    awk '{ k=$1 FS $2 FS $3;  a[k]=(k in a)? a[k]"/"$5 : $5 }
 END{ for(i in a) { 
          split(i,b,FS); b[5]=a[i]"\t"b[5]; r=""; 
          for(j=1;j<=NF;j++) { 
              r=(r!="")? r"\t"b[j] : b[j] 
          } 
          print r} 
    }' input.bed > output.bed

Mas com isso eu estou perdendo valores e não consigo concatenar mais de uma coluna.

Você pode me ajudar por favor?

EDITAR:

nova tentativa:

    awk -F'\t' -v OFS='\t' '{
        if ($2 in a) {
            a[$2] = a[$2]";"$5;
            b[$2] = b[$2]";"$6;
        } else {
            a[$2] = $5;
            b[$2] = $6;
       }
    }
    END { for (i in a) print i, a[i], b[i] }' input.bed > output.bed

Mas continuo a perder os campos que não estão sendo avaliados.

    
por José Dias 12.12.2017 / 15:12

2 respostas

0

Pergunta:

Concatenate the values in column 5,6 and 7 IF I have a match in the first 3 columns

Resposta:

perl -lane 'if($.==1){@a=@F;next} if($F[0]eq$a[0]&&$F[1]eq$a[1]&&$F[2]eq$a[2]){$a[4].="/$F[4]";$a[5].="/$F[5]";$a[6].="/$F[6]";}else{for($i=0;$i<@a;$i++){printf "\t%s",$a[$i]};print"";@a=@F}END{for($i=0;$i<@a;$i++){printf "\t%s",$a[$i]};print""}' input.bed

Saída:

    chr1    69744110        69793325        .       -1      -1      0
    chr1    82791976        82831348        chr1    82792114/82816285/82828015      82792615/82817077/82829891      501/792/1876
    chr1    88599340        88658398        .       -1      -1      0
    chr1    137772945       137830035       .       -1      -1      0
    chr1    137875312       137920590       .       -1      -1      0
    chr1    193433080       193446861       .       -1      -1      0
    chr10   26483800        26501370        chr10   26484794        26485295        501
    chr10   68069913        68089436        .       -1      -1      0
    chr10   95098349        95113967        .       -1      -1      0
    chr10   97310211        97335589        .       -1      -1      0
    chr10   111083097       111118237       chr10   111088928       111090274       1346
    chr10   117904141       117947090       chr10   117905334/117918966/117926867   117906320/117919852/117927368   986/886/501
    chr11   11521339        11587607        chr11   11523970/11555497/11560639/11564617     11524747/11559868/11562128/11565370     777/4371/1489/753

Nota:

Pode haver uma solução mais curta ou mais elegante

    
por 12.12.2017 / 17:16
1

Com o awk. Infelizmente, o awk não possui uma função de junção de matriz integrada, mas o manual on-line do gawk tem um exemplo de como escrever um.

Se estiver no arquivo aggregate.awk (suponho que o arquivo de entrada esteja separado por tabulações)

BEGIN {
    FS = OFS = "\t"
}

# ref https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html#Join-Function
function join(array, start, end, sep,    result, i)
{
    if (sep == "")
        sep = " "
    else if (sep == SUBSEP) # magic value
        sep = ""
    result = array[start]
    for (i = start + 1; i <= end; i++)
        result = result sep array[i]
    return result
}

function print_record() {
    last_line[5] = join(col5, 1, n, "/")
    last_line[6] = join(col6, 1, n, "/")
    last_line[7] = join(col7, 1, n, "/")
    print join(last_line, 1, NF, OFS)
}

{
    key = $1 OFS $2 OFS $3
}

key != prev_key {
    if (n > 0) {
        print_record()
    }
    delete col5
    delete col6
    delete col7
    n = 0
}

{
    n++
    col5[n] = $5
    col6[n] = $6
    col7[n] = $7
    prev_key = key
    split($0, last_line)
}

END {print_record()}

Então nós temos:

$ awk -f aggregate.awk input.bed
chr1    69744110        69793325        .       -1      -1      0
chr1    82791976        82831348        chr1    82792114/82816285/82828015      82792615/82817077/82829891      501/792/1876
chr1    88599340        88658398        .       -1      -1      0
chr1    137772945       137830035       .       -1      -1      0
chr1    137875312       137920590       .       -1      -1      0
chr1    193433080       193446861       .       -1      -1      0
chr10   26483800        26501370        chr10   26484794        26485295        501
chr10   68069913        68089436        .       -1      -1      0
chr10   95098349        95113967        .       -1      -1      0
chr10   97310211        97335589        .       -1      -1      0
chr10   111083097       111118237       chr10   111088928       111090274       1346
chr10   117904141       117947090       chr10   117905334/117918966/117926867   117906320/117919852/117927368   986/886/501
chr11   11521339        11587607        chr11   11523970/11555497/11560639/11564617     11524747/11559868/11562128/11565370     777/4371/1489/753
    
por 12.12.2017 / 19:01