我在文件中有一个数字列表,每行一个。我怎样才能得到最小值,最大值,中位数和平均的价值观?我想在 bash 脚本中使用结果。
尽管我当前的情况是针对整数,但浮点数的解决方案最终会很有用,但简单的整数方法就可以了。
答案1
与GNU数据混合:
$ printf '%s\n' 1 2 4 | datamash max 1 min 1 mean 1 median 1
4 1 2.3333333333333 2
答案2
您可以使用R编程语言。
这是一个快速但肮脏的 R 脚本:
#! /usr/bin/env Rscript
d<-scan("stdin", quiet=TRUE)
cat(min(d), max(d), median(d), mean(d), sep="\n")
请注意,"stdin"
其中scan
是从标准输入(即从管道或重定向)读取的特殊文件名。
现在您可以通过 stdin 将数据重定向到 R 脚本:
$ cat datafile
1
2
4
$ ./mmmm.r < datafile
1
4
2
2.333333
也适用于浮点:
$ cat datafile2
1.1
2.2
4.4
$ ./mmmm.r < datafile2
1.1
4.4
2.2
2.566667
如果您不想编写 R 脚本文件,您可以使用以下命令在命令行中调用真正的单行代码(仅使用换行符以提高可读性)Rscript
:
$ Rscript -e 'd<-scan("stdin", quiet=TRUE)' \
-e 'cat(min(d), max(d), median(d), mean(d), sep="\n")' < datafile
1
4
2
2.333333
阅读精美的 R 手册:http://cran.r-project.org/manuals.html。
不幸的是,完整的参考资料仅提供 PDF 版本。阅读参考文献的另一种方法是输入?topicname
交互式 R 会话的提示。
为了完整起见:有一个 R 命令可以输出您想要的所有值以及更多值。不幸的是,采用人类友好的格式,很难以编程方式解析。
> summary(c(1,2,4))
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.000 1.500 2.000 2.333 3.000 4.000
答案3
实际上,我保留了一个 awk 程序来给出单列数字数据(包括负数)的总和、数据计数、最小数据、最大数据、平均值和中位数:
#!/bin/sh
sort -n | awk '
BEGIN {
c = 0;
sum = 0;
}
$1 ~ /^(\-)?[0-9]*(\.[0-9]*)?$/ {
a[c++] = $1;
sum += $1;
}
END {
ave = sum / c;
if( (c % 2) == 1 ) {
median = a[ int(c/2) ];
} else {
median = ( a[c/2] + a[c/2-1] ) / 2;
}
OFS="\t";
print sum, c, ave, median, a[0], a[c-1];
}
'
上面的脚本从标准输入读取,并在一行上打印制表符分隔的输出列。
答案4
使用 awk 很容易获得最小值、最大值和平均值:
% echo -e '6\n2\n4\n3\n1' | awk 'NR == 1 { max=$1; min=$1; sum=0 }
{ if ($1>max) max=$1; if ($1<min) min=$1; sum+=$1;}
END {printf "Min: %d\tMax: %d\tAverage: %f\n", min, max, sum/NR}'
Min: 1 Max: 6 Average: 3,200000
计算中位数有点棘手,因为您需要对数字进行排序并将它们全部存储在内存中一段时间或读取它们两次(第一次计算它们,第二次 - 获取中值)。这是将所有数字存储在内存中的示例:
% echo -e '6\n2\n4\n3\n1' | sort -n | awk '{arr[NR]=$1}
END { if (NR%2==1) print arr[(NR+1)/2]; else print (arr[NR/2]+arr[NR/2+1])/2}'
3