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
사용하여 분산을 계산할 수 있습니다 .Rational
Float
예를 들면 :
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 |