2017-09-12 27 views
5

考慮以下基準(Windows機器R上3.4.1):時差對象

library(rbenchmark) 

mtx <- matrix(runif(1e8), ncol = 100) 
df <- as.data.frame(mtx) 

colnames(mtx) <- colnames(df) <- paste0("V", 1:100) 

benchmark(
    mtx[5000:7000, 80], 
    mtx[5000:7000, "V80"], 
    mtx[, "V80"][5000:7000], 
    mtx[, "V80", drop = FALSE][5000:7000, ], 
    mtx[5000:7000, , drop = FALSE][, "V80"], 
    #mtx$V80[5000:7000], # does not apply 
    replications = 5000 
) 

##          test replications elapsed relative user.self sys.self user.child sys.child 
## 4 mtx[, "V80", drop = FALSE][5000:7000, ]   5000 64.71 588.273  47.44 16.61   NA  NA 
## 3     mtx[, "V80"][5000:7000]   5000 72.15 655.909  52.90 18.18   NA  NA 
## 2     mtx[5000:7000, "V80"]   5000 0.11 1.000  0.11  0.00   NA  NA 
## 5 mtx[5000:7000, , drop = FALSE][, "V80"]   5000 7.47 67.909  5.89  1.47   NA  NA 
## 1      mtx[5000:7000, 80]   5000 0.13 1.182  0.12  0.00   NA  NA 

benchmark(
    df[5000:7000, 80], 
    df[5000:7000, "V80"], 
    df[, "V80"][5000:7000], 
    df[, "V80", drop = FALSE][5000:7000, ], 
    df[5000:7000, , drop = FALSE][, "V80"], 
    df$V80[5000:7000], 
    replications = 5000 
) 

##          test replications elapsed relative user.self sys.self user.child sys.child 
## 6      df$V80[5000:7000]   5000 0.13 1.000  0.12  0.00   NA  NA 
## 4 df[, "V80", drop = FALSE][5000:7000, ]   5000 0.33 2.538  0.33  0.00   NA  NA 
## 3     df[, "V80"][5000:7000]   5000 0.17 1.308  0.17  0.00   NA  NA 
## 2     df[5000:7000, "V80"]   5000 0.15 1.154  0.16  0.00   NA  NA 
## 5 df[5000:7000, , drop = FALSE][, "V80"]   5000 13.63 104.846  12.91  0.39   NA  NA 
## 1      df[5000:7000, 80]   5000 0.19 1.462  0.17  0.00   NA  NA 

的時間差是相當驚人的。這是爲什麼?什麼是建議子集的方式,爲什麼?考慮到基準,矩陣的mtx[i, colname]方式和df$colname[i](但它似乎沒有太大的差別)data.frame似乎是最省時間的,但是有什麼一般原因爲什麼我們應該更喜歡任何方法嗎?

+1

並不總是推薦data.frame的$ -extraction。它僅用於交互式使用。您可以添加'df [[「V80」]]和'df [[80]]'提取方法。 –

+0

只要使用哪一個是最快的爲您的特定矩陣/ data.frame(假設子設置的速度甚至是代碼的阻塞部分)。它通常更好的做一個子集操作'[]'而不是兩個[] []'。你有不同的選擇,所以你可以選擇哪一個更具可讀性或使你的代碼更易於理解。 – MrFlick

回答

1

主要原因在於矩陣和data.frames後面的R數據結構。矩陣基本上是一個具有rownumber x columnnumber(主要是數字)條目(由R的默認矩陣不稀疏)和維屬性的對象。出於這個原因,你的第一個2個命令

mtx[5000:7000, 80], 
mtx[5000:7000, "V80"] 

再次提取矩陣,其中:R不能只分配值,而且尺寸創建新的Matrix對象簡單的載體,其爲R的默認對象來代替。

另一方面,R中的data.frame通過定義是一種特殊類型的列表對象,其中每個列對象的長度必須相同,而列可以包含不同類型的變量(數字,字符串等)。矩陣只能包含單個類型的變量,默認情況下這是最常用的變量。因此,

df[5000:7000, 80] 

提取第80列的向量,然後提取出位置5000-7000之外的值。 R比矩陣對象更容易處理矢量,因此速度要快得多。

但是,如果選擇drop = FALSE,則強制R在選擇第80列時不能使用簡單的矢量對象,而應將其視爲data.frame/list對象。列表是R對象中最通用和最靈活的類型,因爲它們的大小和條目沒有限制,但是這樣做的代價是它們最難以處理,並且比較時可以觀察到

mtx[5000:7000, , drop = FALSE][, "V80"] 
df[5000:7000, , drop = FALSE][, "V80"] 

從數據框中獲得另一個data.frame/list,而矩陣仍然返回比列表處理速度更快的矩陣。