2012-07-04 50 views
1

大廈關閉和更早的問題:Computing stats on generators in single pass. Python如何用一次通過計算髮電機的百分位數和等級?

正如我前面提到的一樣,從一個生成器計算統計數據是非常快速和高效的。複雜的統計數據和排名屬性(如第90百分位數和第n位最小數)往往需要比標準偏差和平均數更復雜的工作(在上面解決)。這些方法在處理地圖/縮減作業和將數據放入列表或計算多次通過的大型數據集變得非常緩慢時變得非常重要。

以下是用於查找基於排名順序的數據的O(n)快速排序樣式算法。用於尋找中位數,百分位數,四分位數和十進制數。等同於數據已經排序後的數據[n]。但是需要列表中的所有數據可以拆分/旋轉。

如何用一次通過計算髮生器的中位數,百分位數,四分位數和十位數?

需要的完整列表

import random 

def select(data, n): 
    "Find the nth rank ordered element (the least value has rank 0)." 
    data = list(data) 
    if not 0 <= n < len(data): 
     raise ValueError('not enough elements for the given rank') 
    while True: 
     pivot = random.choice(data) 
     pcount = 0 
     under, over = [], [] 
     uappend, oappend = under.append, over.append 
     for elem in data: 
      if elem < pivot: 
       uappend(elem) 
      elif elem > pivot: 
       oappend(elem) 
      else: 
       pcount += 1 
     if n < len(under): 
      data = under 
     elif n < len(under) + pcount: 
      return pivot 
     else: 
      data = over 
      n -= len(under) + pcount 
+0

你是什麼意思的「與發電機」?你的意思是一個在線分位數選擇算法?你的記憶力有多大? P.S. 「Quicksort風格」算法被稱爲QuickSelect,因爲它選擇QuickSort風格的第k個元素。 –

+0

生成器是python術語,用於收集您可以通過一次收集數據。是的,我的意思是一個在線分位數選擇算法。感謝您的QuickSelect。 –

+0

您尚未回答內存限制問題。這是必不可少的,因爲你正在尋找的元素可能是第一個,所以你可能需要記住整個流(除非你知道流大小的界限,那就是) –

回答

4

您將需要存儲數據的大部分地區的快速排序算法的風格。直到它可能只是爲了完全存儲它而付清。除非你願意接受一個近似算法(當你知道你的數據是獨立的時候這可能是非常合理的)。

考慮你需要找到以下數據集的中位數:

0 1 2 3 4 5 6 7 8 9 -1 -2 -3 -4 -5 -6 -7 -8 -9 

中位數明顯0。但是,如果您只看到前10個元素,那麼這是您當時最糟糕的猜測!因此,爲了找到一個n元素流的中位數,您至少需要在內存中保留n/2候選元素。如果你不知道總大小n,你需要保持所有!

這裏是每一個奇數大小的情況位數:

0 _ 1 _ 2 _ 3 _ 4 _ 4 _ 3 _ 2 _ 1 _ 0 

雖然他們從來沒有人選,你還需要記住元素5 - 9:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 

產生的中位數9 。對於n的一系列大小的每一個元素,我都可以找到一個連續的大小爲O(2 * n)的系列,它具有這個元素作爲中值。但顯然,這些系列不是隨機的/獨立的。

有關相關方法的概述,請參閱"On-line" (iterator) algorithms for estimating statistical median, mode, skewness, kurtosis?