2014-03-25 23 views
1

一個月前我曾問過類似的問題。請參考 Count the occurrences of unequal numbers from a data frame如何自定義外部和Vectorize函數?

我用outerVectorize函數解決了這個問題。我的解決方案如下:

dist_mat<- outer(1:nrow(df),1:nrow(df), 
       FUN = Vectorize(function(i,j) sum(df[i,]!=df[j,]))) 

這工作完美,但現在我有一個巨大的矩陣,超過我的內存大小。

我得到dist_mat之後,對於每一行我計算列數少於或等於2,這是我現在無法做到的。所以,我想知道是否可以將外部函數中的計數操作結合起來以避免內存問題。我的結果只會是一個向量。

預先感謝您!

+0

羅蘭在另一個問題的答案是否也有記憶問題? [編輯我的評論進一步思考:它可能會,因爲它只減少了一半的操作,但增加了兩列。]這將是解決內存問題的一種方法;如果是這樣,矢量化操作可能會以某種方式用於獲取所需的計數。 – Aaron

回答

1

雖然這並不嚴格回答你的問題,你應該避免outer和使用這樣的:

tot.rows <- nrow(df) 
res <- numeric(tot.rows) 
for(i in 1:tot.rows) 
    for(j in 1:tot.rows) 
    res[[i]] <- res[[i]] + (sum(df[i,] != df[j,]) <= 2) 

outer將預先分配的i * j矩陣從一開始走,所以你要在使用外層時很難修復問題。如果結果的確是一個與數據幀長度相同的向量,則不需要outer,它會在您的應用程序中生成一個尺寸爲nrow(df) * nrow(df)的矩陣。

上述算法將運行與outer相同的計算次數,但爲每一行重新使用相同的內存空間,因爲所有您關心的都是最終計數,所以它應該適合內存。 它的速度也應該和外層的相當(這是我測試過的玩具例子)。只要實際需要計算每個值,並且有內存來處理像outer這樣的完全擴展,矢量化操作就非常棒,但它們不一定是所有事情的答案。

正如其他人在上一個答案中指出的那樣,如果距離計算是對稱的,那麼可以修改代碼,以便不計算對角線或矩陣的其中一個三角形,這應該大致減半計算時間。

+0

我在去矢量化之前就已經嘗試過了。我沒有內存問題,但運行了幾個小時。可能幾天(我在6個小時左右後停止了它)。 – Chris

+0

@Chris,'外部'版本應該運行得很慢。您是否比較了足夠小的數據子集上的兩種方法的性能,以適應內存?另外,看起來你真的想把計算限制在那些嚴格必要的計算上。你的數據中有重複嗎?你的數據是什麼(數字,因素,字符)? – BrodieG

+0

你說得對,外面也很慢。我有一個因子數據類型。我現在試圖找到一種方法來減少我的數據。 – Chris

1

如果你已經有了一個矩陣DF然後

apply(DF, 2, function(y) sum(colSums(DF==y) < 2)) 

可能會奏效? DF==y將每列與apply,colSums中的目標列進行比較,然後找出該列對中有多少行是相等的,我們將其與2進行比較(目標列始終與自身進行比較,作爲DF = = y,所以我已經將這個因素考慮在內 - 您可能需要考慮這一點,具體取決於您的'2'閾值是否包括自我比較)。然後最終sum計算滿足< 2閾值的列數。

假設你不需要中間距離矩陣,它完全重新考慮了代碼。

+0

您的數據可能還有一些功能可能會使效率更高。例如你可以使用'apply(DF,1,anyDuplicated)== 0'移除沒有任何重複值的行 - df的維數是多少?是否有很多列組合,或者是列的長度? –

+0

Gavin,我認爲OP正在試圖比較行,而不是列,而且看起來你在做相反的事情(我認爲?)? – BrodieG

+0

A'DF < - t(DF)'應該對此進行排序,除非我已經將它解釋爲一列中的列和另一列中的列,這完全是可能的!而且這可能是值得標杆的,這對於OPs數據來說效果最好,因爲我們不知道它是長而細,還是短而寬,以及重複的流行等等。 –