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
```

スタージスの式を追加

```ruby: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
```