2014-01-09 29 views
5

我非常困惑,爲什麼按行索引訪問data.table比data.frame慢。任何建議如何我可以訪問每一行data.table順序循環,這是更快?爲什麼data.table行索引上的for循環比data.frame上的慢?

m = matrix(1L, nrow=100000, ncol=100) 

DF = as.data.frame(m) 
DT = as.data.table(m) 

identical(DF[100, ], DT[100, ]) 
[1] FALSE 

> all(DF[100, ], DT[100, ]) 
[1] TRUE 

> system.time(for (i in 1:1000) DT[i,]) 
    user system elapsed 
    5.440 0.000 5.451 

R> system.time(for (i in 1:1000) DF[i,]) 
    user system elapsed 
    2.757 0.000 2.784 
+3

最簡單的解釋是''.data.table'比'[.data.frame'做了更多*事情。 – Arun

+0

如何更快地迭代行索引的data.frame行? – user3147662

+0

我已在此處創建了[FR#5260](https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5260&group_id=240&atid=978)。感謝您的報告。應該有可能獲得更多的速度。 – Arun

回答

6

data.table查詢具有多個參數(和它更多)所以DT[...]小開銷比DF[...]大。如果你循環它,這個開銷會加起來。 data.table的預期用途是使其執行幾次大型複雜操作,而不是多次小型微小計算。所以讓我們重新制定你的測試:

> system.time(DT[seq(len=nrow(m)),]) 
user system elapsed 
0.08 0.02 0.09 
> system.time(DF[seq(len=nrow(m)),]) 
user system elapsed 
0.08 0.05 0.13 

在這裏,它們大致相同。由於我們只有一個DT呼叫,開銷並不明顯,因爲開銷只能執行一次。在你的情況下,你執行了100K次(不必要的,我可能會添加)。如果您使用的是data.table,並且您正在撥打數千次電話,則可能是錯誤的。幾乎可以肯定的是有一種方法來重新配置,這樣你就可以做一個或幾個data.table調用來做同樣的事情。

此外,請注意,即使我在這裏重新配置的測試是相當平凡的,這就是爲什麼data.tabledata.frame的性能相當。

+0

對不起,您的第一行是什麼意思?每個data.table語句的開銷是多少? – Arun

+1

''.data.table'在解析時是1000行代碼,而'[.data.frame'是145.#代碼行絕對不是一個很好的開銷比較,但顯然'data.table'需要做waaay比'[.data.frame'更適合對不同的輸入作出反應。這並不差,只是意味着如果你打算用'data.table'完成一個簡單的計算,並且每次都調用'[.data.table',你會注意到相關的開銷處理'[data.table'管理的所有特殊條件。由於這不是數據表的正確用法,所以不是問題 – BrodieG

+0

一直以來。但是我們可以獲得更多的加速。一旦我測試了一些想法,我就會回信。 – Arun