colunas para o awk da matriz de dados

1

Estou procurando uma solução awk para obter desta tabela (com x número de nomes na coluna 1 e diferentes comprimentos da coluna 2 que é ";" separados):

dataframe.txt:

name1 1;2;4;8
name2 4;5;7
name3 8
name4 11;12
namex 20;21

para esta matriz com o presente 1 e não presente 0 :

matrix.txt:

        1 2 4 5 7 8 11 12 20 21
name1   1 1 1 0 0 1 0  0  0  0 
name2   0 0 1 1 1 0 0  0  0  0
name3   0 0 0 0 0 1 0  0  0  0
name4   0 0 0 0 0 0 1  1  0  0
namex   0 0 0 0 0 0 0  0  1  1
    
por newAWKer 09.05.2018 / 12:43

2 respostas

2

Awk solução:

awk 'BEGIN{
         h = "1 2 3 4 5 6 7 8 11 12 20 21";
         len = split(h, head);
         print "\t\t" h
     }
     {
         printf "%s\t", $1;
         for (i = 1; i <= len; i++)
             printf "%s%d", (i == 1? "" : OFS), ($2 ~ "\<" head[i] "\>");
         print "" 
     }' file
  • h = "1 2 3 4 5 6 7 8 11 12 20 21" - cabeçalho linha
  • len = split(h, head) - split h line no array head onde os índices são ordenados a partir de 1 e os valores são valores cruciais obtidos por divisão; len contém um tamanho de matriz
  • print "\t\t" h - imprima a linha cabeçalho com os principais caracteres de tabulação
  • printf "%s\t", $1; - imprime o primeiro campo $1
  • for (i = 1; i <= len; i++) - iterar por head itens
    • $2 ~ "\<" head[i] "\>" - verifique se o segundo campo $2 contém o item acessado atualmente head[i]

A saída:

        1 2 3 4 5 6 7 8 11 12 20 21
name1   1 1 0 1 0 0 0 1 0 0 0 0
name2   0 0 0 1 1 0 1 0 0 0 0 0
name3   0 0 0 0 0 0 0 1 0 0 0 0
name4   0 0 0 0 0 0 0 0 1 1 0 0
namex   0 0 0 0 0 0 0 0 0 0 1 1
    
por 09.05.2018 / 13:01
0

Outra abordagem awk que gera o cabeçalho primeiro e depois preenche a matriz com 1 para cada chave na matriz head existe na linha de entrada atual, caso contrário com 0 se não existe.

Usamos grep para buscar apenas -o números que correspondem à string vazia na borda esquerda de um número \b (o mesmo que \< que usamos em awk para os lados esquerdo e direito).

awk 'NR==FNR { !head[$1]++; next } 
    { printf $1; for (x in head) { printf (x?FS:"") ($0 ~ "\<" x "\>") }; print ""
}' <(grep -o '\b[0-9]\+' infile) infile

A saída é:

name1 1 1 1 0 0 1 0 0 0 0
name2 0 0 1 1 1 0 0 0 0 0
name3 0 0 0 0 0 1 0 0 0 0
name4 0 0 0 0 0 0 1 1 0 0
namex 0 0 0 0 0 0 0 0 1 1

Você poderia gerar o cabeçalho e inserir na primeira linha do arquivo de entrada, então o awk seria fácil como:

awk 'NR==1{ split($0, head); next }
    { printf $1; for (x in head){ printf (x?FS:"") ($2 ~ "\<" head[x] "\>" ) }; 
print "" }' infile
    
por 10.05.2018 / 12:50