【问题标题】:Finding minimum and maximum values of the first column - grouped by the second column查找第一列的最小值和最大值 - 按第二列分组
【发布时间】:2013-05-06 14:23:15
【问题描述】:

我在文本文件中有很多未排序的数据,格式如下:

1.0 10
1.8 10
1.1 10
1.9 20
2.8 20
2.1 20
2.9 20
...

对于第二列中的每个值,我想获取第一列中值的区间。所以对于上面的例子,结果应该是

1.0 1.8 10
1.9 2.9 20

如何使用 c/c++、awk 或其他 linux shell 工具做到这一点?

【问题讨论】:

  • 现在问题应该很清楚了。

标签: linux shell awk


【解决方案1】:

你可以使用这个 awk:

awk '{
        if (!($2 in nmin) || $1<nmin[$2])
            nmin[$2]=$1;
         else if ($1>=nmax[$2])
            nmax[$2]=$1
     }
     END {
        for (a in nmin)
           print nmin[a], nmax[a], a
     }
' inFile

【讨论】:

  • 小修改:{ if (!($2 in nmin) || $1=nmax[$2]) nmax[$2]=$1; } END{ for (a in nmin){ if(!nmax[a]) print nmin[a], nmin[a], a;否则打印 nmin[a], nmax[a], a; } }
【解决方案2】:

这个单线应该适合你:

 awk '!($2 in i){i[$2]=$1}{a[$2]=$1}END{for(x in i)print i[x],a[x],x}' file

输出:

1.0 1.8 10
1.9 2.9 20

【讨论】:

  • @Dong 仅供参考,它适用于您当前的输入(已经排序)。但是,如果输入尚未排序,则它将不起作用。
  • 对,所以数据应该先排序。
【解决方案3】:

我认为这应该可行:

{ read vStart int &&
while read vNext nextInt; do
  if [ $int -ne $nextInt ]; then
    echo "$vStart $v $int";
    vStart=$vNext;
  fi

  v=$vNext;
  int=$nextInt;
done &&
echo "$vStart $v $int"; }

【讨论】:

  • @Dong:对,但在原始问题中,输入集已经排序(意外?)
【解决方案4】:

要添加另一种选择,您也可以在 R 中执行此操作:

d.in <- read.table(file = commandArgs(trailingOnly = T)[1]);
write.table(
    aggregate(V1 ~ V2, d.in, function (x) c(min(x),max(x)))[,c(2,1)]
    , row.names = F
    , col.names = F
    , sep = "\t");

然后用Rscript调用这个脚本:

$ Rscript script.R data.txt 
1       1.8     10
1.9     2.9     20

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多