在 Bash 中计算百分位数

arn*_*pry 5 unix bash statistics awk

我正在尝试为Bash包含 5 个值(每行一个)的文本文件计算百分位数范围(第 5-99 个)。

输入

34.5
32.2
33.7
30.4
31.8
Run Code Online (Sandbox Code Playgroud)

尝试的代码

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

预期产出

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
Run Code Online (Sandbox Code Playgroud)

das*_*h-o 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
Run Code Online (Sandbox Code Playgroud)

从技术上讲是一个bash脚本,但基于对OP的注释,最好将整个想法放入script.awk中,并作为一行执行。解决方案有“#!” 调用 awk 脚本。

/path/to/script.awk < input 
Run Code Online (Sandbox Code Playgroud)