如何使用awk统计指定列中排除-9缺失值的正负数出现次数
awk统计多列正负数(排除-9缺失值)
问题场景
待处理的文本文件结构如下,前两列是FID、IID标识,从第三列开始是数值型数据:
FID IID data1 data2 data3 1 RQ00001-2 1.670339 -0.792363849 -0.634434791 2 RQ00002-0 -0.238737767 -1.036163943 -0.423512414 3 RQ00004-9 -0.363886913 -0.98661685 -0.259951265 3 RQ00004-9 -9 -0.98661685 0.259951265
统计规则:
- 分别统计每个数据列的正数、负数出现次数
- 值为
-9代表缺失值,不计入负数统计 - 示例数据预期统计结果:
- data1列:1个正数、2个负数
- data2列:1个正数、3个负数
- data3列:1个正数、3个负数
之前使用的正则匹配负号的命令存在缺陷,会把缺失值-9也统计为负数:
awk '$3 ~ /^-/{cnt++} END{print cnt}' filename.txt
可直接使用的awk实现
awk ' NR == 1 { for (i = 3; i <= NF; i++) col[i] = $i next } { for (i = 3; i <= NF; i++) { v = $i if (v == -9) continue v > 0 ? pos[i]++ : neg[i]++ } } END { printf "%-8s %-8s %-8s\n", "列名", "正数数", "负数数" for (i = 3; i <= NF; i++) { printf "%-8s %-8d %-8d\n", col[i], pos[i]+0, neg[i]+0 } } ' filename.txt
逻辑说明
- 第一行(
NR==1)是表头,先把第三列开始的列名存到数组里,直接跳过不做统计 - 逐行遍历数据时,从第三列开始逐个取值:
- 遇到值等于
-9直接跳过,不做计数 - 值大于0就给对应列的正数计数器加1,小于0就给负数计数器加1
- 遇到值等于
- 最后格式化输出结果,计数器后加
+0是为了避免某类计数为0时输出空值,保证输出格式对齐
运行上述命令处理示例文件,会输出和预期完全一致的统计结果。
内容的提问来源于stack exchange,提问作者AvniKaur
相关产品推荐
相关产品推荐

