在Bash中计算百分位数(s)

5

我想在 Bash 中计算一个文本文件中的一系列百分位数(第 5-99 个百分位数),其中每行包含 5 个值。

输入

34.5
32.2
33.7
30.4
31.8

尝试的代码

awk '{s[NR-1]=$1} END{print s[int(0.05-0.99)]}' input

期望的输出结果

99th    34.5
97th    34.4
95th    34.3
90th    34.2
80th    33.9
70th    33.4
60th    32.8
50th    32.2
40th    32.0
30th    31.9
20th    31.5
10th    31.0
5th     30.7

2
请在您的问题中发布预期输出。 - RavinderSingh13
1
请分享您已经完成的内容。同时,请以文本格式发布输出,而不是图像。 - dash-o
@arnpry,请查看此线程https://dev59.com/Z4Hba4cB1Zd3GeqPRXRt,如果这对您有帮助? - RavinderSingh13
3
你发布的是一个 awk 脚本,而不是 bash 脚本。你正在 awk 中计算百分位数,而不是在 bash 中。 - Ed Morton
2
没关系,你可以在ksh、dash、Windows或任何其他操作系统中运行它。你所尝试的事情与bash没有任何关系,解决方案也和bash无关。在这个问题中提到bash就像提到你正在使用的电脑品牌一样有用。如果你在问题中提供了你想要用来计算百分位数的算法,我相信有人可以帮助你用awk编写出来。 - Ed Morton
显示剩余2条评论
1个回答

4

计算基于5个值的百分位数,需要创建一个将百分位数映射到它们之间插值的过程。这个过程称为“分段线性函数”(也称为pwlf)。

F(100) = 34.5 F(75) = 33.7 F(50) = 32.2 F(25) = 31.8 F(0) = 30.4

对于范围在0..100内的任何其他x的映射,需要在线性插值F(L)和F(H)之间 - 其中L是最接近x的最高值,并且H=L+1。

awk '
#! /bin/env awk
  # PWLF Interpolation function, take a value, and two arrays for X & Y
function pwlf(x, px, py) {
  # Shortcut to calculate low index of X, >= p
  p_l = 1+int(x/25)
  p_h = p_l+1
  x_l = px[p_l]
  x_h = px[p_h]
  y_l = py[p_l]
  y_h = py[p_h]
#print "X=", x, p_l, p_h, x_l, x_h, y_l, y_h
  return y_l+(y_h-y_l)*(x-x_l)/(x_h-x_l)
}

  # Read f Input in yy array, setup xx
{ yy[n*25] = $1  ; n++ }

  # Print the table
END {
  # Sort values of yy
  ny = asort(yy) ;
  # Create xx array 0, 25, ..., 100
  for (i=1 ; i<=ny ; i++) xx[i]=25*(i-1)

  # Prepare list of requested results
  ns = split("99 97 95 90 80 70 60 50 40 30 20 10 5", pv)
  for (i=1 ; i<=ns ; i++) printf "%dth %.1f\n",  pv[i], pwlf(pv[i], xx, yy) ;
}
' input

从OP的评论看来,最好将整个脚本放到script.awk中,并作为一行执行。 解决方案具有“#!”来调用awk脚本。 实际上是一个bash脚本。
/path/to/script.awk < input 

1
就“技术上讲,这是一个bash脚本”的说法而言——该脚本中没有任何部分属于bash。我只是想强调,因为很多人会将awk与shell混淆。顺便说一句,尝试的shebang实际上什么也没做,它只是awk脚本内的注释。 - Ed Morton
1
你能提供仅限于Bash的脚本吗? - arnpry
@arnpry 原始帖子在技术上是一个bash解决方案。拥有“纯bash”解决方案非常困难,因为bash不支持浮点数计算。 - dash-o
1
引用在任何允许将单引号脚本传递给解释工具的shell或其他环境中都可以工作,你的回答并不需要bash。而且,再次强调,#!只是awk脚本内的注释,它在功能上没有任何作用。 - Ed Morton
1
它是100 /(n-1),其中n是点的数量,对于特定问题为5。 - dash-o
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接