¿Por qué es `[` mejor que `subconjunto`?


Cuando necesito filtrar un dato.frame, es decir, extraer filas que cumplen ciertas condiciones, prefiero usar la función subset:

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

En lugar de la función [:

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

Hay dos razones principales para mi preferencia:{[12]]}

  1. Creo que el código se lee mejor, de izquierda a derecha. Incluso las personas que no saben nada sobre R podrían decir lo que la declaración subset anterior está haciendo.

  2. Porque las columnas pueden ser referidas como variables en el select expresión, puedo guardar algunas pulsaciones. En mi ejemplo anterior, solo tenía que escribir airquality una vez con subset, pero tres veces con [.

Así que estaba viviendo feliz, usando subset en todas partes porque es más corto y lee mejor, incluso abogando por su belleza a mis compañeros codificadores R. Pero ayer mi mundo se rompió. Al leer la documentación subset, noto esta sección:

Advertencia

Esta es una función de conveniencia diseñada para su uso interactivo. Para la programación es mejor usar las funciones de subconjunto estándar como [, y en particular la evaluación no estándar del subconjunto de argumentos puede tener consecuencias imprevistas.

¿Podría alguien ayudar a aclarar lo que los autores quieren decir?

Primero, ¿qué quieren decir con " para usar interactivamente"? Sé lo que es una sesión interactiva, a diferencia de un script ejecutado en modo BATCH, pero no veo qué diferencia debería hacer.

Entonces, podría por favor explique " la evaluación no estándar del subconjunto de argumentos" y por qué es peligroso, tal vez proporcione un ejemplo?

Author: Bhargav Rao, 2012-03-25

2 answers

Esta pregunta fue respondida bien en los comentarios de @James, señalando una excelente explicación de Hadley Wickham de los peligros de subset (y funciones similares) [aquí] . ¡Ve a leerlo!

Es una lectura algo larga, por lo que puede ser útil registrar aquí el ejemplo que Hadley usa que aborda más directamente la pregunta de "¿qué puede salir mal?":

Hadley sugiere el siguiente ejemplo: supongamos que queremos subconjuntos y luego reordenar un marco de datos usando lo siguiente funciones:

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

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

subscramble(mtcars, cyl == 4)

Esto devuelve el error:

Error en eval (expr, envir, enclos) : object 'cyl' not found

Porque R ya no "sabe" dónde encontrar el objeto llamado 'cyl'. También señala las cosas verdaderamente extrañas que pueden suceder si por casualidad hay un objeto llamado ' cyl ' en el entorno global:

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

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

(Ejecutarlos y ver por ti mismo, es bastante loco.)

 215
Author: joran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-06 02:46:49

También [ es más rápido:

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
 23
Author: bartektartanus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-05 15:48:23