计算每个变量的百分位数和最大值

时间:2016-11-09 10:14:20

标签: bash sorting awk percentile

Bash Gurus,我需要使用awk计算列表中每个项目的最大值和百分位数

aa  1
ab  3
aa  4
ac  5
aa  3
ad  2
ab  4
ac  2
ae  2
ac  5

预期输出

Item   90th percentile   max value
aa     3.8             4
ab     3.9             4
ac     5               5
ad     2               2
ae     2               2

能够使用以下内容获得总和和最大值,但不能使用百分位数。

awk '{
item[$1]++;
count[$1]+=$2;
max[$1]=$2;
percentile[$1,.9]=$2
 }
 END{
 for (var in item)
 print var,count[var],max[var],percentile[var]
 }
' 

请建议。

3 个答案:

答案 0 :(得分:2)

来自第二版的傻瓜数据的百分位数计算。 :)。在Gnu awk:

$ cat mnp.awk
BEGIN {
    PROCINFO["sorted_in"]="@ind_num_asc"   # for order in output
    if(p=="")                              # if p not defined it's median
        p=0.5
    else
        p=p/100                            # if 90th percentile: p=0.9
}
{
    v[$1][NR]=$2                           # values stored per keyword. NR for unique
    if($2>m[$1])                           # find max val
        m[$1]=$2
}
END {
    for(i in v) {                          # for all keywords
        n=asort(v[i])                      # sort values, n is count
        prc=p*n;                           # percentile figuration
        if(prc==int(prc))
            w=(v[i][prc]+v[i][prc+1])/2
        else
            w=v[i][int(prc)+1]
        print i, m[i], w                   # print keyword, max and nth value
    }
}

运行它:

$ awk -p=90 -f mnp.awk data.txt
aa 4 4
ab 4 4
ac 5 5
ad 2 2
ae 2 2

TODO:如果对数据文件进行了排序,则可以简化此操作,并且不需要将所有数据都存储到内存中。

答案 1 :(得分:1)

datamash是一个可爱的工具,虽然它不支持percantile部分。

$ datamash -W --sort --group=1 max 2 min 2 < INPUT
aa  4   1
ab  4   3
ac  5   2
ad  2   2
ae  2   2

它支持以下操作

File operations:
  transpose, reverse
Numeric Grouping operations:
  sum, min, max, absmin, absmax
Textual/Numeric Grouping operations:
  count, first, last, rand 
  unique, collapse, countunique
Statistical Grouping operations:
  mean, median, q1, q3, iqr, mode, antimode
  pstdev, sstdev, pvar, svar, mad, madraw
  pskew, sskew, pkurt, skurt, dpo, jarque

答案 2 :(得分:0)

这是一个优雅的解决方案,我发现在互联网上浮动以找到最大值:

{
  max[$1] = !($1 in max) ? $2 : ($2 > max[$1]) ? $2 : max[$1]
}
END {
  for (i in max)
    print i, max[i]
}

输出:

ab 4
ac 5
ad 2
ae 2
aa 4