如何将列转置到$ 1字段相同的行?

时间:2014-02-20 13:10:09

标签: perl unix sed awk

我有一个包含两列的文件:

PLEKHN1   1:901922:G:A
PLEKHN1   1:901923:C:A
PLEKHN1   1:902088:G:A
HES4   1:934735:A:C
HES4   1:934770:G:A

我想在$1中的字段相同的位置将列转置为行,同时仅为每个转置组保留第一次出现的$1值。

Desired output:

PLEKHN1   1:901922:G:A   1:901923:C:A   1:902088:G:A
HES4   1:934735:A:C   1:934770:G:A

谢谢。

6 个答案:

答案 0 :(得分:2)

如果数据按批量分组,您可以执行以下操作:

awk 'f!=$1 {printf RS$1} {printf "\t%s",$2;f=$1}' file

PLEKHN1 1:901922:G:A    1:901923:C:A    1:902088:G:A
HES4    1:934735:A:C    1:934770:G:A

如果开头的空白行很重要,最后一次点击则返回,请使用:

awk 'f!=$1 {printf (NR==1?"":RS)"%s",$1} {printf "\t%s",$2;f=$1} END {print ""}' file
PLEKHN1 1:901922:G:A    1:901923:C:A    1:902088:G:A
HES4    1:934735:A:C    1:934770:G:A

答案 1 :(得分:2)

如果订单很重要,那么您可以尝试以下方式:

awk '$1==p{l=l", "$2; next}{if(p) print p,l; p=$1;l=$2}END{print p,l}' file

这假设您不会出现第一列乱序。

答案 2 :(得分:1)

使用awk你可以说:

gawk '{o=""; for(i=2;i<=NF;i++) o = o $i "\t"; a[$1]=a[$1] o;} END {for (i in a) print i, a[i]}' OFS='\t' inputfile

为了您的输入,它会产生:

HES4    1:934735:A:C    1:934770:G:A
PLEKHN1 1:901922:G:A    1:901923:C:A    1:902088:G:A

答案 3 :(得分:1)

这是一个Perl解决方案。

将所有值放入哈希值,然后将其读回。

如果您需要维护第一列中值的顺序,那么添加一组键以记住此顺序是一个简单的修改。

该程序期望输入文件的路径作为命令行上的第一个参数。

use strict;
use warnings;

my %data;
while (<>) {
  my ($key, $val) = split;
  push @{ $data{$key} }, $val;
}

while (my ($key, $vals) = each %data) {
  print join('   ', $key, @$vals), "\n";
}

<强>输出

HES4   1:934735:A:C   1:934770:G:A
PLEKHN1   1:901922:G:A   1:901923:C:A   1:902088:G:A

<强>更新

Perl哈希本质上是无序的。要按照它们在原始文件中出现的顺序维护密钥,您只需在读取新密钥时保留它们的列表即可。这个修订后的计划证明了这一点。

use strict;
use warnings;

my %data;
my @keys;
while (<>) {
  my ($key, $val) = split;
  push @keys, $key unless $data{$key};
  push @{ $data{$key} }, $val;
}

for my $key (@keys) {
  my $vals = $data{$key};
  print join('   ', $key, @$vals), "\n";
}

<强>输出

PLEKHN1   1:901922:G:A   1:901923:C:A   1:902088:G:A
HES4   1:934735:A:C   1:934770:G:A

答案 4 :(得分:0)

perl -lane'
  $k = shift @F;
  $s{$k} or push @r, $k;
  push @{$s{$k}}, @F;
  END {
    $" = "\t";
    print "$_\t@{$s{$_}}" for @r;
  }
' file

输出

PLEKHN1 1:901922:G:A    1:901923:C:A    1:902088:G:A
HES4    1:934735:A:C    1:934770:G:A

答案 5 :(得分:0)

sed -n '
1 h
1 !{H;g;s/\([^ ]\{1,\}\) \{1,\}\(.*\)\n\1 \{1,\}/\1 \2 /;t same
   P;s/.*\n//
:same
   h;}
$ {x;p;}' YourFile

假设线条与样品中的第一个模式分组。您可以在不同的非连续组中具有相同的第一个模式,它将创建单独的行

(@ user2162153)如果文件中出现1,仍可正常工作

$ cat YourFile
AtStart  0:123456789:A:A
PLEKHN1   1:901922:G:A
PLEKHN1   1:901923:C:A
PLEKHN1   1:902088:G:A
HES4   1:934735:A:C
HES4   1:934735:A:C
midle  5:934735:M:M
HES5   1:934735:A:C
HES5   1:934735:A:C
AtEnd  9:934735:Z:Z
$ sed -n '
> 1 h
> 1 !{H;g;s/\([^ ]\{1,\}\) \{1,\}\(.*\)\n\1 \{1,\}/\1 \2 /;t same
>    P;s/.*\n//
> :same
>    h;}
> $ {x;p;}' YourFile

AtStart  0:123456789:A:A
PLEKHN1 1:901922:G:A 1:901923:C:A 1:902088:G:A
HES4 1:934735:A:C 1:934735:A:C
midle  5:934735:M:M
HES5 1:934735:A:C 1:934735:A:C
AtEnd  9:934735:Z:Z