这是我的输入文件:
Region_1 Region_1276
Region_2 Region_47
Region_3 Region_50
Region_1 Region_14
Region_50 Region_1
Region_27 Region_4
Region_12 Region_4
这就是我想要的输出:
Region_1 Region_1276 Common_0
Region_2 Region_47 Common_1
Region_3 Region_50 Common_2
Region_1 Region_14 Common_0
Region_50 Region_1 Common_3
Region_27 Region_4 Common_4
Region_12 Region_4 Common_4
目标:我想为输入中的每一行添加一个具有唯一ID的新列。问题是有时第一列有一个重复的值,在我的例子中,column1中的“Region_1”有两行。因此,这两行的ID必须相同(输出中的Common_0)。它与第二列的情况相同。如果第2列具有重复值,则ID必须相同(Common_4)。我白天一直在努力,但这是我最接近的代码,而且距离解决方案还很远:
awk -v c=0 '{a[$1]++}END{for(x in a){if(a[x]>1){for(i=1;i<=a[x];i++){print x"\tCommon_"c}}else{print x"\tCommon_"c};c++}}'
输出我的代码:
Region_27 Common_0
Region_12 Common_1
Region_1 Common_2
Region_1 Common_2
Region_50 Common_3
Region_2 Common_4
Region_3 Common_5
这不好,因为它只评估column1,而且我没有得到print column2。
答案 0 :(得分:1)
如果你把它放入a.awk
col = sys.argv[1]
db[col].find()
你做了
{
if (a[$1])
print $0 a[$1]
else if (b[$2])
print $0 b[$2]
else {
print $0 " common_" c
a[$1] = b[$2] = " common_" c
c++
}
}
您将获得所需的结果
awk -f a.awk -v c=0 foo.txt | column -t
答案 1 :(得分:1)
使用perl
我会像这样解决它:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my %id_for;
my $count = 0;
while ( <> ) {
chomp;
my ( $R1, $R2 ) = split;
my $id = $id_for{$R1} // $id_for{$R2} // $count++;
$id_for{$R1} //= $id;
$id_for{$R2} //= $id;
print join ( "\t", $R1, $R2, "common_".$id_for{$R1} ), "\n";
}
这并不是你想要的,因为我得到了:
Region_1 Region_1276 common_0
Region_2 Region_47 common_1
Region_3 Region_50 common_2
Region_1 Region_14 common_0
Region_50 Region_1 common_2
Region_27 Region_4 common_3
Region_12 Region_4 common_3
因为它将该区域1与单个列表进行匹配。这是否意味着你有两个名单?
E.g:
#!/usr/bin/env perl
use strict;
use warnings;
my %column_A;
my %column_B;
my $count = 0;
while ( <> ) {
chomp;
my ( $R1, $R2 ) = split;
my $id = $column_A{$R1} // $column_B{$R2} // $count++;
$column_A{$R1} //= $id;
$column_B{$R2} //= $id;
print join ( "\t", $R1, $R2, "Common_".$id ), "\n";
}
这会创建一个看起来像您想要的输出的列表:
Region_1 Region_1276 Common_0
Region_2 Region_47 Common_1
Region_3 Region_50 Common_2
Region_1 Region_14 Common_0
Region_50 Region_1 Common_3
Region_27 Region_4 Common_4
Region_12 Region_4 Common_4
答案 2 :(得分:1)
一般情况下,这不能线性完成,需要构建图表。
例如,如果我有
Region_A Region_B
Region_C Region_D
然后从表面上看,我有两个独立的记录,你给出的解决方案应用了两个不同的ID。但如果我那么
Region_C Region_B
然后统一前两个记录,他们需要给出相同的ID
这是使用Graph
模块的解决方案。我已将上面的情况添加到示例数据的末尾,以证明它按预期工作。如果您不需要按照输入数据的顺序分配ID,或者您希望以与输入不同的顺序输出分配,那么可以使用更简单的解决方案
use strict;
use warnings 'all';
use Graph;
my @data = <DATA>;
chomp @data;
my $g = Graph::Undirected->new(vertices => \@data, );
my @vertices = $g->vertices;
for my $i ( 0 .. $#vertices ) {
for my $j ( $i+1 .. $#vertices ) {
my @ri = split ' ', $vertices[$i];
my @rj = split ' ', $vertices[$j];
if ( $ri[0] eq $rj[0] or $ri[1] eq $rj[1]) {
$g->add_edge($vertices[$i], $vertices[$j]);
}
}
}
my %group;
{
my $n = 0;
for my $set ( $g->connected_components ) {
$group{$_} = $n for @$set;
++$n;
}
}
my @ids;
my $n = 0;
for ( @data ) {
printf "%-16s%-16s%-16s\n", split, $ids[$group{$_}] //= 'common_' . $n++;
}
__DATA__
Region_1 Region_1276
Region_2 Region_47
Region_3 Region_50
Region_1 Region_14
Region_50 Region_1
Region_27 Region_4
Region_12 Region_4
Region_A Region_B
Region_C Region_D
Region_C Region_B
Region_1 Region_1276 common_0
Region_2 Region_47 common_1
Region_3 Region_50 common_2
Region_1 Region_14 common_0
Region_50 Region_1 common_3
Region_27 Region_4 common_4
Region_12 Region_4 common_4
Region_A Region_B common_5
Region_C Region_D common_5
Region_C Region_B common_5