Diferença entre 'selecionar' e '$' no R

votos
-1

Eu quero entender a diferença de velocidade entre selecte $para o subconjunto colunas em R (embora apreciando que eles não retornam exatamente as mesmas coisas, ao invés tanto realizar o conceitual get-me-a-columnoperação). Eu gostaria de entender quando qualquer um é mais adequado.

Especificamente, em que condições seria a seguinte selectdeclaração ser mais rápido do que a correspondente $declaração?

A sintaxe é:

select(df, colName1, colName2, ...)
df$colName
Publicado 20/10/2018 em 05:42
fonte usuário
Em outras línguas...                            


3 respostas

votos
2

Em resumo, você deve usar dplyrquando a velocidade de desenvolvimento, facilidade de compreensão ou facilidade de manutenção é mais importante.

  • Padrões de referência a seguir mostram que a operação demora mais tempo com dplyra base de equivalentes de P.
  • dplyr devolve um objecto diferente (mais complexo).
  • R Base de dados $e operações semelhantes podem ser mais rápido de executar, mas possuem riscos adicionais (por exemplo, o comportamento de correspondência parcial); pode ser mais difícil de ler e / manter; devolver um (mínima) vector de objecto, que pode estar em falta alguma da riqueza contextual de um quadro de dados.

Isso também pode ajudar a destrinchar (se está acostumado a evitar olhar para o código-fonte dos pacotes) que dplyrestá fazendo um monte de trabalho sob o capô para atingir colunas. É também um teste injusto, uma vez que fazer as coisas de volta diferentes, mas todos os ops são "me dar esta coluna" ops, então lê-lo com esse contexto:

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

Mas, o que se temos um monte de colunas:

# 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

Para uma tonelada de projetos, dplyré uma ótima escolha. Velocidade de execução, no entanto, muitas vezes não é um atributo do "tidyverse", mas a velocidade de desenvolvimento e expressividade geralmente superam a diferença de velocidade.

NOTA: dplyrverbos são prováveis candidatos melhores do que subset()e - enquanto eu preguiçosamente usar $também é um pouco perigoso, devido ao padrão de comportamento de correspondência parcial, como é [[]]sem exact=TRUE. Um bom hábito (IMO) para entrar é a criação options(warnPartialMatchDollar = TRUE)em todos os seus projetos em que você não está conscientemente contando com esse comportamento.

Respondeu 20/10/2018 em 12:01
fonte usuário

votos
1

Não é o mesmo. Se você está procurando a mesma funcionalidade que você poderia considerar puxar () do mesmo pacote dplyr. Dollarsign retorna um vetor 'construir' da trama de dados, puxe faz o mesmo.

Respondeu 20/10/2018 em 07:36
fonte usuário

votos
0

selectestá no pacote dplyr, parte do tidyverse. https://dplyr.tidyverse.org/

que você pode fazer algo como

df %>% 
  select(colName1, colName2)

Que selecionar as colunas de df. Estas declarações são escritos como verbos (por exemplo, selecionar, organizar, group_by, etc.) e faz com que seja muito mais fácil trabalhar com dados.

$é a partir da base r. Ele iria mostrar só esta coluna de df.

Respondeu 20/10/2018 em 08:18
fonte usuário

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