bash 使用 bc 或其他标准实用程序的任意数量数字的标准偏差

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15101343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 04:41:06  来源:igfitidea点击:

standard deviation of an arbitrary number of numbers using bc or other standard utilities

bashvariablesstandard-deviation

提问by d3pd

Is there some trick that would allow one to use bc (or some other standard utility) to return the standard deviation of an arbitrary number of numbers? For convenience, let's say that the numbers are stored in a Bash variable in the following way:

是否有一些技巧可以让人们使用 bc (或其他一些标准实用程序)来返回任意数量数字的标准偏差?为方便起见,假设数字按以下方式存储在 Bash 变量中:

myNumbers="0.556
1.456
45.111
7.812
5.001"

So, the answer I'm looking for would be in a form such as the following:

因此,我正在寻找的答案将采用如下形式:

standardDeviation="$(echo "${myNumbers}" | <insert magic here>)"

回答by Gilles Quenot

Using awk:

使用awk

standardDeviation=$(
    echo "$myNumbers" |
        awk '{sum+=; sumsq+=*}END{print sqrt(sumsq/NR - (sum/NR)**2)}'
)
echo $standardDeviation

Using perl:

使用perl

#!/usr/bin/env perl

use strict; use warnings;
use Math::NumberCruncher;

my @data = qw/
    0.556
    1.456
    45.111
    7.812
    5.001
/;

print Math::NumberCruncher::StandardDeviation(\@data);

Output

输出

16.7631

回答by nisetama

Population standard deviation:

人口标准差:

jq -s '(add/length)as$a|map(pow(.-$a;2))|add/length|sqrt'
ruby -e'a=readlines.map(&:to_f);puts (a.map{|x|(x-a.reduce(:+)/a.length)**2}.reduce(:+)/a.length)**0.5'
jq -s '(map(.*.)|add/length)-pow(add/length;2)|sqrt'
awk '{x+=
jq -s '(add/length)as$a|map(pow(.-$a;2))|add/(length-1)|sqrt'
ruby -e'a=readlines.map(&:to_f);puts (a.map{|x|(x-a.reduce(:+)/a.length)**2}.reduce(:+)/(a.length-1))**0.5'
R -q -e 'sd(scan("stdin"))'
;y+=
standardDeviation="$(echo "${myNumbers}" | octave --eval 'disp(std(scanf("%f")))')"
echo $standardDeviation
^2}END{print sqrt(y/NR-(x/NR)^2)}'

In awk, ^is in POSIX but **is not. **is supported by gawkand nawkbut not by mawk.

awk,^在 POSIX 中但**不是。**gawknawk但不由支持mawk

Sample standard deviation (the first two commands are the same as the first two commands above, but lengthwas replaced with length-1):

样本标准偏差(前两个命令与上面的前两个命令相同,但length被替换为length-1):

18.742

回答by Andy

Or use GNU Octave (which can much more than simple std):

或者使用 GNU Octave(它不仅仅是简单的 std):

$ myNumbers=$(echo "0.556 1.456 45.111 7.812 5.001" | tr " " "\n")

Outputs

输出

$ echo "$myNumbers" | awk '+0== {sum+=; sumsq+=*; cnt++}
                           END{print sumsq/cnt; print sqrt(sumsq/cnt - (sum/cnt)**2)}'
16.7631

回答by dawg

Given:

鉴于:

$ echo "$myNumbers" | ruby -e 'arr=$<.read.split(/\s/).map { |e| Float(e) rescue nil }.compact
                             sumsq=arr.inject(0) { |acc, e| acc+=e*e }
                             p (sumsq/arr.length - (arr.sum/arr.length)**2)**0.5'
16.76307799182477

First decide if you need sample standard deviationvs population standard deviationof those numbers.

首先确定您是否需要这些数字的样本标准差总体标准差

Population standard deviation (the function STDEV.Pin Excel) requires the entire population of datum. In Excel, text or blanks are skipped.

总体标准偏差(Excel 中的函数STDEV.P)需要整个数据总体。在 Excel 中,将跳过文本或空格。

It is easily calculated on a rolling basis in awk:

它很容易在滚动基础上计算awk

$ echo "$myNumbers" | 
     awk 'function sdev(array) {
     for (i=1; i in array; i++)
        sum+=array[i]
     cnt=i-1
     mean=sum/cnt
     for (i=1; i in array; i++)  
        sqdif+=(array[i]-mean)**2
     return (sqdif/(cnt-1))**0.5
     }
     +0== {sum1[++cnt]=} 
     END {print sdev(sum1)}' 
18.7417

Or in Ruby:

或在Ruby

$ ruby -lane 'BEGIN{col1=[]}
            col1 << Float($F[0]) rescue nil
            END {col1.compact
                 mean=col1.sum / col1.length
                 p (col1.inject(0){ |acc, e| acc+(e-mean)**2 } / 
                        (col1.length-1))**0.5
              }' <(echo "$myNumbers")
18.741690950925424

For a sample standard deviation (the function STDEV.Sin Excel and ignoring text or blanks) You need to have the entire sample collected first since the mean is used against each value in the sample.

对于样本标准偏差(Excel 中的函数STDEV.S并忽略文本或空白),您需要先收集整个样本,因为针对样本中的每个值使用平均值。

In awk:

awk

##代码##

Or in Ruby:

或者在 Ruby 中:

##代码##