RubyでSpearman's R (順位相関係数)を計算しよう
Rubyの配列(Arrayクラス)を拡張して和,分散,標準偏差,相関係数を計算する - Loud Minority や Ruby で Mann-Whitney U test をする - Loud Minority の続き.
Spearman(スピアマン)の順位相関係数を計算しよう.
http://d.hatena.ne.jp/sesejun/20070502/p1 を改良して,順位相関係数を計算できるようにしてみました.
使い方
x = [2.8,3.4,3.6,5.8,7.0,9.5,10.2,12.3,13.2,13.4]
y = [0.6,3.0,0.4,1.5,15.0,13.4,7.6,19.8,18.3,18.9]
puts x.corrcoef(y, :spearman)
#=> 0.854545454545454
ソース
class Array def sum_with_number s = 0.0 n = 0 self.each do |v| next if v.nil? s += v.to_f n += 1 end [s, n] end def sum s, n = self.sum_with_number s end def avg s, n = self.sum_with_number s / n end alias mean avg def var c = 0 while self[c].nil? c += 1 end mean = self[c].to_f sum = 0.0 n = 1 (c+1).upto(self.size-1) do |i| next if self[i].nil? sweep = n.to_f / (n + 1.0) delta = self[i].to_f - mean sum += delta * delta * sweep mean += delta / (n + 1.0) n += 1 end sum / n.to_f end def stddev Math.sqrt(self.var) end def corrcoef(y, method = :pearson) if method == :pearson corrcoef_pearson(y) elsif method == :spearman corrcoef_spearman(y) end end def corrcoef_pearson(y) raise "Invalid Argument Array Size" unless self.size == y.size sum_sq_x = 0.0 sum_sq_y = 0.0 sum_coproduct = 0.0 c = 0 while self[c].nil? || y[c].nil? c += 1 end mean_x = self[c].to_f mean_y = y[c].to_f n = 1 (c+1).upto(self.size-1) do |i| next if self[i].nil? || y[i].nil? sweep = n.to_f / (n + 1.0) delta_x = self[i].to_f - mean_x delta_y = y[i].to_f - mean_y sum_sq_x += delta_x * delta_x * sweep sum_sq_y += delta_y * delta_y * sweep mean_x += delta_x / (n + 1.0) mean_y += delta_y / (n + 1.0) n += 1 end pop_sd_x = Math.sqrt(sum_sq_x / n.to_f) pop_sd_y = Math.sqrt(sum_sq_y / n.to_f) cov_x_y = sum_coproduct / n.to_f cov_x_y / (pop_sd_x * pop_sd_y) end def corrcoef_spearman(y) xo = Array.new yo = Array.new self.size.times do |n| xo << [n, self[n]] yo << [n, y[n]] end xo = xo.sort{|a, b| a[1]<=>b[1]} yo = yo.sort{|a, b| a[1]<=>b[1]} self.size.times do |n| xo[n][1] = n yo[n][1] = n end xo = xo.sort{|a, b| a[0]<=>b[0]} yo = yo.sort{|a, b| a[0]<=>b[0]} xary = xo.map{|v| v[1]} yary = yo.map{|v| v[1]} xary.corrcoef_pearson(yary) end end