web-dev-qa-db-fra.com

Pourquoi est-il meilleur que sous-ensemble?

Lorsque je dois filtrer un nom data.fr, c’est-à-dire extraire des lignes qui répondent à certaines conditions, je préfère utiliser la fonction subset:

subset(airquality, Month == 8 & Temp > 90)

Plutôt que la fonction [:

airquality[airquality$Month == 8 & airquality$Temp > 90, ]

Il y a deux raisons principales à ma préférence:

  1. Je trouve que le code se lit mieux, de gauche à droite. Même les personnes qui ne connaissent rien à R pourraient dire ce que la déclaration subset ci-dessus fait.

  2. Étant donné que les colonnes peuvent être appelées variables dans l'expression select, je peux enregistrer quelques frappes au clavier. Dans l'exemple ci-dessus, je n'avais qu'à taper airquality une fois avec subset, mais trois fois avec [.

Donc, je vivais heureux, en utilisant subset partout car il est plus court et lit mieux, même en préconisant sa beauté à mes collègues codeurs R. Mais hier, mon monde s'est brisé. En lisant la documentation subset, je remarque cette section:

Attention

C'est une fonction pratique destinée à être utilisée de manière interactive. Pour la programmation, il est préférable d'utiliser les fonctions de sous-ensemble standard telles que [ et en particulier l'évaluation non standard d'un sous-ensemble d'arguments peut avoir des conséquences imprévues.

Quelqu'un pourrait-il aider à clarifier ce que les auteurs veulent dire?

Premièrement, qu’entendent-ils par "pour une utilisation interactive"? Je sais ce qu'est une session interactive, par opposition à un script exécuté en mode BATCH, mais je ne vois pas quelle différence cela devrait faire.

Ensuite, pourriez-vous expliquer "l'évaluation non standard du sous-ensemble d'arguments" et pourquoi c'est dangereux, donnez peut-être un exemple?

389
flodel

@James a bien répondu à cette question, soulignant l'excellente explication de Hadley Wickham sur les dangers de subset (et fonctionne de la même manière) [ici] . Allez le lire!

La lecture étant assez longue, il peut être utile de noter ici l'exemple cité par Hadley qui aborde le plus directement la question de "qu'est-ce qui peut mal tourner?":

Hadley suggère l'exemple suivant: supposons que nous voulions créer un sous-ensemble, puis réorganiser une trame de données à l'aide des fonctions suivantes:

scramble <- function(x) x[sample(nrow(x)), ]

subscramble <- function(x, condition) {
  scramble(subset(x, condition))
}

subscramble(mtcars, cyl == 4)

Cela renvoie l'erreur:

Erreur dans eval (expr, envir, enclos): objet 'cyl' non trouvé

parce que R ne "sait" plus où trouver l'objet appelé "cyl". Il signale également les choses vraiment bizarres qui peuvent se produire si, par hasard, il existe un objet appelé "cyl" dans l'environnement mondial:

cyl <- 4
subscramble(mtcars, cyl == 4)

cyl <- sample(10, 100, rep = T)
subscramble(mtcars, cyl == 4)

(Exécutez-les et voyez par vous-même, c'est assez fou.)

234
joran

Aussi [ est plus rapide:

require(microbenchmark)        
microbenchmark(subset(airquality, Month == 8 & Temp > 90),airquality[airquality$Month == 8 & airquality$Temp > 90,])
    Unit: microseconds
                                                           expr     min       lq   median       uq     max neval
                     subset(airquality, Month == 8 & Temp > 90) 301.994 312.1565 317.3600 349.4170 500.903   100
     airquality[airquality$Month == 8 & airquality$Temp > 90, ] 234.807 239.3125 244.2715 271.7885 340.058   100
28
bartektartanus