R中“选择”和“ $”之间的区别

时间:2018-10-20 05:42:11

标签: r dplyr

我想了解select$到R中子集列的速度差异(这是因为它们并没有完全返回 ,而是都执行相同的操作概念性get-me-a-column操作)。我想了解哪种情况最合适。

特别是,在什么情况下,以下select语句会比相应的$语句快?

语法是:

select(df, colName1, colName2, ...)
df$colName

3 个答案:

答案 0 :(得分:2)

总而言之,当开发速度,易于理解或易于维护最为重要时,应使用dplyr

  • 以下基准表明,dplyr的运算所花的时间比基数R所花的时间更长。
  • dplyr返回一个不同的(更复杂的)对象。
  • 基数R $和类似的操作可以更快地执行,但是会带来额外的风险(例如,部分匹配的行为);可能难以阅读和/或维护;返回一个(最小的)矢量对象,该对象可能缺少数据框的某些上下文相关性。

这也可能有助于弄清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中的那一列。