【问题标题】:Collapse rows based on column 1根据第 1 列折叠行
【发布时间】:2016-09-28 08:45:58
【问题描述】:

我想为 TopGO R 包解析 InterProScan 结果。

我想要一个格式与我所拥有的文件有点距离的文件。

# input file (gene_ID  GO_ID1, GO_ID2, GO_ID3, ....)
Q97R95  GO:0004349, GO:0005737, GO:0006561
Q97R95  GO:0004349, GO:0006561
Q97R95  GO:0005737, GO:0006561
Q97R95  GO:0006561


# desired output (removed duplicates and rows collapsed)
Q97R95  GO:0004349,GO:0005737,GO:0006561

您可以在此处使用整个数据文件测试您的工具:

https://drive.google.com/file/d/0B8-ZAuZe8jldMHRsbGgtZmVlZVU/view?usp=sharing

【问题讨论】:

  • 您编辑了您的问题,删除了标签 perl、shell 和 awk。你的意思是?这些答案将不再被接受还是什么?
  • 接受任何语言
  • 我们能否相信在输入中具有相同第一列的所有行都将彼此相邻(就像它们在您的示例中一样)?这让代码更有效率。
  • 问题仍未解决。 Kent 脚本与正确结果有少许偏差。只用一个 GO 术语就忘记了基因,除了重复的行。在上面的例子中,忘记了 'Q97R95 GO:0006561' 行,但结果仍然很好,因为 GO 术语 '0006561' 也在基因 'Q97R95' 的其他行中。
  • 是的@hobbs,我之前可以对输入文件进行排序。事实上,我给的大文件是排序的。

标签: python perl awk text-processing


【解决方案1】:

你可以使用二维的 gnu awk 数组:

awk -F'[, ]+' '{for(i=2;i<=NF;i++)r[$1][$i]}
         END{for(x in r){
                printf "%s ",x;b=0;
                for(y in r[x]){printf "%s%s",(b?",":""),y;b=1}
                print ""}
         }' file

它给出:

Q97R95 GO:0005737,GO:0006561,GO:0004349

重复的字段被删除,但没有保留顺序。

【讨论】:

  • @biotech 我在这里测试过,该行运行没有任何错误。你有 gnu awk 吗?
  • awk: {for(i=2;i
  • 我们需要第三个测试人员来复制可能的错误
  • 对我来说,它与 GNU awk 配合得很好。我用普通的 awk 得到语法错误。执行 awk --version 以确认您正在使用 GNU awk(例如,我的返回 GNU Awk 4.1.3, API: 1.1
  • 我有 GNU Awk 3.1.7
【解决方案2】:

这是一个希望整洁的 Perl 解决方案。它尽可能地保留键和值的顺序,并且不会将整个文件内容保留在内存中,仅保留完成工作所需的部分。

#!perl
use strict;
use warnings;

my ($prev_key, @seen_values, %seen_values);

while (<>) {
  # Parse the input
  chomp;
  my ($key, $values) = split /\s+/, $_, 2;
  my @values = split /,\s*/, $values;

  # If we have a new key...
  if ($key ne $prev_key) {
    # output the old data, as long as there is some,
    if (@seen_values) {
      print "$prev_key\t", join(", ", @seen_values), "\n";
    }
    # clear it out,
    @seen_values = %seen_values = ();
    # and remember the new key for next time.
    $prev_key = $key;
  }

  # Merge this line's values with previous ones, de-duplicating
  # but preserving order.
  for my $value (@values) {
    push @seen_values, $value unless $seen_values{$value}++;
  }
}

# Output what's left after the last line
if (@seen_values) {
  print "$prev_key\t", join(", ", @seen_values), "\n";
}

【讨论】:

  • 太棒了。 3665 个 ID,如 input.txt 文件中所示。我们没有失去基因,很好。
  • @biotech 进行了调整,使其匹配更准确。对于输入,它接受任何类型的空格。对于输出,它将使用制表符作为第一个分隔符,并使用“,”作为其余分隔符。
  • 不错,很优雅。事实上,我现在注意到我的输入文件有两个空格作为第一个分隔符。
  • @biotech 是的,这就是我实际模仿的。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多