我想了解select
和$
到R中子集列的速度差异(这是因为它们并没有完全返回 ,而是都执行相同的操作概念性get-me-a-column
操作)。我想了解哪种情况最合适。
特别是,在什么情况下,以下select
语句会比相应的$
语句快?
语法是:
select(df, colName1, colName2, ...)
df$colName
答案 0 :(得分:2)
总而言之,当开发速度,易于理解或易于维护最为重要时,应使用dplyr
。
dplyr
的运算所花的时间比基数R所花的时间更长。 dplyr
返回一个不同的(更复杂的)对象。 $
和类似的操作可以更快地执行,但是会带来额外的风险(例如,部分匹配的行为);可能难以阅读和/或维护;返回一个(最小的)矢量对象,该对象可能缺少数据框的某些上下文相关性。这也可能有助于弄清dplyr
正在为目标列做 alot 的工作(如果不想避免查看软件包的源代码)。这也是一个不公平的测试,因为我们得到了不同的结果,但是所有操作都是“给我本专栏文章”操作,因此请在此上下文下阅读它:
library(dplyr)
microbenchmark::microbenchmark(
base1 = mtcars$cyl, # returns a vector
base2 = mtcars[['cyl', exact = TRUE]], # returns a vector
base2a = mtcars[['cyl', exact = FALSE]], # returns a vector
base3 = mtcars[,"cyl"], # returns a vector
base4 = subset(mtcars, select = cyl), # returns a 1 column data frame
dplyr1 = dplyr::select(mtcars, cyl), # returns a 1 column data frame
dplyr2 = dplyr::select(mtcars, "cyl"), # returns a 1 column data frame
dplyr3 = dplyr::pull(mtcars, cyl), # returns a vector
dplyr4 = dplyr::pull(mtcars, "cyl") # returns a vector
)
## Unit: microseconds
## expr min lq mean median uq max neval
## base1 4.682 6.3860 9.23727 7.7125 10.6050 25.397 100
## base2 4.224 5.9905 9.53136 7.7590 11.1095 27.329 100
## base2a 3.710 5.5380 7.92479 7.0845 10.1045 16.026 100
## base3 6.312 10.9935 13.99914 13.1740 16.2715 37.765 100
## base4 51.084 70.3740 92.03134 76.7350 95.9365 662.395 100
## dplyr1 698.954 742.9615 978.71306 784.8050 1154.6750 3568.188 100
## dplyr2 711.925 749.2365 1076.32244 808.9615 1146.1705 7875.388 100
## dplyr3 64.299 78.3745 126.97205 85.3110 112.1000 2383.731 100
## dplyr4 63.235 73.0450 99.28021 85.1080 114.8465 263.219 100
但是,如果我们有 alot 列怎么办:
# Make a wider version of mtcars
do.call(
cbind.data.frame,
lapply(1:20, function(i) setNames(mtcars, sprintf("%s_%d", colnames(mtcars), i)))
) -> mtcars_manycols
# I randomly chose to get "cyl_4"
microbenchmark::microbenchmark(
base1 = mtcars_manycols$cyl_4, # returns a vector
base2 = mtcars_manycols[['cyl_4', exact = TRUE]], # returns a vector
base2a = mtcars_manycols[['cyl_4', exact = FALSE]], # returns a vector
base3 = mtcars_manycols[,"cyl_4"], # returns a vector
base4 = subset(mtcars_manycols, select = cyl_4), # returns a 1 column data frame
dplyr1 = dplyr::select(mtcars_manycols, cyl_4), # returns a 1 column data frame
dplyr2 = dplyr::select(mtcars_manycols, "cyl_4"), # returns a 1 column data frame
dplyr3 = dplyr::pull(mtcars_manycols, cyl_4), # returns a vector
dplyr4 = dplyr::pull(mtcars_manycols, "cyl_4") # returns a vector
)
## Unit: microseconds
## expr min lq mean median uq max neval
## base1 4.534 6.8535 12.15802 8.7865 13.1775 75.095 100
## base2 4.150 6.5390 11.59937 9.3005 13.2220 73.332 100
## base2a 3.904 5.9755 10.73095 7.5820 11.2715 61.687 100
## base3 6.255 11.5270 16.42439 13.6385 18.6910 70.106 100
## base4 66.175 89.8560 118.37694 99.6480 122.9650 340.653 100
## dplyr1 1970.706 2155.4170 3051.18823 2443.1130 3656.1705 9354.698 100
## dplyr2 1995.165 2169.9520 3191.28939 2554.2680 3765.9420 11550.716 100
## dplyr3 124.295 142.9535 216.89692 166.7115 209.1550 1138.368 100
## dplyr4 127.280 150.0575 195.21398 169.5285 209.0480 488.199 100
对于大量项目,dplyr
是一个不错的选择。但是,执行速度通常不是“ tidyverse”的属性,但是开发速度和表现力通常会超过速度差异。
注意:dplyr
动词可能比subset()
更好,而且-我懒惰地使用$
时,由于[[]]
的默认部分匹配行为,它也有点危险没有exact=TRUE
。进入一个好习惯(IMO)是在所有项目中都设置options(warnPartialMatchDollar = TRUE)
,而您并不是故意依靠这种行为的。
答案 1 :(得分:1)
不一样。如果您正在寻找相同的功能,则可以考虑使用同一dplyr软件包中的pull()。 Dollarsign从数据帧返回向量“ build”,pull也这样做。
答案 2 :(得分:0)
select
在dplyr软件包中,是dydyverse的一部分。 https://dplyr.tidyverse.org/
您可能会做类似
的操作df %>%
select(colName1, colName2)
从df中选择那些列。这些语句的写法类似于动词(例如,select,range,group_by等),使处理数据更加容易。
$
来自于r。它只会显示df中的那一列。