Ruby에서 표준 편차를 어떻게 할 수 있습니까?
주어진 속성을 가진 여러 레코드가 있고 표준 편차를 찾고 싶습니다.
어떻게하나요?
module Enumerable
def sum
self.inject(0){|accum, i| accum + i }
end
def mean
self.sum/self.length.to_f
end
def sample_variance
m = self.mean
sum = self.inject(0){|accum, i| accum +(i-m)**2 }
sum/(self.length - 1).to_f
end
def standard_deviation
Math.sqrt(self.sample_variance)
end
end
테스트 :
a = [ 20, 23, 23, 24, 25, 22, 12, 21, 29 ]
a.standard_deviation
# => 4.594682917363407
2012 년 1 월 17 일 :
Dave Sag 덕분에 "sample_variance"수정
Angela는 기존 도서관을 원했던 것 같습니다. statsample, array-statisics 및 기타 몇 가지 작업을 마친 후 휠을 재발 명하지 않으 려면 descriptive_statistics gem을 추천합니다 .
gem install descriptive_statistics
$ irb
1.9.2 :001 > require 'descriptive_statistics'
=> true
1.9.2 :002 > samples = [1, 2, 2.2, 2.3, 4, 5]
=> [1, 2, 2.2, 2.3, 4, 5]
1.9.2p290 :003 > samples.sum
=> 16.5
1.9.2 :004 > samples.mean
=> 2.75
1.9.2 :005 > samples.variance
=> 1.7924999999999998
1.9.2 :006 > samples.standard_deviation
=> 1.3388427838995882
나는 그것의 통계적 정확성이나 원숭이 패치 Enumerable에 대한 당신의 편안함에 대해 말할 수 없습니다. 하지만 사용하기 쉽고 기여하기 쉽습니다.
위에 주어진 대답은 우아하지만 약간의 오류가 있습니다. 나는 통계가 아닌 내가 앉아서 여러 웹 사이트를 자세히 읽었고 이것이 표준 편차를 도출하는 방법에 대한 가장 이해하기 쉬운 설명을 제공한다는 것을 알았습니다. http://sonia.hubpages.com/hub/stddev
위 답변의 오류는 sample_variance방법에 있습니다.
이것이 작동하는 것을 보여주는 간단한 단위 테스트와 함께 수정 된 버전입니다.
에 ./lib/enumerable/standard_deviation.rb
#!usr/bin/ruby
module Enumerable
def sum
return self.inject(0){|accum, i| accum + i }
end
def mean
return self.sum / self.length.to_f
end
def sample_variance
m = self.mean
sum = self.inject(0){|accum, i| accum + (i - m) ** 2 }
return sum / (self.length - 1).to_f
end
def standard_deviation
return Math.sqrt(self.sample_variance)
end
end
./test간단한 스프레드 시트에서 파생 된 숫자 를 사용합니다.

#!usr/bin/ruby
require 'enumerable/standard_deviation'
class StandardDeviationTest < Test::Unit::TestCase
THE_NUMBERS = [1, 2, 2.2, 2.3, 4, 5]
def test_sum
expected = 16.5
result = THE_NUMBERS.sum
assert result == expected, "expected #{expected} but got #{result}"
end
def test_mean
expected = 2.75
result = THE_NUMBERS.mean
assert result == expected, "expected #{expected} but got #{result}"
end
def test_sample_variance
expected = 2.151
result = THE_NUMBERS.sample_variance
assert result == expected, "expected #{expected} but got #{result}"
end
def test_standard_deviation
expected = 1.4666287874
result = THE_NUMBERS.standard_deviation
assert result.round(10) == expected, "expected #{expected} but got #{result}"
end
end
나는 Enumerable원치 않는 부작용이있을 수 있기 때문에 방법을 추가하는 것을 좋아하지 않습니다 . 또한에서 상속하는 모든 클래스에 숫자 배열에 특정한 메서드를 제공합니다 Enumerable. 이는 대부분의 경우 의미가 없습니다.
While this is fine for tests, scripts or small apps, it's risky for larger applications, so here's an alternative based on @tolitius' answer which was already perfect. This is more for reference than anything else:
module MyApp::Maths
def self.sum(a)
a.inject(0){ |accum, i| accum + i }
end
def self.mean(a)
sum(a) / a.length.to_f
end
def self.sample_variance(a)
m = mean(a)
sum = a.inject(0){ |accum, i| accum + (i - m) ** 2 }
sum / (a.length - 1).to_f
end
def self.standard_deviation(a)
Math.sqrt(sample_variance(a))
end
end
And then you use it as such:
2.0.0p353 > MyApp::Maths.standard_deviation([1,2,3,4,5])
=> 1.5811388300841898
2.0.0p353 :007 > a = [ 20, 23, 23, 24, 25, 22, 12, 21, 29 ]
=> [20, 23, 23, 24, 25, 22, 12, 21, 29]
2.0.0p353 :008 > MyApp::Maths.standard_deviation(a)
=> 4.594682917363407
2.0.0p353 :043 > MyApp::Maths.standard_deviation([1,2,2.2,2.3,4,5])
=> 1.466628787389638
The behavior is the same, but it avoids the overheads and risks of adding methods to Enumerable.
The presented computation are not very efficient because they require several (at least two, but often three because you usually want to present average in addition to std-dev) passes through the array.
I know Ruby is not the place to look for efficiency, but here is my implementation that computes average and standard deviation with a single pass over the list values:
module Enumerable
def avg_stddev
return nil unless count > 0
return [ first, 0 ] if count == 1
sx = sx2 = 0
each do |x|
sx2 += x**2
sx += x
end
[
sx.to_f / count,
Math.sqrt( # http://wijmo.com/docs/spreadjs/STDEV.html
(sx2 - sx**2.0/count)
/
(count - 1)
)
]
end
end
As a simple function, given a list of numbers:
def standard_deviation(list)
mean = list.inject(:+) / list.length.to_f
var_sum = list.map{|n| (n-mean)**2}.inject(:+).to_f
sample_variance = var_sum / (list.length - 1)
Math.sqrt(sample_variance)
end
현재 레코드가 Integer또는 유형 인 경우 반올림으로 인한 오류를 방지하기 위해 대신을 Rational사용하여 분산을 계산할 수 있습니다 .RationalFloat
예를 들면 :
def variance(list)
mean = list.reduce(:+)/list.length.to_r
sum_of_squared_differences = list.map { |i| (i - mean)**2 }.reduce(:+)
sum_of_squared_differences/list.length
end
(빈 목록 및 기타 엣지 케이스에 대한 특수 케이스 처리를 추가하는 것이 현명합니다.)
그런 다음 제곱근을 다음과 같이 정의 할 수 있습니다.
def std_dev(list)
Math.sqrt(variance(list))
end
사람들이 postgres를 사용하는 경우 ... stddev_pop 및 stddev_samp에 대한 집계 함수를 제공합니다-postgresql 집계 함수
stddev (stddev_samp와 동일)는 samp와 pop이 모두 제공되는 8.2 이후 최소한 postgres 7.1부터 사용 가능합니다.
또는 어떻습니까?
class Stats
def initialize( a )
@avg = a.count > 0 ? a.sum / a.count.to_f : 0.0
@stdev = a.count > 0 ? ( a.reduce(0){ |sum, v| sum + (@avg - v) ** 2 } / a.count ) ** 0.5 : 0.0
end
end
참조 URL : https://stackoverflow.com/questions/7749568/how-can-i-do-standard-deviation-in-ruby
'Development Tip' 카테고리의 다른 글
| MySQL : 10 분 이상 지난 모든 행 삭제 (0) | 2021.01.09 |
|---|---|
| Hibernate에서 load () 대 get ()의 장점은 무엇입니까? (0) | 2021.01.09 |
| jQuery를 사용하여 프로그래밍 방식으로 (0) | 2021.01.09 |
| VIM에 대한 GoLang 구문 강조 표시 추가 (0) | 2021.01.09 |
| Autoconf 및 Autotools의 대안? (0) | 2021.01.09 |