Transformando uma matriz com dimensão (nxn) em matriz com combinação de linha * coluna

1

Acho que será melhor exemplificar.

Eu tenho essa estrutura de matriz (arquivo):

Arquivo1

____   snp1  snp2   snp3   snp4
snp1    1     0.3   0.4    0.5
snp2    0.3     1   0.4    0.5
snp3    0.4   0.4     1    0.5
snp4    0.5   0.5   0.5      1

Eu queria transformar esse Arquivo1 em Arquivo2 :

snp1 snp1   1
snp1 snp2   0.3 
snp1 snp3   0.4 
snp1 snp4   0.5
snp2 snp2   1 
snp2 snp3   0.4
snp2 snp4   0.5
snp3 snp3   1
snp3 snp4   0.5
snp4 snp4   1

Espero que seja compreensível, mas não sei outra forma de perguntar. No meu arquivo real é maior que o arquivo1.

Obrigado.

    
por Amanda Botelho Alvarenga 08.08.2016 / 15:57

3 respostas

2

Para imprimir apenas os valores triangulares superiores de acordo com a saída desejada

awk '
  NR==1 {
    split($0,hdr," "); next
  } 
  {
    for (i=NR;i<=NF;i++) {print $1 FS hdr[i] FS $i}
  }
' file
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp3 1
snp3 snp4 0.5
snp4 snp4 1

ou equivalentemente, com perl

perl -alne '
  if ($. == 1) {
    @hdr = @F;
  } else {
    for $i ($.-1 .. $#F) {
      print join " ", $F[0], $hdr[$i], @F[$i];
    }
  }' file

Se você quiser a matriz completa em vez de apenas o triângulo superior, modifique o índice inicial do loop for , substituindo NR (na versão awk) por 2 ou $.-1 (no versão perl) por 1

    
por 08.08.2016 / 19:52
1

UPDATE

Sem limitações agora.

#!/bin/bash

INPUT=File1
declare -a fields

fields=( $(head -n1 "$INPUT") )

i=0
while read -r line; do
    values=( $line )
    for ((j=++i; j<${#values[@]}; j++)); do
        echo -e "${fields[$i]}" "${fields[$j]}"'\t'"${values[$j]}"
    done
done < <( tail -n+2 "$INPUT")
    
por 08.08.2016 / 19:03
0

Isso deve ser fácil usando awk .

$ awk -f script.awk file1.txt
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp1 0.3
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp1 0.4
snp3 snp2 0.4
snp3 snp3 1
snp3 snp4 0.5
snp4 snp1 0.5
snp4 snp2 0.5
snp4 snp3 0.5
snp4 snp4 1

Conteúdo de script.awk . Ignoramos a primeira linha e formamos o restante conforme desejado.

$ cat script.awk
{
if (NR == 1) next;
print $1" snp1 "$2;
print $1" snp2 "$3;
print $1" snp3 "$4;
print $1" snp4 "$5;
}

Conteúdo de file1.txt

$ cat test.txt 
____   snp1  snp2   snp3   snp4
snp1    1     0.3   0.4    0.5  
snp2    0.3     1   0.4    0.5
snp3    0.4   0.4     1    0.5 
snp4    0.5   0.5   0.5      1

Você pode redirecionar a saída para um novo arquivo como esse.

awk -f script.awk file1.txt > file2.txt
    
por 08.08.2016 / 17:26