Impute dados por valor majoritário por grupo

1

Eu tenho instrumentos em col1, suas variáveis em col2 e chamadas em col3. Neste exemplo, existem 17 tipos INS e 3 M. Potencialmente haverá 17 x 3 linhas. Mas alguns estão faltando.

INS1    M1  AA
INS2    M1  AA
INS3    M1  AA
INS4    M1  GG
INS5    M1  GG
INS6    M1  GG
INS7    M1  AA
INS8    M1  GG
INS9    M1  GG
INS10   M1  AA
INS11   M1  AA
INS12   M1  GG
INS13   M1  AA
INS14   M1  AA
INS15   M1  AA
INS1    M2  GG
INS3    M2  TT
INS4    M2  GG
INS5    M2  GG
INS6    M2  TT
INS7    M2  TT
INS8    M2  TT
INS9    M2  TT
INS10   M2  GG
INS11   M2  GG
INS14   M2  GG
INS15   M2  TT
INS1    M3  AA
INS2    M3  TT
INS3    M3  AA
INS4    M3  TT
INS5    M3  TT
INS7    M3  AA
INS8    M3  TT
INS9    M3  AA
INS10   M3  TT
INS15   M3  TT

Eu tenho outro arquivo de pesquisa que tem os grupos aos quais esses instrumentos pertencem. por exemplo. INS (1,2,3,7,14,16 e 17) pertencem ao grupo1.

GR1 INS1
GR1 INS2
GR1 INS3
GR1 INS7
GR1 INS14
GR1 INS16
GR1 INS17
GR2 INS5
GR2 INS6
GR2 INS8
GR2 INS9
GR2 INS15
GR3 INS4
GR3 INS10
GR3 INS11
GR3 INS12
GR3 INS13

Estou tentando imputar as chamadas ausentes, com base na chamada de grupo majoritário acima de um limite de 70%. (linhas imputadas com estrela, mas não desejadas na saída).

Se dentro do grupo1, o mesmo valor M tiver frequência de chamada AA = 80% (3/4) e frequência de chamada de GG = 20% (1/4), então poderemos imputar todo o INS ausente no grupo1 como AA já que a maioria de 80% atende ao limite de 70%.

Se a frequência foi de 66% (2/3) para AA e 33% (1/3) para GG, não imputamos como AA, uma vez que 66% não atinge o limite de 70%.

INS1    M1  AA
INS2    M1  AA
INS3    M1  AA
INS4    M1  GG
INS5    M1  GG
INS6    M1  GG
INS7    M1  AA
INS8    M1  GG
INS9    M1  GG
INS10   M1  AA
INS11   M1  AA
INS12   M1  GG
INS13   M1  AA
INS14   M1  AA
INS15   M1  AA
**INS16 M1  AA
INS17   M1  AA**
INS1    M2  GG
INS3    M2  TT
INS4    M2  GG
INS5    M2  GG
INS6    M2  TT
INS7    M2  TT
INS8    M2  TT
INS9    M2  TT
INS10   M2  GG
INS11   M2  GG
**INS12 M2  GG
INS13   M2  GG**
INS14   M2  GG
INS15   M2  TT
INS1    M3  AA
INS2    M3  TT
INS3    M3  AA
INS4    M3  TT
INS5    M3  TT
**INS6  M3  TT**
INS7    M3  AA
INS8    M3  TT
INS9    M3  AA
INS10   M3  TT
**INS11 M3  TT
INS12   M3  TT
INS13   M3  TT
INS14   M3  AA**
INS15   M3  TT
**INS16 M3  AA
INS17   M3  AA**

Por exemplo, Grp1 M1 (INS1,2,3,7,14) tem 5 chamadas de AA com frequncia de 100%. Portanto, podemos atribuir INS16 e INS17 (uma vez que estão faltando e pertencendo ao Grp 1) para M1 como AA, porque a frequência de chamadas é acima de 70%.

Para o Grp1 M2, as chamadas GG (2/4) e TT (2/4) são feitas em 50%, portanto, uma imputação confiável não pode ser feita acima de 70%. Para Grp1 M2, INS2,16 e 17 continuam desaparecidos porque não há uma maioria clara de uma chamada (acima de 70%).

Por favor, orientar sobre como conseguir isso em awk ou perl. Minha tentativa de solução é adicionar o grupo aos dados e, em seguida, encontrar a frequência da chamada mais alta, para verificar com o limite, estou ficando um pouco perdido com matrizes de hash.

awk 'NR==FNR{a[$2]=$1;next} $1 in a { print $0 FS a[$1]}' groups data > tmp
awk '{count[$4 FS $1]++}END{for(j in count) print j":"count[j]}' tmp > tmp2
awk -F, '{if (a[$2]< $3)a[$2]=$3;}END{for(i in a){print i,a[i];}}' tmp2 > tmp3
    
por Hia Sen 26.06.2015 / 23:01

1 resposta

2

Isso é um pouco complexo demais para ser legível como um liner, então aqui está um script gawk comentado:

#!/usr/bin/gawk -f
## Save the data in array data: data[M][INS]=dinucleotide
NR==FNR{
    data[$2][$1]=$3;
    next
}
## Save the groups in array groups: groups[GRN][INS]
{
    groups[$1][$2]++
}
## Now that everything is stored in memory, analyze
END{
    ## Get averages: for each group
    for(group in groups){
        ## For each INS in this group
        for(ins in groups[group]){
            ## For each MN in the data file
            for(m in data){
                ## If this INS had a value for this M
                if(data[m][ins]){
                    ## This counts the number of times this dinucleotide
                    ## (data[m][ins]) was found in this M among the INSs 
                    ## of this group.
                    num[group][m][data[m][ins]]++
                    ## My version of gawk doesn't seem to support
                    ## length for multidimensional arrays, so this array
                    ## only exists to count the number of Ms of this group.
                    len[group][m]++;
                }
            }
        }
    }
    ## Foreach group of the groups file
    for(group in num){
        ## For each M of this group 
        for(m in num[group]){
            ## For each INS of this group
            for(ins in groups[group]){
                ## If this INS has a value for this m in
                ## the data file, print it. 
                if(data[m][ins]){
                    printf "%-5s %s %s\n", ins,m,data[m][ins]
                }
                ## If it doesn't, check if there's an nt at
                ## >=70% for this group and print that
                else{
                    for(nt in num[group][m]){
                        if(num[group][m][nt]*100/len[group][m] >= 70){
                            printf "%-5s %s %s\n", ins,m,nt
                        }
                    }
                }
            }
        }
    }
}

Salve o arquivo como foo.awk , torne-o executável chmod +x foo.awk e execute-o em seus arquivos:

$ ./foo.awk data groups 
INS1  M1 AA
INS2  M1 AA
INS14 M1 AA
INS3  M1 AA
INS16 M1 AA
INS17 M1 AA
INS7  M1 AA
INS1  M2 GG
INS14 M2 GG
INS3  M2 TT
INS7  M2 TT
INS1  M3 AA
INS2  M3 TT
INS14 M3 AA
INS3  M3 AA
INS16 M3 AA
INS17 M3 AA
INS7  M3 AA
INS9  M1 GG
INS15 M1 AA
INS5  M1 GG
INS6  M1 GG
INS8  M1 GG
INS9  M2 TT
INS15 M2 TT
INS5  M2 GG
INS6  M2 TT
INS8  M2 TT
INS9  M3 AA
INS15 M3 TT
INS5  M3 TT
INS6  M3 TT
INS8  M3 TT
INS10 M1 AA
INS11 M1 AA
INS12 M1 GG
INS13 M1 AA
INS4  M1 GG
INS10 M2 GG
INS11 M2 GG
INS12 M2 GG
INS13 M2 GG
INS4  M2 GG
INS10 M3 TT
INS11 M3 TT
INS12 M3 TT
INS13 M3 TT
INS4  M3 TT

Observe que essa abordagem requer o carregamento de todo o conjunto de dados (os dois arquivos) na memória. Eu realmente não vejo uma maneira de contornar isso, já que você precisa ler a coisa toda antes de saber se há casos de > = 70%. A única outra abordagem em que posso pensar envolveria o processamento do arquivo várias vezes. Deixe-me saber se o carregamento na memória é um problema e verificarei se posso criar uma opção diferente.

    
por 27.06.2015 / 14:49

Tags