计算给定输入数据及其频率的中位数

时间:2014-07-29 20:35:14

标签: algorithm median

我收到以下输入:

num: counts
1:5
2:4
3:8

这个数字与频率之比:

为了计算这个输入的中位数,我做了一个天真的方法,用这些元素填充数组

>>>l = [1,1,1,1,1,2,2,2,2,3,3,3,3,3,3,3,3]
>>>i = len(l)/2
>>> median = l[i] if not i%2 else l[i+1]
>>> median
2

这是对的。但是,我不必要地使用数组来填充。 我想知道是否有一种数学方法来获得中位数给定数量及其出现频率。

4 个答案:

答案 0 :(得分:1)

您可以按顺序开始对频率求和,并在总和超过总计数的一半时找到中位数。

counts = {1: 5, 2: 4, 3: 8}
total = sum(counts.values())
s = 0
for k in sorted(counts.keys()):
  s += counts[k]
  if s > total / 2:
    break
print 'median:', k

答案 1 :(得分:0)

您是否需要准确的中位数或估计中位数。

要获得精确的中位数,您可以迭代频率集并继续添加频率值。当总和大于总返回量的一半时。红宝石中的等价物(假设输入按键排序):

def median(h)
  half = h.values.inject(:+).to_f/2
  sort = h.sort 
  sum = 0
  prev = 0
  sort.each do |k, v|
    if prev.nonzero?
      return (k + prev).to_f/2
    end
    sum+=v
    if sum == half 
      prev = k
    elsif sum > half
      return k
    end
  end
end

median({1=>5, 2 => 4, 3 => 8})

存在计算估计媒体的公式

median = l + ((n/2) − cfb)*w/fm

其中

  • l是包含中位数
  • 的组的下层边界
  • n是数据总数
  • cfb是中位数组之前的组的累积频率
  • fm是中位数组的频率
  • w是组宽度

答案 2 :(得分:0)

您可以利用累积总和(例如pandas或numpy中的cumsum())。这是一个例子。

import pandas as pd
data = pd.Series([5,4,8], index = [1,2,3])


data.sort_index()                   # sort just in case
mid  = data.sum() / 2.0             # index of the middle element

cum = data.cumsum()                 # cumulative sums of your data frequencies
median = cum[cum >= mid].argmin()   # ignore the first half of the data and get the 
                                    # index of the median element

答案 3 :(得分:0)

假设您的输入已完全排序,您提供的输入是,您可以这样做: 将每个数字的频率相加。如果是偶数,除以2.如果是奇数,则将频率加1并除以2。在您提供的示例输入中,执行此操作将产生9。

现在将输入的频率相加并在它们达到9时停止。与您停止的频率相邻的值(num)是您的中位数。在这种情况下,它是2.