命令行实用程序,用于打印 linux 中的数字统计信息
Posted
技术标签:
【中文标题】命令行实用程序,用于打印 linux 中的数字统计信息【英文标题】:command line utility to print statistics of numbers in linux 【发布时间】:2012-04-05 02:20:18 【问题描述】:我经常发现自己的文件每行有一个数字。我最终将其导入 excel 以查看中位数、标准差等内容。
在 linux 中有没有命令行工具可以做同样的事情?我通常需要找到平均值、中位数、最小值、最大值和标准偏差。
【问题讨论】:
这可能是相关的:***.com/questions/214363/…. 投票结束作为工具记录。 stats.stackexchange.com/questions/24934/… || serverfault.com/questions/548322/… unix.stackexchange.com/questions/13731/… 回答这个问题的人可能也对jp
, a CLI utility for making plots感兴趣。
unix.stackexchange.com/a/202889/44236
【参考方案1】:
这对 R 来说是一件轻而易举的事。对于一个看起来像这样的文件:
1
2
3
4
5
6
7
8
9
10
使用这个:
R -q -e "x <- read.csv('nums.txt', header = F); summary(x); sd(x[ , 1])"
要得到这个:
V1
Min. : 1.00
1st Qu.: 3.25
Median : 5.50
Mean : 5.50
3rd Qu.: 7.75
Max. :10.00
[1] 3.02765
-q
标志抑制了 R 的启动许可和帮助输出
-e
标志告诉 R 你将从终端传递一个表达式
x
是 data.frame
- 基本上是一张桌子。它是一种可以容纳多个向量/数据列的结构,如果您只是读取单个向量,这有点奇怪。这会影响您可以使用哪些功能。
一些函数,比如summary()
,自然会适应data.frames
。如果x
有多个字段,summary()
将为每个字段提供上述描述性统计信息。
但是sd()
一次只能取一个向量,这就是我为该命令索引x
的原因(x[ , 1]
返回x
的第一列)。您可以使用 apply(x, MARGIN = 2, FUN = sd)
获取所有列的 SD。
【讨论】:
谢谢。从那以后我开始使用 R,我认为它是理解数据的好工具 节省额外搜索如何在 Ubuntu 上获取 R:sudo apt-get install r-base
R 将来可能会更好地使用更多,但我猜这是一个巨大的库安装,所以我想安装下面的st
表单。与该评论无关,但我的brew install R
在 MacBook Pro Mid 2015 10.12.5 2.5GHz i7 16GB 上使用 Chrome、Atom 和其他应用程序打开了大约一个小时。其中大部分用于使用 Xcode CLT O_o 构建一些 gcc jit 补丁,但现在我很高兴使用这个答案的一部分:)
这是general data-wrangling with bash tools 上的一篇博文,发现此问题的人可能会感兴趣。【参考方案2】:
使用“st”(https://github.com/nferraz/st)
$ st numbers.txt
N min max sum mean stddev
10 1 10 55 5.5 3.02765
或者:
$ st numbers.txt --transpose
N 10
min 1
max 10
sum 55
mean 5.5
stddev 3.02765
(免责声明:我写了这个工具:))
【讨论】:
关于新手安装的任何信息 如果您使用自制软件安装,这就像brew install st
一样简单。
注意st
也可能引用simple terminal
。【参考方案3】:
对于平均值、中位数和标准差,您可以使用awk
。这通常比R
解决方案更快。例如,以下将打印平均值:
awk 'a+=$1 ENDprint a/NR' myfile
(NR
是记录数的awk
变量,$1
表示该行的第一个(空格分隔)参数($0
将是整行,这也可以在这里工作,但是原则上会不太安全,尽管对于计算它可能只需要第一个参数)和END
意味着在处理完整个文件后将执行以下命令(也可以将a
初始化为@ 987654330@ 在BEGINa=0
语句中))。
这是一个简单的 awk
脚本,它提供了更详细的统计信息(以 CSV 文件作为输入,否则更改 FS
):
#!/usr/bin/awk -f
BEGIN
FS=",";
a += $1;
b[++i] = $1;
END
m = a/NR; # mean
for (i in b)
d += (b[i]-m)^2;
e += (b[i]-m)^3;
f += (b[i]-m)^4;
va = d/NR; # variance
sd = sqrt(va); # standard deviation
sk = (e/NR)/sd^3; # skewness
ku = (f/NR)/sd^4-3; # standardized kurtosis
print "N,sum,mean,variance,std,SEM,skewness,kurtosis"
print NR "," a "," m "," va "," sd "," sd/sqrt(NR) "," sk "," ku
在这个脚本中添加最小值/最大值很简单,但通过管道传递sort
和head
/tail
一样容易:
sort -n myfile | head -n1
sort -n myfile | tail -n1
【讨论】:
【参考方案4】:另一个可用于以 ASCII 模式计算统计数据和视图分布的工具是 ministat。它是来自 FreeBSD 的工具,但它也被打包用于流行的 Linux 发行版,如 Debian/Ubuntu。或者您可以简单地从 sources 下载并构建它 - 它只需要 C 编译器和 C 标准库。
使用示例:
$ cat test.log
Handled 1000000 packets.Time elapsed: 7.575278
Handled 1000000 packets.Time elapsed: 7.569267
Handled 1000000 packets.Time elapsed: 7.540344
Handled 1000000 packets.Time elapsed: 7.547680
Handled 1000000 packets.Time elapsed: 7.692373
Handled 1000000 packets.Time elapsed: 7.390200
Handled 1000000 packets.Time elapsed: 7.391308
Handled 1000000 packets.Time elapsed: 7.388075
$ cat test.log| awk 'print $5' | ministat -w 74
x <stdin>
+--------------------------------------------------------------------------+
| x |
|xx xx x x x|
| |__________________________A_______M_________________| |
+--------------------------------------------------------------------------+
N Min Max Median Avg Stddev
x 8 7.388075 7.692373 7.54768 7.5118156 0.11126122
【讨论】:
【参考方案5】:是的,它叫做 perl 这是简洁的单行:
perl -e 'use List::Util qw(max min sum); @a=();while(<>)$sqsum+=$_*$_; push(@a,$_); $n=@a;$s=sum(@a);$a=$s/@a;$m=max(@a);$mm=min(@a);$std=sqrt($sqsum/$n-($s/$n)*($s/$n));$mid=int @a/2;@srtd=sort @a;if(@a%2)$med=$srtd[$mid];else$med=($srtd[$mid-1]+$srtd[$mid])/2;;print "records:$n\nsum:$s\navg:$a\nstd:$std\nmed:$med\max:$m\min:$mm";'
例子
$ cat tt
1
3
4
5
6.5
7.
2
3
4
还有命令
cat tt | perl -e 'use List::Util qw(max min sum); @a=();while(<>)$sqsum+=$_*$_; push(@a,$_); $n=@a;$s=sum(@a);$a=$s/@a;$m=max(@a);$mm=min(@a);$std=sqrt($sqsum/$n-($s/$n)*($s/$n));$mid=int @a/2;@srtd=sort @a;if(@a%2)$med=$srtd[$mid];else$med=($srtd[$mid-1]+$srtd[$mid])/2;;print "records:$n\nsum:$s\navg:$a\nstd:$std\nmed:$med\max:$m\min:$mm";'
records:9
sum:35.5
avg:3.94444444444444
std:1.86256162380447
med:4
max:7.
min:1
【讨论】:
我确信这行得通,但是只做一行会让我的眼睛流血。为什么不创建一个脚本,而不是那种暴行? 我很确定“函数式语言”!=“尽可能简洁地将所有内容写在一行上”。 仅仅因为你可以做某事一行并不意味着你应该。 Oneliners 绝对不是用来阅读的。但是他们很高兴只是复制粘贴到我的腻子中,并从 apache 日志中获取一些数字的统计信息......所以 bua roxx 命令行(至少是 bash)也支持多行字符串。只需在文字中使用换行符即可。【参考方案6】:另一个工具:https://www.gnu.org/software/datamash/
# Example: calculate the sum and mean of values 1 to 10:
$ seq 10 | datamash sum 1 mean 1
55 5.5
可能被更普遍地打包(至少我发现的第一个为 nix 预打包的工具)
【讨论】:
【参考方案7】:平均值:
awk 'sum += $1 END print "mean = " sum/NR' filename
中位数:
gawk -v max=128 '
function median(c,v, j)
asort(v,j)
if (c % 2) return j[(c+1)/2]
else return (j[c/2+1]+j[c/2])/2.0
count++
values[count]=$1
if (count >= max)
print median(count,values); count=0
END
print "median = " median(count,values)
' filename
模式:
awk 'c[$1]++ END for (i in count) if (c[i]>max) max=i print "mode = " max' filename
这种模式计算需要偶数个样本,但你看看它是如何工作的......
标准偏差:
awk 'sum+=$1; sumsq+=$1*$1 END print "stdev = " sqrt(sumsq/NR - (sum/NR)**2)' filename
【讨论】:
做得很好 - 并且使用了每个 Linux 发行版上的工具。 @rbellamy - 谢谢!不仅仅是 Linux - 我管理着 FreeBSD 系统,awk
和 gawk
之间的区别很重要(因为 BSD 上的 Plain Old Awk 不包括 asort()
)。【参考方案8】:
以防万一,有datastat
,这是一个简单的程序,用于从命令行计算简单统计信息的 Linux。例如,
cat file.dat | datastat
将为file.dat 的每一列输出所有行的平均值。如果您需要知道标准差,最小值,最大值,可以分别添加--dev
、--min
和--max
选项。
datastat
可以根据一个或多个“键”列的值聚合行。例如,
cat file.dat | datastat -k 1
对于在第一列(“键”)上找到的每个不同值,将生成所有其他列值的平均值,这些值在键上具有相同值的所有行中聚合。您可以使用更多列作为关键字段(例如,-k 1-3、-k 2,4 等...)。
它是用 C++ 编写的,运行速度快,内存占用少,并且可以很好地与 cut
、grep
、sed
、sort
、awk
等其他工具进行管道传输。
【讨论】:
useless use ofcat
的文体轻微畏缩
我认为缺少作者身份免责声明。【参考方案9】:
data_hacks
is a Python command-line utility for basic statistics.
该页面的第一个示例产生了预期的结果:
$ cat /tmp/data | histogram.py
# NumSamples = 29; Max = 10.00; Min = 1.00
# Mean = 4.379310; Variance = 5.131986; SD = 2.265389
# each * represents a count of 1
1.0000 - 1.9000 [ 1]: *
1.9000 - 2.8000 [ 5]: *****
2.8000 - 3.7000 [ 8]: ********
3.7000 - 4.6000 [ 3]: ***
4.6000 - 5.5000 [ 4]: ****
5.5000 - 6.4000 [ 2]: **
6.4000 - 7.3000 [ 3]: ***
7.3000 - 8.2000 [ 1]: *
8.2000 - 9.1000 [ 1]: *
9.1000 - 10.0000 [ 1]: *
【讨论】:
【参考方案10】:您也可以考虑使用clistats。它是一个高度可配置的命令行界面工具,用于计算分隔输入数字流的统计信息。
I/O 选项
输入数据可以来自文件、标准输入或管道 可以将输出写入文件、标准输出或管道 输出使用以“#”开头的标头来启用到 gnuplot 的管道解析选项
基于信号、文件结尾或空行的检测以停止处理 可以设置注释和分隔符 可以从处理中过滤掉列 可以根据数值约束从处理中过滤掉行 可以根据字符串约束从处理中过滤掉行 可以跳过初始标题行 可以处理固定的行数 可以忽略重复的分隔符 行可以重新整形为列 严格强制只处理相同大小的行 包含列标题的行可用于标题输出统计信息统计选项
汇总统计信息(计数、最小值、平均值、最大值、标准差) 协方差 相关性 最小二乘偏移 最小二乘斜率 直方图 过滤后的原始数据注意:我是作者。
【讨论】:
【参考方案11】:我发现自己想在 shell 管道中执行此操作,并且为 R 获取所有正确的参数需要一段时间。这是我想出的:
seq 10 | R --slave -e 'x <- scan(file="stdin",quiet=TRUE); summary(x)'
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.00 3.25 5.50 5.50 7.75 10.00
--slave
选项 "Make(s) R run as quietly as possible...It implies --quiet and --no-save." -e
选项告诉 R 将以下字符串视为 R 代码。第一条语句从标准输入中读取,并将读取的内容存储在名为“x”的变量中。 scan
函数的 quiet=TRUE
选项禁止写入一行,说明读取了多少项目。第二条语句将summary
函数应用于x
,从而产生输出。
【讨论】:
【参考方案12】:还有 simple-r,它几乎可以做 R 可以做的所有事情,但按键次数更少:
https://code.google.com/p/simple-r/
要计算基本的描述性统计数据,必须键入以下之一:
r summary file.txt
r summary - < file.txt
cat file.txt | r summary -
对于平均值、中位数、最小值、最大值和标准偏差中的每一个,代码将是:
seq 1 100 | r mean -
seq 1 100 | r median -
seq 1 100 | r min -
seq 1 100 | r max -
seq 1 100 | r sd -
没有得到任何简单的-R!
【讨论】:
有趣的是,它是 R 的 Perl 包装器。R 不是编程语言! >:-)【参考方案13】:#!/usr/bin/perl
#
# stdev - figure N, min, max, median, mode, mean, & std deviation
#
# pull out all the real numbers in the input
# stream and run standard calculations on them.
# they may be intermixed with other test, need
# not be on the same or different lines, and
# can be in scientific notion (avagadro=6.02e23).
# they also admit a leading + or -.
#
# Tom Christiansen
# tchrist@perl.com
use strict;
use warnings;
use List::Util qw< min max >;
#
my $number_rx = qr
# leading sign, positive or negative
(?: [+-] ? )
# mantissa
(?= [0123456789.] )
(?:
# "N" or "N." or "N.N"
(?:
(?: [0123456789] + )
(?:
(?: [.] )
(?: [0123456789] * )
) ?
|
# ".N", no leading digits
(?:
(?: [.] )
(?: [0123456789] + )
)
)
)
# abscissa
(?:
(?: [Ee] )
(?:
(?: [+-] ? )
(?: [0123456789] + )
)
|
)
x;
my $n = 0;
my $sum = 0;
my @values = ();
my %seen = ();
while (<>)
while (/($number_rx)/g)
$n++;
my $num = 0 + $1; # 0+ is so numbers in alternate form count as same
$sum += $num;
push @values, $num;
$seen$num++;
die "no values" if $n == 0;
my $mean = $sum / $n;
my $sqsum = 0;
for (@values)
$sqsum += ( $_ ** 2 );
$sqsum /= $n;
$sqsum -= ( $mean ** 2 );
my $stdev = sqrt($sqsum);
my $max_seen_count = max values %seen;
my @modes = grep $seen$_ == $max_seen_count keys %seen;
my $mode = @modes == 1
? $modes[0]
: "(" . join(", ", @modes) . ")";
$mode .= ' @ ' . $max_seen_count;
my $median;
my $mid = int @values/2;
if (@values % 2)
$median = $values[ $mid ];
else
$median = ($values[$mid-1] + $values[$mid])/2;
my $min = min @values;
my $max = max @values;
printf "n is %d, min is %g, max is %d\n", $n, $min, $max;
printf "mode is %s, median is %g, mean is %g, stdev is %g\n",
$mode, $median, $mean, $stdev;
【讨论】:
【参考方案14】:使用xsv:
$ echo '3 1 4 1 5 9 2 6 5 3 5 9' |tr ' ' '\n' > numbers-one-per-line.csv
$ xsv stats -n < numbers-one-per-line.csv
field,type,sum,min,max,min_length,max_length,mean,stddev
0,Integer,53,1,9,1,1,4.416666666666667,2.5644470922381863
# mode/median/cardinality not shown by default since it requires storing full file in memory:
$ xsv stats -n --everything < numbers-one-per-line.csv | xsv table
field type sum min max min_length max_length mean stddev median mode cardinality
0 Integer 53 1 9 1 1 4.416666666666667 2.5644470922381863 4.5 5 7
【讨论】:
使用brew
安装它揭示了很多依赖关系。这个功能相当“重”。
所以不要使用brew? github.com/BurntSushi/xsv/releases 已经为 macos 预编译了二进制文件,因此没有理由安装完整的 rust 工具链或 brew 所做的任何事情。【参考方案15】:
另一个工具:tsv-summarize,来自eBay's tsv utilities。最小值、最大值、平均值、中值、标准差都支持。适用于大型数据集。示例:
$ seq 10 | tsv-summarize --min 1 --max 1 --median 1 --stdev 1
1 10 5.5 3.0276503541
免责声明:我是作者。
【讨论】:
【参考方案16】:另外,自写stats,(与'scut'捆绑在一起)一个perl util来做到这一点。在 STDIN 上输入数字流,它尝试拒绝非数字并发出以下内容:
$ ls -lR | scut -f=4 | stats
Sum 3.10271e+07
Number 452
Mean 68643.9
Median 4469.5
Mode 4096
NModes 6
Min 2
Max 1.01171e+07
Range 1.01171e+07
Variance 3.03828e+11
Std_Dev 551206
SEM 25926.6
95% Conf 17827.9 to 119460
(for a normal distribution - see skew)
Skew 15.4631
(skew = 0 for a symmetric dist)
Std_Skew 134.212
Kurtosis 258.477
(K=3 for a normal dist)
它还可以对输入流进行许多转换,如果你要求它,它只会发出未修饰的值; ie 'stats --mean' 会将平均值作为未标记的浮点数返回。
【讨论】:
以上是关于命令行实用程序,用于打印 linux 中的数字统计信息的主要内容,如果未能解决你的问题,请参考以下文章