删除一列中的重复条目并将多行中的值线性化为单行

删除一列中的重复条目并将多行中的值线性化为单行

我有一个看起来像这样的表:

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        

正如您所看到的,它可以在可变数量的列中包含数据(由制表符分隔)。

应删除以“DAPPUDRAFT_”开头的第一列中的重复条目,并且多行中出现的所有其他值应出现在单行中。

例如,在我的输入表中,“DAPPUDRAFT_194440”在表中出现了 2 次,并且它在一行中有两个值“温度”,第二行有“磷”,如此处的数据子集所示:

 DAPPUDRAFT_194440   Phosphorous     
 DAPPUDRAFT_194440   Temperature  

我希望看到的是:“DAPPUDRAFT_”应该只出现一次,并且两个条目“温度”和“磷”应该出现在同一行中,并用选项卡分隔,如下所示:

 DAPPUDRAFT_194440   Phosphorous   Temperature  

预期输出:

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 

我尝试使用 R 中的“reshape2”包和 dcast 函数。但它所做的事情与我想要的完全不同。命令行、R 或 perl 有没有办法可以帮助解决这个问题?

答案1

简单地与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- 捕获记录的副本

  • sub($1,"",r)- 删除副本中的第一个字段以将剩余字段存储在r变量中

  • a[$1]=(a[$1])? a[$1]"\t"r : r- 累积相同的值团体(由第1场提出)

  • for(i in a)- 迭代所有分组的项目

  • gsub(/[[:space:]]{2,}/," ",a[i])- 删除单词之间过多的空格

  • print i,a[i]- 打印组名称及其值


输出:

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 

答案2

或者

$ 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

答案3

如果您不关心行和元素的排序方式:

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

对于非 GNU,sed将 替换\t为文字 TAB。

相关内容