首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用unix工具(不诉诸R),如何根据分组的一些统计信息过滤行?

使用unix工具(不诉诸R),如何根据分组的一些统计信息过滤行?
EN

Stack Overflow用户
提问于 2014-09-21 10:10:14
回答 4查看 118关注 0票数 1

我想过滤下表中的行,以便从下面的表格中筛选出来:

代码语言:javascript
复制
A   1   3   SOME_OTHER_INFO
A   1   4   SOME_OTHER_INFO2
A   2   5   SOME_OTHER_INFO3
B   1   1   SOME_OTHER_INFO4
B   2   3   SOME_OTHER_INFO4
B   2   0   SOME_OTHER_INFO4

对此:

代码语言:javascript
复制
A   1   3   SOME_OTHER_INFO
A   2   5   SOME_OTHER_INFO3
B   1   1   SOME_OTHER_INFO4
B   2   0   SOME_OTHER_INFO4

过滤标准是:

1)根据前2列对行进行分组。

2)然后,对于每个组,选择第三列在组内最小的行。

3)返回。

现在,在R中使用包(如使用以下命令的plyr )可以很容易地执行这样的操作:

代码语言:javascript
复制
ddply(data, .(first_col, second_col), function(x) { 
                min_idx = which.min(x$third_col); 
                return(x[min_idx]) 
                })

但是,我想知道是否有一种使用命令行上的unix工具的高效而优雅的方法。

最后,我几乎找到了使用datamash的漂亮解决方案,这是最近在GNU中发布的一个工具,但有一些小问题。

代码语言:javascript
复制
$ datamash -g 1,2 min 3 -f < file.txt | cut -f1-4

A 1 3 SOME_OTHER_INFO1
A 2 5 SOME_OTHER_INFO3
B 1 1 SOME_OTHER_INFO4
B 2 3 SOME_OTHER_INFO4 # <-- not the correct row I want to grab

问题是当使用"-f“标志时,它从每个组抓取第一个项,而不是min对应的行。因此,如果您查看上面的输出,“B2 3 SOME_OTHER_INFO4”被选中,而不是“B2 0 SOME_OTHER_INFO4”。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-09-21 17:58:56

下面是使用perl的几个更多选项:

代码语言:javascript
复制
perl -MList::Util=min -lane'
  $h{"@F[0,1]"}{$F[2]} = $_ 
}{
  print $h{$_}{ min keys %{$h{$_}} } for sort keys %h
' file
A   1   3   SOME_OTHER_INFO
A   2   5   SOME_OTHER_INFO3
B   1   1   SOME_OTHER_INFO4
B   2   0   SOME_OTHER_INFO4
  • 创建一个哈希哈希,内键作为前两列,外键作为第三列。
  • 使用核心模块min方法获取最小的外键并打印值,这是整个行。

或者没有核心模块:

代码语言:javascript
复制
perl -lane'
    push @{ $h{"@F[0,1]"} }, [$F[2], $_] 
}{ 
    print $_->[1] for sort map { 
        (sort { $a->[0] <=> $b->[0] } @$_)[0] 
    } values %h
' file
A   1   3   SOME_OTHER_INFO
A   2   5   SOME_OTHER_INFO3
B   1   1   SOME_OTHER_INFO4
B   2   0   SOME_OTHER_INFO4
  • 创建数组的散列,使用键作为前两列,值作为第三列和整行的数组。
  • 根据数组的第一个元素按值和排序提取散列项。
  • 使用片,只需获取第一个最小的条目,并打印第二个元素,即整行。
票数 2
EN

Stack Overflow用户

发布于 2014-09-21 10:49:30

不知道你所说的有效率还是优雅,但这似乎是你想要的:

代码语言:javascript
复制
sort -k1 -k2,3n file.txt | rev | uniq -f 2 | rev

如果双rev被认为是不雅的(或者实际列数不同,在这种情况下它将无法工作),

代码语言:javascript
复制
sort -k1 -k2,3n file.txt | perl -wane'print if $.==1 || $F[0] ne $last[0] || $F[1] != $last[1]; @last=@F'
票数 1
EN

Stack Overflow用户

发布于 2014-09-21 13:36:55

如果您能够按正确的顺序排序行,那么只打印组中的第一行的简单的Awk过滤器应该可以工作。

代码语言:javascript
复制
sort -k1 -k2n -k3n file.txt |
awk '!a[$1 $2]++'

Awk脚本使用前两个字段中的键填充数组a,只有当它看到新键时才会打印。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25958105

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档