簡體   English   中英

Ruby百分位數計算以匹配Excel公式(需要重構)

[英]Ruby Percentile calculations to match Excel formulas (need refactor)

我已經用Ruby編寫了兩個簡單的計算,它們與Microsoft Excel計算給定數據集的上下四分位數的方式相匹配-與通常接受的方法(驚奇)不同。

我的問題是-為了最大程度地干燥,這些方法可以重構多少?

# Return an upper quartile value on the same basis as Microsoft Excel (Freund+Perles method)
  def excel_upper_quartile(array)
      return nil if array.empty?
      sorted_array = array.sort
      u = (0.25*(3*sorted_array.length+1))
      if (u-u.truncate).is_a?(Integer)
        return sorted_array[(u-u.truncate)-1]
      else
        sample = sorted_array[u.truncate.abs-1]
        sample1 = sorted_array[(u.truncate.abs)]
        return sample+((sample1-sample)*(u-u.truncate))
      end
  end


  # Return a lower quartile value on the same basis as Microsoft Excel (Freund+Perles method)
  def excel_lower_quartile(array)
      return nil if array.empty?
      sorted_array = array.sort
      u = (0.25*(sorted_array.length+3))
      if (u-u.truncate).is_a?(Integer)
        return sorted_array[(u-u.truncate)-1]
      else
        sample = sorted_array[u.truncate.abs-1]
        sample1 = sorted_array[(u.truncate.abs)]
        return sample+((sample1-sample)*(u-u.truncate))
      end
  end

我將首先進行概括,並提供一種方法來處理兩個實例。

def excel_quartile(array, quartile)
  # Returns nil if array is empty and covers the case of array.length == 1
  return array.first if array.length <= 1
  sorted = array.sort
  # The 4th quartile is always the last element in the sorted list.
  return sorted.last if quartile == 4
  # Source: http://mathworld.wolfram.com/Quartile.html
  quartile_position = 0.25 * (quartile*sorted.length + 4 - quartile)
  quartile_int = quartile_position.to_i
  lower = sorted[quartile_int - 1]
  upper = sorted[quartile_int]
  lower + (upper - lower) * (quartile_position - quartile_int)
end

然后,您可以使用以下便捷方法:

def excel_lower_quartile(array)
  excel_quartile(array, 1)
end

def excel_upper_quartile(array)
  excel_quartile(array, 3)
end

注意: excel_quartile方法匹配quartile in { 1, 2, 3, 4}quartile in { 1, 2, 3, 4}期望。 除此之外,我保證會失敗。

更新:

我引用的網站上未明確給出我使用的公式,但這是Freund和Perles方法計算四分位數位置的抽象方法。

進一步更新:

原始代碼中有一個錯誤,盡管您永遠都不會遇到它: u - u.trunc始終在[ u - u.trunc )的區間內,因此唯一類似於整數的時間是u - u.trunc = 0 但是,每當u為Float時(u - u.trunc)仍然是Float的實例,因此您的代碼永遠不會發生在計算錯誤的索引上。 順便說一句,如果u-u.trunc是整數,則您的方法將返回數組的最后一個元素。

有人可能不同意重構,但這是我的處理方式:

def excel_quartile(extreme,array)      
  return nil if array.empty?
  sorted_array = array.sort
  u = case extreme
  when :upper then 3 * sorted_array.length + 1
  when :lower then sorted_array.length + 3
  else raise "ArgumentError"
  end
  u *= 0.25
  if (u-u.truncate).is_a?(Integer)
    return sorted_array[(u-u.truncate)-1]
  else
    sample = sorted_array[u.truncate.abs-1]
    sample1 = sorted_array[(u.truncate.abs)]
    return sample+((sample1-sample)*(u-u.truncate))
  end
end

def excel_upper_quartile(array)
  excel_quartile(:upper, array)
end

def excel_lower_quartile(array)
  excel_quartile(:lower, array)
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM