【问题标题】:How do I create an average for a temperature data set?如何为温度数据集创建平均值?
【发布时间】:2013-09-30 06:25:23
【问题描述】:

我正在编写一个程序,它获取一组数据然后对其进行平均。这个数据集是拉瓜迪亚机场每个月的平均温度,对应一个温度。

这是一个数据点的示例:

    2009-07,23.6

哪个是年月,温度。

我有 163 个数据点。所有数据点都在一个 .txt 文件中,每个都在一个新行上。

我把数据做成一个数组,然后拆分。由于某种原因,我的程序每次尝试运行它时都说我的平均值为 0

这是我的代码:

data = File.open("avg_temp.txt", "r+")

contents = data.read

contents = contents.split("\r\n")

contents.collect! do |x|
        x.split(',')
end


sum = 0

data.each do |x|

sum = sum  + x[1].to_f

end

avg = sum / contents.length

puts avg

【问题讨论】:

    标签: ruby-on-rails ruby arrays ruby-on-rails-3 split


    【解决方案1】:

    在循环结束后分配avg = sum/contents.length。在循环中定义的变量的范围仅限于该循环。你也循环data,应该是content

    contents.each do |x|
    
        puts x[1] # to check if the right value is being evaluated
        sum = sum  + x[1].to_f     
    
    end
    
    avg = sum/contents.length
    

    【讨论】:

    • 你在循环中有temp[1],但它没有在任何地方定义..它应该是x[1]吗?
    • 我这样做了,但仍然是 0
    • 更新了答案,它将循环中的值打印到控制台,以便您查看发生了什么。
    【解决方案2】:

    您的avg 不是顶级局部变量。因此,您无法从顶层访问它。 avg 仅限于块。您可以执行以下操作:-

    avg = 0
    
    data.each do |x|
      sum = sum  + temp[1].to_f
      avg = sum / contents.length
    end
    
    puts avg
    

    【讨论】:

    • 这会重新计算avg,在循环内部没有真正的目的,作为一种未使用的“运行平均值”。对于 OP,它只需要在总和完成时计算。
    • @NeilSlater 你是对的!我只是想展示他能做什么来消除错误..
    • 我将 avg = sum / contents.length 切换到循环之外。它修复了错误,但现在它说我的平均值为 0.???
    【解决方案3】:
    sum = 0
    data.each do |x|
        sum = sum  + temp[1].to_f
        avg = sum / contents.length
    end
    puts avg
    

    avg 变量不再在范围内,因为它在每个块之外。要打印平均值,只需像这样将其移动到块内

    sum = 0
    data.each do |x|
        sum = sum  + temp[1].to_f
        avg = sum / contents.length
        puts avg
    end
    

    或者将 avg 变量移到循环之外(在循环退出后执行一次操作)

    sum = 0
    data.each do |x|
        sum = sum  + temp[1].to_f
    end
    
    avg = sum / contents.length
    puts avg
    

    更多信息http://rubyflare.com/2009/09/30/variables-scope-and-iterators/

    【讨论】:

    • 进行了更改,但说我的平均值是 0
    • 不确定变量 temp 是在哪里定义的,但请看这个例子:contents = (1..90).to_a; sum = 0; contents.each { |x| sum += x } #> 4095 这表明现在总和是 == 4095 avg = sum/contents.length #> 45 这样我们就有了 45 的平均值.
    • 但我的程序的重点是不要手动将所有温度相加。我有数百个数据点
    • 我没有手动将这些数字相加 - 我只是创建了 contents 变量来向您展示如何在您的代码中执行此操作,并且上述方法有效。当然,如果你的 temp[1].to_f 的结果是 nil 或 0 值,那么总和永远不会增加。
    • 在我的程序中该方法放在哪里?
    【解决方案4】:

    我会写得更简单:

    lines = 0
    sum = 0
    
    File.foreach("avg_temp.txt") do |data|
      sum += data.split(',').last.to_f
      lines = $.
    end
    
    puts 'Average: %f over %d datapoints' % [sum / lines.to_i, lines]
    # >> Average: 23.375000 over 4 datapoints
    

    哪些输出:

    Average: 23.375000 over 4 datapoints
    

    以“avg_temp.txt”开头,如下所示:

    2009-07,23.6
    2009-08,23.7
    2009-09,23.6
    2009-10,22.6
    

    解释一下:

    • $. 是当前行号。每次通过循环时,它都会将最后读取的行号重新分配给lines,因此我们知道要除以多少。
    • foreach 逐行读取,因此无需拆分文件。这也解释了为什么我使用$. 来跟踪元素的数量。这也意味着这可以毫无问题地读取包含数百万或数十亿值的文件,而 read 会屈服。

    【讨论】:

      猜你喜欢
      • 2023-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多