Ruby

ruby 度数分布表

度数分布表

rubyの勉強のために度数分布表を作ってみた。もっと短く賢く書きたい。。泣
誰かよりよい書き方、きれいな書き方などがあれば教えてくださいませ。

freq_dist.rb
  1 init_seed = 12345
  2 max_value = 16.00
  3 init_value = 10.0
  4 class_interval_width=0.9
  5 
  6 total = 50000.0
  7 
  8 # sample
  9 prng1 = Random.new(init_seed)
 10 sample = Array.new(total){(prng1.rand(9.4...20.1))}
 11 
 12 class_interval = init_value.step(max_value, class_interval_width).map{|i| i}
 13 
 14 frequency = Array.new(class_interval.size, 0)
 15 for num in sample do
 16   if class_interval[0] <= num && num < class_interval[-1]+class_interval_width
 17     b = class_interval.map{|i| i <= num ? num-i : max_value }
 18     class_num = b.each_with_index.map{|v, i| v == b.min ? i : nil}.compact.min
 19     frequency[class_num] += 1
 20   end
 21 end
 22 relative_frequency = frequency.map{|i| (i / sample.size.to_f) }
 23 
 24 cumulative_distribution_function = Array.new(class_interval.size, 0)
 25 cumulative_distribution_frequency = Array.new(class_interval.size, 0)
 26 for num in 0...class_interval.size do
 27   if num == 0
 28     cumulative_distribution_function[num] = frequency[num]
 29     cumulative_distribution_frequency[num] = relative_frequency[num]
 30   else
 31     cumulative_distribution_function[num] += cumulative_distribution_function[num-1]+frequency[num]
 32     cumulative_distribution_frequency[num] += cumulative_distribution_frequency[num-1]+relative_frequency    [num]
 33   end
 34 end
 35 
 36 printf("%s\t%s\t%s\t%s\t%s\n","階級","度数","相対度数","累積度数","累積相対度数")
 37 for num in 0...class_interval.size
 38   printf("%05.02f~%05.02f\t%02d\t%.02f\t%05d\t%.02f\n",class_interval[num],class_interval[num]+class_inte    rval_width,frequency[num],relative_frequency[num],cumulative_distribution_function[num],cumulative_distri    bution_frequency[num])
 39 end
$ ruby freq_dist.rb 
階級  度数  相対度数    累積度数    累積相対度数
10.00~10.90 4229    0.08    04229   0.08
10.90~11.80 4256    0.09    08485   0.17
11.80~12.70 4108    0.08    12593   0.25
12.70~13.60 4244    0.08    16837   0.34
13.60~14.50 4235    0.08    21072   0.42
14.50~15.40 4141    0.08    25213   0.50
15.40~16.30 4172    0.08    29385   0.59

スタージスの式を追加

freq_dist2.rb
  1 include Math
  2 
  3 init_seed = 12345
  4 
  5 # sample
  6 n = 100.0
  7 prng1 = Random.new(init_seed)
  8 sample = Array.new(n){(prng1.rand(300...400).round(2))}
  9 total = sample.size
 10 
 11 init_value = sample.min.to_f
 12 max_value = sample.max.to_f
 13 
 14 sturges = 1 + (log10(total.to_f) / log10(2)).round
 15 class_interval_width = ((max_value - init_value)/sturges).ceil(2)
 16 class_interval = init_value.step(max_value, class_interval_width).map{|i| i}
 17 
 18 frequency = Array.new(class_interval.size, 0)
 19 for num in sample do
 20   if class_interval[0] <= num && num < class_interval[-1]+class_interval_width
 21     b = class_interval.map{|i| i <= num ? num-i : max_value }
 22     class_num = b.each_with_index.map{|v, i| v == b.min ? i : nil}.compact.min
 23     frequency[class_num] += 1
 24   end
 25 end
 26 relative_frequency = frequency.map{|i| (i / total.to_f) }
 27 
 28 cumulative_distribution_function = Array.new(class_interval.size, 0)
 29 cumulative_distribution_frequency = Array.new(class_interval.size, 0)
 30 for num in 0...class_interval.size do
 31   if num == 0
 32     cumulative_distribution_function[num] = frequency[num]
 33     cumulative_distribution_frequency[num] = relative_frequency[num]
 34   else
 35     cumulative_distribution_function[num] += cumulative_distribution_function[num-1]+frequency[num]
 36     cumulative_distribution_frequency[num] += cumulative_distribution_frequency[num-1]+relative_frequency[num    ]
 37   end
 38 end
 39 
 40 p "-----"*10
 41 printf("%s\t%s\t%s\t%s\t%s\n","階級","度数","相対度数","累積度数","累積相対度数")
 42 p "-----"*10
 43 for num in 0...class_interval.size
 44   printf("%05.02f~%05.02f\t%02d\t%.02f\t%05d\t%.02f\n",class_interval[num],class_interval[num]+class_interval    _width,frequency[num],relative_frequency[num],cumulative_distribution_function[num],cumulative_distribution_f    requency[num])
 45 end
 46 p "-----"*10
 47 
 48 total = sample.inject{|result, i| result + i}
 49 ave = total/n
 50 median = sample.size % 2 == 0 ? sample[sample.size/2 - 1, 2].inject(:+) / 2.0 : sample[sample.size/2]
 51 mode = sample.uniq.sort_by{|x| sample.count x }.reverse[0]
 52 
 53 printf("最小値:\t\t%f\n",init_value)
 54 printf("最大値:\t\t%f\n",max_value)
 55 printf("総計値:\t\t%f\n",total)
 56 printf("平均値:\t\t%f\n",ave)
 57 printf("中央値:\t\t%f\n",median)
 58 printf("最頻値:\t\t%f\n",mode)
$ ruby freq_dist2.rb 
"--------------------------------------------------"
階級  度数  相対度数    累積度数    累積相対度数
"--------------------------------------------------"
300.00~312.38   18  0.18    00018   0.18
312.38~324.76   11  0.11    00029   0.29
324.76~337.14   13  0.13    00042   0.42
337.14~349.52   10  0.10    00052   0.52
349.52~361.90   10  0.10    00062   0.62
361.90~374.28   14  0.14    00076   0.76
374.28~386.66   13  0.13    00089   0.89
386.66~399.04   11  0.11    00100   1.00
"--------------------------------------------------"
最小値:      300.000000
最大値:      399.000000
総計値:      34721.000000
平均値:      347.210000
中央値:      353.500000
最頻値:      305.000000