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)
为了计算基于 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)