在Linux中是否有命令行实用程序可以做同样的事情?我通常需要找到平均值、中位数、最小值、最大值和标准差。
在Linux中是否有命令行实用程序可以做同样的事情?我通常需要找到平均值、中位数、最小值、最大值和标准差。
使用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。sudo apt-get install r-base
。 - E-richst
表格。这与评论无关,但我的 brew install R
在 MacBook Pro Mid 2015 10.12.5 2.5GHz i7 16GB 上花了近一个小时,同时打开了 Chrome、Atom 和其他应用程序。大部分时间都用于使用 Xcode CLT 构建一些 gcc jit patch,但现在我很高兴地使用了这个答案的部分 :) - Pysis$ 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
(免责声明:我是这个工具的作者 :))
计算平均值、中位数和标准差,您可以使用awk
。这通常比R
的解决方案更快。例如,以下代码将打印出平均值:
awk '{a+=$1} END{print a/NR}' myfile
(NR
是 awk
变量,表示记录数,$1
表示行的第一个(以空格分隔的)参数($0
表示整行,虽然在这里也可以使用,但原则上不太安全,尽管对于计算来说,它可能只需要第一个参数),END
表示在处理整个文件后执行以下命令(也可以在 BEGIN{a=0}
语句中初始化 a
为 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
}
将min/max添加到此脚本非常简单,但使用管道sort
和head
/tail
同样容易:
sort -n myfile | head -n1
sort -n myfile | tail -n1
另一个可以用来计算统计数据和在ASCII模式下查看分布的工具是ministat。它是来自FreeBSD的一个工具,但也被打包到像Debian/Ubuntu这样的流行Linux发行版中。或者您可以从源代码中简单地下载并构建它 - 它只需要一个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
是的,它叫做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
均值:
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
awk
和gawk
之间的区别很重要(因为在BSD上的Plain Old Awk不包括asort()
)。 - ghoti又一个工具: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 中找到的第一个预打包的工具)
如果需要的话,可以使用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
等)很好地配合使用。
cat
使用”而言,这只是一种风格上的小问题。 - tripleee我发现自己想在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
选项"使R尽可能地安静运行...它隐含了--quiet和--no-save。"-e
选项告诉R将以下字符串视为R代码。第一个语句从标准输入读取,并将读取的内容存储在名为"x"的变量中。scan
函数的quiet=TRUE
选项抑制了一行显示读取了多少个项目的输出。第二个语句将summary
函数应用于x
,产生输出。
注意:我是作者。
jp
,一个用于绘制图表的 CLI 工具 感兴趣。 - Matt Parker