summaryrefslogtreecommitdiff
path: root/lib/array.rb
blob: 32a8e5d3de5bed86b0aa506bdfd8d17196434336 (plain)
1
2
3
4
5
6
7
8
9
10
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
61
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
94
95
96
97
98
99
100
101
102
103
# TODO increase speed with vectors, matrices?
class Array

  # Sum the size of single arrays in an array of arrays
  # @param [Array] Array of arrays
  # @return [Integer] Sum of size of array elements
  def sum_size
    self.inject(0) { |s,a|
      if a.respond_to?('size')
        s+=a.size
      else
        internal_server_error "No size available: #{a.inspect}"
      end
    }
  end

  # Check if the array has just one unique value.
  # @param [Array] Array to test.
  # @return [TrueClass,FalseClass] 
  def zero_variance?
    return self.uniq.size == 1
  end

  # Get the median of an array
  # @return [Numeric]
  def median
    sorted = self.sort
    len = sorted.length
    (sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
  end

  # Get the mean of an array
  # @return [Numeric]
  def mean
    self.compact.inject{ |sum, el| sum + el }.to_f / self.compact.size
  end

  # Get the variance of an array
  # @return [Numeric]
  def sample_variance
    m = self.mean
    sum = self.compact.inject(0){|accum, i| accum +(i-m)**2 }
    sum/(self.compact.length - 1).to_f
  end

  # Get the standard deviation of an array
  # @return [Numeric]
  def standard_deviation
    Math.sqrt(self.sample_variance)
  end
  
  # Calculate dot product 
  # @param [Array]
  # @return [Numeric]
  def dot_product(a)
    products = self.zip(a).map{|a, b| a * b}
    products.inject(0) {|s,p| s + p}
  end

  # Calculate magnitude
  # @return [Numeric]
  def magnitude
    squares = self.map{|x| x ** 2}
    Math.sqrt(squares.inject(0) {|s, c| s + c})
  end

  # Convert array values for R
  # @return [Array]
  def for_R
    if self.first.is_a?(String) 
      #"\"#{self.collect{|v| v.sub('[','').sub(']','')}.join(" ")}\"" # quote and remove square brackets
      "NA"
    else
      self.median
    end
  end

  def remove indices
    out = self
    indices.sort.reverse_each do |i|
      out.delete_at i
    end
    out
  end

  # Correlation coefficient
  # @param [Array]
  # @return [Numeric]
  def r(y) 
    raise "Argument is not a Array class!"  unless y.class == Array
    raise "Self array is nil!"              if self.size == 0
    raise "Argument array size is invalid!" unless self.size == y.size

    mean_x = self.inject(0) { |s, a| s += a } / self.size.to_f
    mean_y = y.inject(0) { |s, a| s += a } / y.size.to_f
    cov = self.zip(y).inject(0) { |s, a| s += (a[0] - mean_x) * (a[1] - mean_y) }
    var_x = self.inject(0) { |s, a| s += (a - mean_x) ** 2 }
    var_y = y.inject(0) { |s, a| s += (a - mean_y) ** 2 }
    r = cov / Math.sqrt(var_x)
    r /= Math.sqrt(var_y)
  end
end