expande dados com base em pontuações

1

Primeiramente eu tenho um conjunto de combinações válidas de 3 colunas (validlist), então o resultado final deve ser um subconjunto deste arquivo.

a   b   c
c   b   c
p   b   d
d   y   d
p   y   d
x   y   z

Eu tenho uma matriz de pontuação como abaixo (scorefile), onde a 3ª coluna (1 max, 0 min) diz o quão perto a variável da 2ª coluna é para a variável da 1ª coluna

a       b       0.3
a       c       0.87
a       d       0.75
b       x       0.87
b       y       0.98
b       z       0.24
c       m       0.9
c       n       0.86
d       p       0.87

Dado um conjunto de variáveis, eu preciso expandir a seleção para outras combinações que são significativamente próximas (> 0.7) para as variáveis de coluna dadas também a soma de proximidade é maior que 1.6. .

Por exemplo: a variável a pode ser expandida para incluir as variáveis c e d, pois elas têm pontuações > 0,7 com um.

A variável b, pode ser expandida para incluir y, e c pode incluir m e n.

Então, minha entrada de exemplo é

a   b   c
d   b   a

e saída expandida é

intermediate output

a   b   c
c   b   c
d   b   c
a   y   c
c   y   c
d   y   c
a   b   m
c   b   m
d   b   m
a   y   m
c   y   m
d   y   m
a   b   n
c   b   n
d   b   n
a   y   n
c   y   n
d   y   n
d   b   a
p   b   a
d   y   a
p   y   a
d   b   c
p   b   c
d   y   c
p   y   c
d   b   d
p   b   d
d   y   d
p   y   d

que é então subconjunto pela lista de validação para ter o resultado final.

a   b   c
c   b   c
p   b   d
d   y   d
p   y   d

Eu tenho um código de trabalho para as duas etapas

awk '
    NR==FNR { 
        if ($3 > 0.7) {
            scr[$1,$2]=$3
            var[$1]
        } 
        next
    }
    { 
        for (col1 in var) {
            for (col2 in var) {
                for (col3 in var)    {
                    if ( 
                        scr[$1,col1] && scr[$2,col2] && scr[$3,col3] &&
                        scr[$1,col1] > 0.7   &&  
                        scr[$2,col2] > 0.7   && 
                        scr[$3,col3] > 0.7   && 
                        scr[$1,col1] + scr[$1,col1] > 1.6
                    ) {
                        print col1,  col2,   col3 
                    }
                }
            }
        }
    }
'  score input > intermediateout


grep -f intermediateout validlist > finalout

O problema é que o arquivo de pontuação tem 345 milhões de registros e a lista válida tem apenas 2600 registros. Então, os 3 loops for duram para sempre, você pode ajudar a acelerar o processo, porque se pudermos filtrar as combinações inválidas primeiro, a saída será muito menor.

Aqui está a memória do cluster e os que eu tenho acesso a

 free -m
             total       used       free     shared    buffers     cached
Mem:        387591     299120      88471          2        481     292698


cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.6

Muito obrigado pela sua ajuda !!

Oi Glenn, estou recebendo um erro de sintaxe no servidor. Por favor, dê uma olhada? Estranhamente, esse erro de sintaxe não aparece no cygwin.

awk: cmd. line:9:         if ($3 > 0.7) clos[$1][$2]  # I would name this array "close"
awk: cmd. line:9:                               ^ syntax error
awk: cmd. line:15:             col[i][$i]
awk: cmd. line:15:                   ^ syntax error
awk: cmd. line:16:             for (key in clos[$i])
awk: cmd. line:16:                             ^ syntax error
awk: cmd. line:17:                 col[i][key]
awk: cmd. line:17:                       ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                              ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                   ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                  ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                       ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                                      ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                                           ^ syntax error
awk: cmd. line:25:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:25:                                                                             ^ unexpected newline or end of string
#

Atualização:

Oi Glenn,

Eu baixei o gawk 4.xxx e esse erro acabou. Obrigado pela sugestão.

Brinquei bastante com o código e acho que entendo melhor as matrizes bidimensionais agora, obrigado.

Quanto ao problema em questão, se eu entendi corretamente, há um possível problema de que cada linha de entrada deve ser processada independentemente das outras. Portanto, deve haver um conjunto de possíveis linhas de saída para cada linha de entrada.

É aí que entra a soma de proximidade,

Para cada linha de entrada 1) Variáveis expandidas com $ 1 devem ser 0.7 fechadas com $ 1. 2) Variáveis expandidas com $ 2 devem ser 0.7 fechadas com $ 2. 3) Para cada variável na matriz $ 1, para cada elemento na matriz $ 2     Sem closeless ($ 1 com variável em $ 1 array) + sem clos ($ 2 com variável em $ 2 array) deve ser maior que 1,6 4) Variáveis expandidas com $ 3 devem ser 0.7 fechadas com $ 3.

À medida que você cria três matrizes com base nas três colunas de entrada, as informações "para cada linha" estão sendo perdidas e a soma de proximidade não pode ser implementada. Por favor, deixe-me saber se isso faz sentido.

Eu tentei um possível ajuste, mas acho que estou perdido na complexidade dos arrays 2-dim e também na possibilidade de usar um array 3-dim. Por favor, ajude

gawk '
    # validlist
    FILENAME == ARGV[1] {
        valid[$1 FS $2 FS $3]
        next
    }
    # scorefile
    FILENAME == ARGV[2] {
        if ($3 > 0.7) clos[$1][$2]
        scr[$1][$2]=$3;                   # I would name this array "close"
        next                        # but that is a keyword
    }
    # input
    {   

        col[NR FS $2][$1];
        col[NR FS $2][$2];
        col[NR FS $3][$3];

        for (key in clos[$i])
        {
            col[NR FS $1][$i];
            col[NR FS $2][$i];
            col[NR FS $3][$i];

            if scr[$1][i] + scr[$2][i] > 1.6
              possible[$i]=$1 FS $2 FS $3
        }


    }
    END {
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for (v in valid) {
           for (allposs in possible)
              if ( v==allpos  ) 
                print v
        }
    }
' validlist scorefile input
    
por Hia Sen 10.11.2015 / 20:37

1 resposta

1

OK, aqui vai você. A chave é que o programa awk leia a lista válida também. Processe a pontuação e os arquivos de entrada. Em seguida, percorra as combinações válidas, não todas as permutações.

Usa o GNU awk para matrizes de matrizes

gawk '
    # validlist
    FILENAME == ARGV[1] {
        valid[$1 FS $2 FS $3]
        next
    }
    # scorefile
    FILENAME == ARGV[2] {
        if ($3 > 0.7) clos[$1][$2]  # I would name this array "close"
        next                        # but that is a keyword
    }
    # input
    {
        for (i=1; i<=3; i++) {
            col[i][$i]
            for (key in clos[$i])
                col[i][key]
        }
    }
    END {
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for (v in valid) {
            split(v, a)
            if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) ) 
                print v
        }
    }
' validlist scorefile input

saídas

a b c
c b c
d y d
p b d
p y d
    
por 11.11.2015 / 01:43

Tags