web-dev-qa-db-ja.com

Rのデータフレームの行をサブセット化するより速い方法は?

私はこれらの2つの方法を同じ意味で使用して、Rのデータフレームからデータをサブセット化しました。
方法1
subset_df <- df[which(df$age>5) , ]
方法2
subset_df <- subset(df, age>5)

これらに属する2つの質問がありました。
1。非常に大きなデータがあることを考えると、どちらが速いですか?
2。ここでのこの投稿 Rでのデータフレームのサブセット化 は、上記の2つの方法の間に実際には違いがあることを示唆しています。それらの1つはNAを正確に処理します。では、どちらが安全に使用できますか?

11
shubham

質問は、データフレームの行をサブセット化するためのより高速な方法を求めています。最速の方法はdata.tableを使用することです。

_set.seed(1)  # for reproducible example
# 1 million rows - big enough?
df <- data.frame(age=sample(1:65,1e6,replace=TRUE),x=rnorm(1e6),y=rpois(1e6,25))

library(microbenchmark)
microbenchmark(result<-df[which(df$age>5),],
               result<-subset(df, age>5), 
               result<-df[df$age>5,],
               times=10)
# Unit: milliseconds
#                               expr       min        lq    median       uq      max neval
#  result <- df[which(df$age > 5), ]  77.01055  80.62678  81.43786 133.7753 145.4756    10
#      result <- subset(df, age > 5) 190.89829 193.04221 197.49973 203.7571 263.7738    10
#         result <- df[df$age > 5, ] 169.85649 171.02084 176.47480 185.9394 191.2803    10

library(data.table)
DT <- as.data.table(df)     # data.table
microbenchmark(DT[age > 5],times=10)
# Unit: milliseconds
#         expr      min       lq  median       uq      max neval
#  DT[age > 5] 29.49726 29.93907 30.1813 30.67168 32.81204    10
_

したがって、この単純なケースでは、data.tableはwhich(...)の2倍強、subset(...)の6倍以上高速です。

21
jlhoward

次を追加してコードを書き直します。

  • サブセット化演算子[[;

  • filterfrom "dplyr" package;

  • 標準評価 を使用する関数。



# 1. Libraries library(microbenchmark) library(data.table) library(dplyr) # 2. Reproducibility set.seed(1) # 3. Create data structures (1e6 rows) # 3.1. Data frame df <- data.frame( age = sample(1:65, 1e6, replace = TRUE), x = rnorm(1e6), y = rpois(1e6,25)) # 3.2. Data table dt <- as.data.table(df) # 4. Helper functions # 4.1. Function that uses standard evaluation # http://adv-r.had.co.nz/Computing-on-the-language.html subset2_q <- function(x, condition) { r <- eval(condition, x, parent.frame()) x[r, ] } subset2 <- function(x, condition) { subset2_q(x, substitute(condition)) } # 5. Benchmarks microbenchmark( # 5.1. Data frame (basic operations) df[which(df$age > 5), ], df[df$age > 5, ], subset(df, age > 5), df[df[['age']] > 5, ], # 5.2. Data frame (dplyr) df %>% filter(age > 5), # 5.3. Data table (basic) dt[age > 5], dt %>% filter(age > 5), # 5.4. Data frame and table with 'subset2' dt %>% subset2(age > 5), df %>% subset2(age > 5), # 5.5. How many times times = 10) # Results expr min lq mean median uq max neval cld df[which(df$age > 5), ] 83.07726 88.77624 102.20981 90.08606 91.52631 212.10305 10 b df[df$age > 5, ] 72.17319 79.98209 80.68900 81.42234 82.33832 84.46876 10 b subset(df, age > 5) 84.95796 85.90815 88.79125 88.03345 89.49680 95.37453 10 b df[df[["age"]] > 5, ] 71.39021 80.22755 81.86848 81.33061 82.38236 104.97732 10 b df %>% filter(age > 5) 21.37622 21.97020 23.57504 22.27681 25.17569 29.64354 10 a dt[age > 5] 20.26226 20.55946 36.58179 25.24155 29.68587 143.57794 10 a dt %>% filter(age > 5) 21.35613 21.76579 25.57424 22.02750 30.99570 32.18407 10 a dt %>% subset2(age > 5) 20.41449 20.57485 23.93314 20.70827 28.63391 31.15306 10 a df %>% subset2(age > 5) 77.43044 79.63956 92.24558 80.80100 81.61990 197.36958 10 b

最良の結果は、data.tableおよびdf%>%filter(age> 5)演算子。したがって、dplyrを使用したdata.frameも役立ちます。

5
Andrii