Разница между «выберите» и «$» в R

голоса
-1

Я хочу , чтобы понять разницу в скорости между selectи $для подмножества столбцов в R ( в то время оценивая , что они не возвращаются в точности те же самые вещи, а как выполнить концептуальную get-me-a-columnоперацию). Я хотел бы понять , когда либо является наиболее подходящим.

В частности, при каких условиях будет следующее selectутверждение быстрее , чем соответствующее $заявление?

Синтаксис:

select(df, colName1, colName2, ...)
df$colName
Задан 20/10/2018 в 05:42
источник пользователем
На других языках...                            


3 ответов

голоса
2

Таким образом, вы должны использовать , dplyrкогда скорость развития, легкость понимания и простоту в обслуживании является наиболее важной.

  • Контрольные показатели ниже , показывает , что эта операция занимает дольше , dplyrчем основание R эквиваленты.
  • dplyr возвращает другой (более сложный) объект.
  • Базовый R $и подобные операции могут быть быстрее выполнить, но поставляются с дополнительными рисками (например , частичное поведение соответствия); может быть труднее читать и / поддерживать; возвращать (минимальный) векторный объект, который может отсутствовать некоторые из контекстной насыщенности кадра данных.

Это может также помочь чесать (если один имеет обыкновение не смотреть на исходный код пакетов) , что dplyrделает много работы под капотом целевых столбцов. Это также несправедливо тест , так как мы вернемся разные вещи, но все вуп «дайте мне эту колонку» опа, так что читать его с этим контекстом:

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

Но, что если у нас есть много столбцов:

# 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. Хорошая привычка (ИМО) , чтобы попасть в устанавливает options(warnPartialMatchDollar = TRUE)во всех ваших проектах , где вы сознательно не рассчитывают на такое поведение.

Ответил 20/10/2018 в 12:01
источник пользователем

голоса
1

Это не то же самое. Если вы ищете ту же функциональность, вы могли бы рассмотреть возможность тянуть () из того же пакета dplyr. Символ доллара возвращает вектор «сборки» из dataframe, тянуть делает то же самое.

Ответил 20/10/2018 в 07:36
источник пользователем

голоса
0

selectнаходится в пакете dplyr, часть tidyverse. https://dplyr.tidyverse.org/

Вы могли бы сделать что-то вроде

df %>% 
  select(colName1, colName2)

Что бы выбрать те столбцы из ФРА. Эти заявления написаны как глаголы (например, выбрать, организовать, group_by и т.д.) и делает его гораздо проще работать с данными.

$от базового г. Он покажет вам только этот столбец из ФРА.

Ответил 20/10/2018 в 08:18
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more