Class: Statistics::StatisticalTest::TTest

Inherits:
Object
  • Object
show all
Defined in:
lib/statistics/statistical_test/t_test.rb

Defined Under Namespace

Classes: ZeroStdError

Class Method Summary collapse

Class Method Details

.paired_test(alpha, tails, left_group, right_group) ⇒ Object

Raises:

  • (StandardError)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/statistics/statistical_test/t_test.rb', line 62

def self.paired_test(alpha, tails, left_group, right_group)
  raise StandardError, 'both samples are the same' if left_group == right_group

  # Handy snippet grabbed from https://stackoverflow.com/questions/2682411/ruby-sum-corresponding-members-of-two-or-more-arrays
  differences = [left_group, right_group].transpose.map { |value| value.reduce(:-) }

  degrees_of_freedom = differences.size - 1
  difference_std = differences.standard_deviation

  raise ZeroStdError, ZeroStdError::STD_ERROR_MSG if difference_std == 0

  down = difference_std/Math.sqrt(differences.size)

  t_score = (differences.mean - 0)/down.to_r

  t_distribution = Distribution::TStudent.new(degrees_of_freedom)
  probability = t_distribution.cumulative_function(t_score)

  p_value = if tails == :two_tail
            2 * (1 - t_distribution.cumulative_function(t_score.abs))
            else
              1 - probability
            end

  { t_score: t_score,
    probability: probability,
    p_value: p_value,
    alpha: alpha,
    null: alpha < p_value,
    alternative: p_value <= alpha,
    confidence_level: 1 - alpha }
end

.perform(alpha, tails, *args) ⇒ Object

Perform a T-Test for one or two samples. For the tails param, we need a symbol: :one_tail or :two_tail



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/statistics/statistical_test/t_test.rb', line 11

def self.perform(alpha, tails, *args)
  return if args.size < 2

  degrees_of_freedom = 0

  # If the comparison mean has been specified
  t_score = if args[0].is_a? Numeric
              data_mean = args[1].mean
              data_std = args[1].standard_deviation

              raise ZeroStdError, ZeroStdError::STD_ERROR_MSG if data_std == 0

              comparison_mean = args[0]
              degrees_of_freedom = args[1].size - 1

              (data_mean - comparison_mean)/(data_std / Math.sqrt(args[1].size).to_r).to_r
            else
              sample_left_mean = args[0].mean
              sample_left_variance = args[0].variance
              sample_right_variance = args[1].variance
              sample_right_mean = args[1].mean
              degrees_of_freedom = args.flatten.size - 2

              left_root = sample_left_variance/args[0].size.to_r
              right_root = sample_right_variance/args[1].size.to_r

              standard_error = Math.sqrt(left_root + right_root)

              (sample_left_mean - sample_right_mean).abs/standard_error.to_r
            end

  t_distribution = Distribution::TStudent.new(degrees_of_freedom)
  probability = t_distribution.cumulative_function(t_score)

  # Steps grabbed from https://support.minitab.com/en-us/minitab/18/help-and-how-to/statistics/basic-statistics/supporting-topics/basics/manually-calculate-a-p-value/
  # See https://github.com/estebanz01/ruby-statistics/issues/23
  p_value = if tails == :two_tail
            2 * (1 - t_distribution.cumulative_function(t_score.abs))
            else
              1 - probability
            end

  { t_score: t_score,
    probability: probability,
    p_value: p_value,
    alpha: alpha,
    null: alpha < p_value,
    alternative: p_value <= alpha,
    confidence_level: 1 - alpha }
end