如何在Linux环境下使用AWK按Continent分组计算CSV文件第二列的Median值
如何在Linux环境下使用AWK按Continent分组计算CSV文件第二列的Median值
我来帮你解决这个问题!你之前的脚本没能得到正确结果,核心问题在于没有对数据按大洲分组存储,也没有先对每组的Ratio排序——毕竟计算中位数的前提是数据有序嘛。咱们一步步来搞定:
第一步:先对CSV数据排序
首先得把原始CSV按Continent分组,同时让每个组内的Ratio按数值排序。用Linux的sort命令就能轻松实现:
sort -t',' -k1,1 -k2,2n input.csv > sorted.csv
命令解释:
-t',':指定CSV的分隔符是逗号-k1,1:按第一列(Continent)进行排序,保证同大洲的行排在一起-k2,2n:按第二列(Ratio)做数值排序,这样每个大洲的Ratio就是有序的了
执行完这条命令后,sorted.csv就会变成你期望的有序格式。
第二步:用AWK脚本分组计算中位数
接下来编写一个AWK脚本(比如命名为calculate_median.awk),处理排序后的文件,按大洲分组计算中位数:
BEGIN { FS = "," # 设置输入分隔符为逗号 OFS = "," # 设置输出分隔符为逗号 print "Continent,Median" # 输出结果的表头 } # 跳过排序后文件的表头行 FNR == 1 { next } # 按大洲分组存储Ratio数据 { # 把当前行的Ratio存入对应大洲的数组,count数组记录每个大洲的数据条数 data[$1][++count[$1]] = $2 } END { # 遍历每个大洲,计算并输出中位数 for (continent in data) { total = count[continent] if (total % 2 == 1) { # 数据条数为奇数时,取中间位置的数值 median = data[continent][(total + 1)/2] } else { # 数据条数为偶数时,取中间两个数的平均值 median = (data[continent][total/2] + data[continent][total/2 + 1]) / 2 } # 格式化输出,保留四位小数,和你期望的结果格式一致 printf "%s,%.4f\n", continent, median } }
第三步:运行脚本得到结果
把排序后的文件作为输入传给AWK脚本即可:
awk -f calculate_median.awk sorted.csv
如果你不想生成中间的sorted.csv文件,也可以把排序和AWK命令合并成一行,直接输出结果:
sort -t',' -k1,1 -k2,2n input.csv | awk -f calculate_median.awk
运行后你就能得到期望的结果:
Continent,Median Africa,2.2513 Asia,3.1764 Europe,0.8286 Latin America and the Caribbean,1.4165
为什么你之前的脚本不行?
你之前的代码把所有Ratio都放到了同一个数组a里,没有按大洲分组,而且数据是无序的,自然无法计算出每个大洲的中位数。现在的方案先排序保证每组数据有序,再用二维数组按大洲存储数据,就能精准计算每组的中位数啦。
备注:内容来源于stack exchange,提问作者Takawako
相关产品推荐
相关产品推荐

