remove entradas duplicadas em uma coluna e lineariza os valores em várias linhas para uma única linha

2

Eu tenho uma tabela assim:

DAPPUDRAFT_194440   Phosphorous     
DAPPUDRAFT_194440   Temperature     
DAPPUDRAFT_194472   Phosphorous Fishkairomones  
DAPPUDRAFT_194472   Temperature     
DAPPUDRAFT_194512   Fishkairomones      
DAPPUDRAFT_194512   Cadmium Zinc    Quantumdots
DAPPUDRAFT_195644   Salinity        
DAPPUDRAFT_195644   Phosphorous     
DAPPUDRAFT_196131   Salinity        
DAPPUDRAFT_196131   Phosphorous     
DAPPUDRAFT_196131   hypoxia     
DAPPUDRAFT_196694   Salinity        

Como você pode ver, ele pode ter dados em um número variável de colunas (separadas por uma guia).

As entradas duplicadas na primeira coluna que iniciam "DAPPUDRAFT_" devem ser removidas e todos os outros valores que ocorrem em várias linhas devem ocorrer em uma única linha.

Por exemplo, na minha tabela de entrada, "DAPPUDRAFT_194440" ocorre 2 vezes na tabela e tem dois valores "temperatura" em uma linha, "fósforo" na segunda linha, como visto no subconjunto de dados aqui:

 DAPPUDRAFT_194440   Phosphorous     
 DAPPUDRAFT_194440   Temperature  

O que eu gostaria de ver é: "DAPPUDRAFT_" deve ocorrer apenas uma vez, e as duas entradas "temperature" e "phosphorus" devem ocorrer na mesma linha, separadas por uma tabulação, como visto aqui:

 DAPPUDRAFT_194440   Phosphorous   Temperature  

Resultado esperado:

DAPPUDRAFT_194440   Phosphorous Temperature     
DAPPUDRAFT_194472   Phosphorous Fishkairomones  Temperature 
DAPPUDRAFT_194512   Fishkairomones  Cadmium Zinc    Quantumdots
DAPPUDRAFT_195644   Salinity    Phosphorous     
DAPPUDRAFT_196694   Salinity            
DAPPUDRAFT_196131   Salinity    Phosphorous hypoxia 

Eu tentei com o pacote "reshape2" em R com a função dcast. Mas faz algo totalmente diferente do que eu queria. Existe uma maneira na linha de comando ou R ou perl que pode ajudar a resolver isso?

    
por biobudhan 15.09.2017 / 14:09

3 respostas

2

Simplesmente com awk :

awk '{ r=$0; sub($1,"",r); a[$1]=(a[$1])? a[$1]"\t"r : r }
     END{ for(i in a) { gsub(/[[:space:]]{2,}/," ",a[i]); print i,a[i] } }' file
  • r=$0 - capturando cópia do registro

  • sub($1,"",r) - removendo o primeiro campo da cópia para armazenar os campos restantes na variável r

  • a[$1]=(a[$1])? a[$1]"\t"r : r - acumulando valores para o mesmo grupo (apresentado pelo 1º campo)

  • for(i in a) - iterando por todos os itens agrupados

  • gsub(/[[:space:]]{2,}/," ",a[i]) - removendo espaços em branco excessivos entre palavras

  • print i,a[i] - imprima o nome do grupo e seus valores

A saída:

DAPPUDRAFT_194440  Phosphorous Temperature 
DAPPUDRAFT_196694  Salinity
DAPPUDRAFT_194512  Fishkairomones Cadmium Zinc Quantumdots
DAPPUDRAFT_194472  Phosphorous Fishkairomones Temperature 
DAPPUDRAFT_196131  Salinity Phosphorous hypoxia 
DAPPUDRAFT_195644  Salinity Phosphorous 
    
por 15.09.2017 / 14:16
0

Ou

$ perl -e 'while(<ARGV>){chomp;($x,$y)=split(/\s+/,$_,2);$hash{$x}.=$y;}for(keys %hash){print "$_ $hash{$_}\n";}' test1
DAPPUDRAFT_196694 Salinity
DAPPUDRAFT_194440 Phosphorous     Temperature
DAPPUDRAFT_195644 Salinity        Phosphorous
DAPPUDRAFT_194472 Phosphorous Fishkairomones  Temperature
DAPPUDRAFT_194512 Fishkairomones      Cadmium Zinc    Quantumdots
DAPPUDRAFT_196131 Salinity        Phosphorous     hypoxia
    
por 15.09.2017 / 14:24
0

Se você não se importa como linhas e elementos são ordenados:

sed 'G;s/^\(.*\)\(\t.*\)\n\(.*\)//;h;$!d;s/\n$//' file

Para o não-GNU sed substitua o \t por um TAB litaral.

    
por 15.09.2017 / 14:27

Tags