extrai colunas da matriz TRUE / FALSE com base na proporção de valores TRUE dentro da coluna

2

Eu tenho um arquivo de texto como o abaixo, embora com quase muitas colunas. Eu quero extrair nomes de colunas que têm uma proporção / número específico de valores VERDADEIROS, por exemplo colunas com TRUE em 2 das 9 linhas (com valores VERDADEIRO / FALSO).

Alternativamente, seria bom extrair colunas com pelo menos um certo número (por exemplo, 2) de valores VERDADEIROS. No exemplo acima, seriam colunas com 2 para 9 linhas possíveis com valores TRUE. Deve ser generalizável para arquivos com diferentes números de linhas.

Obrigado!

Exemplo de arquivo de entrada:

Comparison  MT  group1  group1.1    group1.2    group1.3    group1.4    group1.5    group1.6    group1.7    group1.8    group1.9
BP:HA      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE
CB:HA      FALSE TRUE   FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
HA:PI      TRUE  TRUE   FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
AL:GR      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
AL:LA      TRUE  FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
AL:PL      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       TRUE         FALSE 
GR:PP      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
LA:PP      TRUE  FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE
PL:PP      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE

Resultado desejado para colunas com 2 ou mais valores VERDADEIROS :

arquivo de saída:

MT
group1
group1.9
    
por Age87 24.01.2018 / 20:49

3 respostas

1

Aqui está uma maneira de escolher as colunas com instâncias suficientes de TRUE , usando bash:

min_true=3; \
max_col=12; \
for col in $(seq 2 $max_col); do \
  sed 's,    ,.,g;s,   ,.,g' "$filename" | \
    tail -n+2 | \
    cut -d. -f$col > /tmp/f; \
  count=$(grep TRUE /tmp/f | wc -l); \
  if [ "$count" -ge "$min_true" ]; then \
    echo "Column $(($col-1)): $count out of $(echo $(wc -l </tmp/f))"; \
    cat /tmp/f; \
  fi; \
done

A saída pode ser usada para strings como "3 de 9", para obter o número da coluna (contando a partir de 0):

Column 1: 3 out of 9
FALSE
FALSE
TRUE
FALSE
TRUE
FALSE
FALSE
TRUE
FALSE
    
por 24.01.2018 / 21:48
1

Analise todas as colunas e acumule a contagem de "TRUE" para cada coluna.
No final, imprima todas as colunas iguais ou maiores que um ponto de referência:

#!/bin/bash
awk -vprop="${1:-0.3}" '
        NR==1{split($0,fields);next};
        {for(i=2;i<=NF;i++){  if($i=="TRUE" ){t[i]++};
                              if($i=="FALSE"){f[i]++}
                           }
        }
        END{
            for(j in t)
            if( (1/(1+f[j]/t[j])) >= prop){
                printf("%-10s\t%s\t%s\n",fields[j],j,1/(1+f[j]/t[j]) )
            }
        }' infile

Na execução (para os dados que você forneceu):

$ ./script  0.001
MT              i=2     t=3     f=6     p=0.333
group1          i=3     t=2     f=7     p=0.222
group1.8        i=11    t=1     f=8     p=0.111
group1.9        i=12    t=3     f=6     p=0.333

A coluna 2 (MT) tem mais de 1 valores VERDADEIROS: 3 na verdade.
Coluna 3 (grupo1) tem 2 valores VERDADEIROS.
A coluna 11 (grupo1.8) possui 1 valor VERDADEIRO. A coluna 12 (grupo 1.9) possui 3 valores VERDADEIROS.

Se você não fornecer uma proporção, o padrão será 0,3.

$ ./script
MT              i=2     t=3     f=6     p=0.333
group1          i=3     t=2     f=7     p=0.222
group1.9        i=12    t=3     f=6     p=0.333
    
por 24.01.2018 / 22:21
0
$ awk -v p='10' 'NR==1 { split($0,cols); next }
                 { 
                     for (i=2; i<=NF; ++i)
                         nt[i] += ($i == "TRUE" ? 1 : 0 )
                 }
                 END {
                     for (i=2; i<=NF; ++i) {
                         cp = 100*nt[i]/NR
                         if (cp > p) printf("%-20s %.2f%%\n", cols[i], cp)
                     }
                 }' file
MT                   30.00%
group1               20.00%
group1.9             30.00%

O programa awk usa um parâmetro p , que é a porcentagem de TRUE necessária para o cabeçalho da coluna ser exibido.

A partir da primeira linha, ele salva todos os cabeçalhos de coluna na matriz cols . Em seguida, resume quantas vezes a palavra TRUE ocorre em cada coluna. No final, ele calcula a porcentagem de linhas que eram TRUE em cada coluna como cp e compara isso com p . Se for maior que o valor p fornecido, o nome da coluna e a porcentagem serão gerados.

    
por 18.06.2018 / 07:47