查找表的平均值

时间:2011-05-18 23:24:26

标签: ruby

我需要找到第一列特定值的同一行中所有列的平均值。所以对于如下表格:

0   11  12  40
1   22  24  92
0   12  13  45
1   24  26  90
2   33  36  138
1   22  24  80
2   36  39  135
0   11  12  46
2   33  36  120

我想要得到的平均值表:

0   11.33333333 12.33333333 43.66666667     
1   22.66666667 24.66666667 87.33333333     
2   34  37  131

例如,对于值0 .. 我取第二列的平均值(11 + 12 + 11)/ 3,第二列的平均值为(12 + 13 + 12)/ 3,第三列的平均值为(46 + 45 + 40)/ 3

3 个答案:

答案 0 :(得分:3)

a = [
  [0,   11,  12,  40],
  [1,   22,  24,  92],
  [0,   12,  13,  45],
  [1,   24,  26,  90],
  [2,   33,  36,  138],
  ...
]

def average array, index
  array = array.select{|l| l[0] == index}
  n = array.length.to_f
  array.transpose.drop(1).map {|values| values.inject(0){|s, v| s += v}/n}
end

average(a, 0) # => [11.33333333, 12.33333333, 43.66666667]

立刻拥有所有这些:

array.group_by{|l| l[0]}.map do |k, array|
  n = array.length.to_f
  [k, array.transpose.drop(1).map {|values| values.inject(0){|s, v| s += v}/n}]
end

# =>
[
  [0, [11.33333333, 12.33333333, 43.66666667]],     
  [1, [22.66666667, 24.66666667, 87.33333333]]     
  [2, [34.0,  37.0,  131.0]]
]

答案 1 :(得分:2)

data = "0   11  12  40
        1   22  24  92
        0   12  13  45
        1   24  26  90
        2   33  36  138
        1   22  24  80
        2   36  39  135
        0   11  12  46
        2   33  36  120"

avgs = data.split(/\n/).map{|d| d.split(/\t/)}.group_by{|d| d[0] }.each{|a,b| b.each(&:shift) }.inject({}){|avg, (k, ar)| avg[k] = ar.inject([0,0,0]){|av,(a,b,c)| av[0]+=a.to_f; av[1]+=b.to_f; av[2]+=c.to_f; av}.map{|e| e/ar.size}; avg}
#=> {"0"=>[11.333333333333332, 12.333333333333332, 43.66666666666667], "1"=>[22.666666666666664, 24.666666666666664, 87.33333333333334], "2"=>[34.0, 37.0, 131.0]}

打印它:

avgs.each{|k, arr| puts [k,*arr].join("\t") }
#=> 0   11.333333333333332  12.333333333333332  43.66666666666667
#=> 1   22.666666666666664  24.666666666666664  87.33333333333334
#=> 2   34.0    37.0    131.0

<强> UPD

我已经清理了一下我的方法:

avgs = data.split(/\n/).
            map{|d| d.split(/\t/).map(&:to_f)}.
            group_by(&:first).
            inject({}){|avg, (k, ar)| avg[k] = ar.transpose[1..-1].map{|av| av.inject(:+)/av.size}; avg} 

答案 2 :(得分:1)

说你有一张表table = [ [0, 11, 12, 40] , [1, 22, 24, 92] .... [2, 33, 36, 120] ]

我假设该表在一行中有固定数量的元素

first_elements_array = table.map { |line| line[0] }.uniq! #get [0,1,2] from your table

avgs = [] #will contain your [ [0, 11.333, 12.3333, 43.66667], ... ]

for element in first_elements_array
  #i need an array with 4 zeros - the number of elements on a line
  temp_sum = [0,0,0,0]
  count = 0 #number of lines that start with 0, or 1, or 2 etc

  #read the lines that start with 0, then 1, then 2 etc
  for line in table
    if line[0] == element
      count += 1
      #add in temp_sum the new line found, element by element
      (0...line.length).each do |i|
         temp_sum[i] += line[i]
      end
    end
  end

  line_avg = []

  #so, temp_sum contains the sum for one line that starts with 0 or 1 or 2 etc. now calculate the average
  for sum in temp_sum
    line_avg << sum/count
  end

  #... and push it in an array
  avgs << line_avg

end

这可能会更优雅,所以随意适应它

另外,没有时间测试它,让我知道它是否有效