2014-02-24 92 views
1

我有大約300個文件,每個文件包含1000個時間序列實現(〜76 MB每個文件)。計算大數據的分位數

我想從整個300000實現的每個時間步計算分位數(0.05,0.50,0.95)。

我無法將1個文件中的實現合併在一起,因爲它會變得太大。

這樣做的最有效方法是什麼?

通過運行模型生成的每個矩陣,但這裏是一個包含隨機數的樣本:

x <- matrix(rexp(10000000, rate=.1), nrow=1000) 

回答

2

至少有三種選擇:

  1. 你確定它必須是從全套? 10%的樣本應該是一個非常非常好的近似值。
  2. 300k個元素不是那麼大的一個向量,但是一個300k x 100 +列矩陣很大。將需要的列拖到內存中,而不是整個矩陣(如果需要,可以在每列中重複)。
  3. 按順序進行,可能與一個較小的樣本結合起來,讓您開始在正確的場地。對於第五百分位數,您只需知道當前猜測上方有多少物品,以及下方有多少物品。所以像這樣:
    1. 採取1%的樣本,找到它的第5個百分點。在上下跳動一些容差,以確保第5個百分點位於該範圍內。
    2. 以塊爲單位讀取矩陣。對於每個塊,計數在範圍之上和範圍之下的觀測值的數量。然後保留在該範圍內的所有觀察值。
    3. 當你讀完最後一個塊時,你現在有三條信息(上面的計數,下面的計數,內部的觀察向量)。採取分位數的一種方法是對整個向量進行排序並找到第n個觀察值,並且可以用上述信息做到這一點:對範圍內的觀察值進行排序,並找到(n-count_below)th。

編輯:實施例(3)。

請注意,我不是一個冠軍算法設計師,有人幾乎可以肯定爲此設計了一個更好的算法。而且,這個實現並不是特別有效。如果速度對您來說很重要,請考慮Rcpp,或者爲此更加優化R。製作一堆列表然後從中提取數值並不是那麼聰明,但是這樣做很容易,所以我就使用它。

library(plyr) 

set.seed(1) 

# -- Configuration -- # 
desiredQuantile <- .25 

# -- Generate sample data -- # 

# Use some algorithm (sampling, iteration, or something else to come up with a range you're sure the true value lies within) 
guessedrange <- c(.2, .3) 
# Group the observations to correspond to the OP's files 
dat <- data.frame(group = rep(seq(100), each=100), value = runif(10000)) 

# -- Apply the algorithm -- # 

# Count the number above/below and return the values within the range, by group 
res <- dlply(dat, .(group), function(x, guessedrange) { 
    above <- x$value > guessedrange[2] 
    below <- x$value < guessedrange[1] 
    list(
    aboveCount = sum(above), 
    belowCount = sum(below), 
    withinValues = x$value[ !above & !below ] 
) 
}, guessedrange = guessedrange) 
# Exract the count of values below and the values within the range 
belowCount <- sum(sapply(res, function(x) x$belowCount)) 
belowCount 
withinValues <- do.call(c, sapply(res, function(x) x$withinValues)) 
str(withinValues) 
# Count up until we find the within value we want 
desiredQuantileCount <- floor(desiredQuantile * nrow(dat)) #! Should fix this so it averages when there's a tie 
sort(withinValues)[ desiredQuantileCount - belowCount + 1 ] 
# Compare to exact value 
quantile(dat$value, desiredQuantile) 

最後,這個值與確切的版本有些偏差。我懷疑我被一個或一些同樣愚蠢的解釋轉移了過來,但也許我錯過了一些基本的東西。

+0

感謝您的回答! 1.我需要全套設置,因爲每個文件都是不同模型的結果,不同的模型會返回非常不同的結果。 2.每一列代表一個時間步驟,因此我需要所有列。 3.如果我理解的很好,這種方法會返回很好的近似值,但不是確切的值,對嗎? – Claudia

+0

(3)應該是確切的。但(1)的要點是你可以抽樣。因此,加載每個文件,抽樣1或5%的行,加載下一個文件。隨機化的樂趣意味着你得到的答案會非常接近確切的版本。 –

+0

在(3)中必須有不同的範圍(特別是因爲模型不同),所以你不能簡單地將所有收集的範圍數據排序在一起:它們不對齊。必須檢測所有範圍的交集(每個給出一個子範圍),然後在那裏進行排序可以完成,但是分位數計算仍然不是那麼直接,因爲每個子範圍都有不同的「移位」(它們是來自不同的概率間隔!)。如果你考慮所有*和*範圍內的抽樣不確定性,那麼算法應該可以正常工作。 – Quartz