如何编写awk命令为分组重复行追加组内标准差列?
原脚本的问题
- 第一趟遍历文件时,仅对分组的第三列值做了求和存储,没有留存计算标准差必须的组内元素个数、数值平方和,缺少核心统计量。
- 第二趟遍历文件时,没有按分组组合隔离计算状态,全局的均值、离均差平方和变量未按组重置,所有行的数值被混在一起计算,完全失去分组逻辑。
- 输出环节没有按分组匹配追加对应的标准差,也没有按要求控制小数位数、替换小数点格式。
可直接运行的awk实现
awk 'BEGIN{ FS = OFS = "\t" } # 第一遍读文件:按前两列的组合为key,累计基础统计值 NR == FNR { grp_key = $1 SUBSEP $2 grp_cnt[grp_key] += 1 grp_sum[grp_key] += $3 grp_sq[grp_key] += $3 * $3 next } # 第二遍读文件:逐行计算对应分组的标准差,追加到行尾输出 { grp_key = $1 SUBSEP $2 n = grp_cnt[grp_key] # 样本标准差公式,计算结果和示例完全匹配 std_val = sqrt( (grp_sq[grp_key] - grp_sum[grp_key] * grp_sum[grp_key] / n) / (n - 1) ) # 保留两位小数,将小数点替换为逗号,匹配示例格式 $4 = sprintf("%.2f", std_val) gsub(/\./, ",", $4) print $0 } ' 你的数据文件 你的数据文件
计算结果校验
逐组核对输出值,和给出的期望结果完全一致:
- 分组
1 aaa:第三列值为1、3、5,计算得标准差2.00,输出为2,00 - 分组
1 ccc:第三列值为9、2、2,计算得标准差≈4.04,输出为4,04 - 分组
1 ddd:第三列值为4、6、8、1,计算得标准差≈2.99,输出为2,99 - 分组
2 ddd:第三列值为5、12、13,计算得标准差≈4.36,输出为4,36
可调参数说明
- 当前脚本计算的是样本标准差(除以n-1),如果需要计算总体标准差(除以n),只需把公式里的
n-1替换为n即可。 - 脚本全程保留原文件的行顺序,不打乱原有数据排列,仅在每行末尾追加对应组的标准差。
- 输出默认用逗号作为小数分隔符,保留两位小数,如果需要换回点号作为小数点,删掉脚本里的
gsub那行即可。
内容的提问来源于stack exchange,提问作者ersan
相关产品推荐
相关产品推荐

