如何使用AWK计算一列数值数据的中位数?
我可以想到一个简单的算法,但我似乎无法编程:
到目前为止我所拥有的是:
sort | awk 'END{print NR}'
这给了我列中元素的数量。我想用它来打印某一行(NR/2)
。如果NR/2
不是整数,那么我向上舍入到最接近的整数,这是中位数,否则我取(NR/2)+1
和(NR/2)-1
的平均值。
答案 0 :(得分:18)
此awk
程序假定一列数字排序数据:
#/usr/bin/env awk
{
count[NR] = $1;
}
END {
if (NR % 2) {
print count[(NR + 1) / 2];
} else {
print (count[(NR / 2)] + count[(NR / 2) + 1]) / 2.0;
}
}
样本用法:
sort -n data_file | awk -f median.awk
答案 1 :(得分:16)
使用awk
,您必须将值存储在数组中并计算最后的中位数,假设我们查看第一列:
sort -n file | awk ' { a[i++]=$1; } END { print a[int(i/2)]; }'
当然,对于实际中值计算,请按照问题中描述的进行舍入:
sort -n file | awk ' { a[i++]=$1; }
END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'
答案 2 :(得分:1)
This AWK based answer对unix.stackexchange.com上的类似问题给出与Excel相同的结果来计算中位数。
答案 3 :(得分:1)
如果你有一个数组来计算中位数(包含Johnsyweb解决方案的一行):
array=(5 6 4 2 7 9 3 1 8) # numbers 1-9
IFS=$'\n'
median=$(awk '{arr[NR]=$1} END {if (NR%2==1) print arr[(NR+1)/2]; else print (arr[NR/2]+arr[NR/2+1])/2}' <<< sort <<< "${array[*]}")
unset IFS
答案 4 :(得分:1)
好的,刚刚看到这个主题,并认为我可以加上我的两分钱,因为我在过去寻找类似的东西。即使标题显示为awk
,所有答案也会使用sort
。使用datamash:
> seq 10 | datamash median 1
5.5
请注意,即使您有未排序的列,也不需要sort
:
> seq 10 | gshuf | datamash median 1
5.5
文档提供了它可以执行的所有功能,以及包含许多列的文件的良好示例。无论如何,它与awk
无关,但我认为datamash
在这种情况下有很大帮助,也可以与awk
一起使用。希望它对某人有帮助!