这是我的输入文件(有数千行):
$ cat file.txt
1 495.03
2 503.76
3 512.28
4 520.75
5 529.17
我想用awk
来计算第一列的中位数(比如1-100)行数和第二列相应值的平均值。然后awk
将移动下一组行(101-201)并执行相同操作,即第一列的中位数和第二列的平均值,依此类推。毋庸置疑,我正在努力学习awk
并尝试了以前的几种解决方案,但却无法使其发挥作用。
从之前的post开始,我发现我可以通过这种方式计算平均值:
awk '{sum+=$1} NR%3==0 {print sum/3; sum=0}'
这是如何工作的(即{sum+=$1}
表达式是什么意思?)以及如何将其调整为中位数?顺便说一句,第一列将始终排序。
提前致谢, TP
答案 0 :(得分:2)
如果记录已排序,则中位数只是 <script async
src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Wide Responsive Ad (White) -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-4269714478926007"
data-ad-slot="1264409627"
data-ad-format="link"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
和50
st值的平均值。
51
如果记录数是100的倍数,这将有效,否则您需要处理具有不同大小的最后一个组。
&#34;中位数&#34;还有其他定义。对于偶数个记录,但这是你应该指定的东西。
解释将$ awk '{r=NR%100; sum+=$2}
r==50 {m=$1}
r==51 {m=(m+$1)/2}
r==0 {print m, sum/100; sum=0}' file
定义为mod 100的余数,实质上是100个记录的每个块中的相对位置。对于中位数,我们取第50和第51条记录的平均值,r
汇总每100个块的第二个字段值。当余数为0时,我们完成每个块,打印中位数和平均值(sum / 100);为下一个块重置sum
。
答案 1 :(得分:2)
注意::其中包含有关运行方式和未排序数据中位数的更多信息。这应该被视为原始问题的附录。
如果您要计算最近 n 个词的运行平均值(假设 n = 100 ),则必须注意如何处理第一个 > m 记录,其中包含 m
$i
的移动平均值:
awk '{a[NR%100] = $i; s=0; for(j in a) { s+=a[j] }; print "avg:" s/length(a) }'
但是,您可以通过跟踪for
来删除s
循环:
awk '{s+=$i; if (NR%100 in a) s-=a[NR%100]; a[NR%100]=$i; print "avg:" s/length(a) }'
运行$i
的中位数:
可以使用gawk
完成一种计算中位数的方法,其中我们假定该数组按值进行数组遍历排序
awk 'BEGIN{ PROCINFO["sorted_in"]="@val_num_asc" }
{ a[NR%100] = $i }
{ k=0; m=0;
for(j in a) { k++
if (k >= length(a)/2 ) m+=a[j]
if (k <= length(a)/2+1) {m+=a[j]; break }
}
print "med:", m/2
}'
或者如果您希望在if-conditions上轻一点
awk 'BEGIN{ PROCINFO["sorted_in"]="@val_num_asc" }
{ a[NR%100] = $i }
{ k=0; m=0;
for(j in a) { k++
if (k < length(a)/2 ) continue
if (k > length(a)/2+1) break
m+=a[j]
}
print "med:", (length(a)%2==0 ? m/2 : m)
}'
如果您不想使用预先排序的概念,则中位数的计算将变得更加困难。一种可能的方式是使用selection algorithm,如here所述。