我有一个文件,其中的条目由空格分隔。例如:
example.txt中
24676 256 218503341 2173
13236272 500 1023073758 5089
2230304 96 15622969 705
0 22 0 526
13277 28 379182 141
我想在命令行中打印“第1列/第3列”或“simila”的结果。我相信它可以用awk完成。但是,有些条目为0,因此除以0给出:
致命:除零尝试
在更高级的情况下,我想找到分部的中值(或某个百分位数)。
答案 0 :(得分:3)
有许多方法可以忽略具有零除数的行,包括:
awk '$3 != 0 { print $1/$3 }' your-data-file
awk '{ if ($3 != 0) print $1/$3 }' your-data-file
问题改变了 - 改为打印0。答案并不难:
awk '{ if ($3 != 0) print $1/$3; else print 0 }' your-data-file
中位数和其他百分位数要处理得更为谨慎。如果数据按排序顺序最简单。我希望使用数字排序然后从那里处理数据这么容易。
我挖出了一个旧的shell脚本来计算描述性统计数据 - 单个数据数据列的最小值,最大值,模式,中值和十进制:
: "@(#)$Id: dstats.sh,v 1.2 1997/06/02 21:45:00 johnl Exp $"
#
# Calculate Descriptive Statistics: min, max, median, mode, deciles
sort -n $* |
awk 'BEGIN { max = -999999999; min = 999999999; }
{ # Accumulate basic data
count[$1]++;
item[++n] = $1;
if ($1 > max) max = $1;
if ($1 < min) min = $1;
}
END { # Print Descriptive Statistics
printf("# Count = %d\n", n);
printf("# Min = %d\n", min);
decile = 1;
for (decile = 10; decile < 100; decile += 10)
{
idx = int((decile * n) / 100) + 1;
printf("# %d%% decile = %d\n", decile, item[idx]);
if (decile == 50)
median = item[idx];
}
printf("# Max = %d\n", max);
printf("# Median = %d\n", median);
for (i in count)
{
if (count[i] > count[mode])
mode = i;
}
printf("# Mode = %d\n", mode);
}'
min
和max
的初始值并非完全科学。它有助于说明一点。
(这个1997版本几乎与它的1991年版本相同 - 除了版本信息行之外所有版本都是相同的。所以,代码已经超过20年了。)
答案 1 :(得分:2)
这是一个解决方案:
awk '
$3 != 0 { vals[$NR]=$1/$3; sum += vals[$NR]; print vals[$NR] }
$3 == 0 { vals[$NR]=0; print "skipping division by 0" }
END { sort vals; print "Mean = " sum/$NR ", Median ~ " vals[$NR/2] }
' < your_file
如果3 rd 列不为零,这将计算,打印和累积商。当它到达你的文件的末尾(应该不有一个空行)时,它将打印所有商的均值和中位数,假设它将除以零的每一行为0
在awk
中,$n
表示n
th 字段,以1开头,$NR
表示记录数(即,已处理的行数)。每个商都存储在数组vals
中,使我们能够计算中值。
在现实生活中,中位数被定义为给定奇数元素的“中间”项目,或者给定偶数元素的两个“中间”项目的平均值。
在实施sort
功能时,你自己就可以了!