2012-01-19 18 views
6

He escrito la siguiente función basada en subset(), que me parece muy útil:subconjunto() de un vector en R

ss <- function (x, subset, ...) 
{ 
    r <- eval(substitute(subset), data.frame(.=x), parent.frame()) 
    if (!is.logical(r)) 
     stop("'subset' must be logical") 
    x[r & !is.na(r)] 
} 

Por lo tanto, puedo escribir:

ss(myDataFrame$MyVariableName, 500 < . & . < 1500) 

en lugar de

myDataFrame$MyVariableName[ 500 < myDataFrame$MyVariableName 
           & myDataFrame$MyVariableName < 1500] 

Esto parece algo para lo que otras personas podrían haber desarrollado soluciones, sin embargo, incluyendo algo en Core RI podría he perdido. ¿Hay algo por ahí?

+0

todavía parece funcionar si cambiamos '' hoja.de.datos a '' lista y sospecho rendimiento mejorará (= x). . –

+0

Buen punto @DWin. –

+0

Para aclarar: acabo de utilizar 'myDataFrame $ MyVariableName' como ejemplo de un nombre de vector muy largo. Probablemente debería haber usado 'myVeryVeryLeryLongVariableName' o algo así, pero si lo edito ahora, la respuesta de @ joran no tendrá mucho sentido. =) –

Respuesta

2

Gracias por compartir Ken.

que puede usar:

x <- myDataFrame$MyVariableName; x[x > 100 & x < 180] 

suyo puede requerir menos mecanografía, pero el código es menos generalizables a otros si va a compartir código. Tengo algunas funciones de ahorro de tiempo como yo, pero utilícelas con moderación porque pueden ralentizar su código (pasos adicionales) y requiere que también incluya ese código para esa función cada vez que comparta el archivo con otra persona.

comparan longitud escritura. Casi la misma longitud:

ss(mtcars$hp, 100 < . & . < 180) 
x <- mtcars$hp; x[x > 100 & x < 180] 

comparar el tiempo en 1000 repeticiones.

library(rbenchmark) 
benchmark(
     tyler = x[x > 100 & x < 180], 
     ken = ss(mtcars$hp, 100 <. & . < 180), 
replications=1000) 

    test replications elapsed relative user.self sys.self user.child sys.child 
2 ken   1000 0.56 18.66667  0.36  0.03   NA  NA 
1 tyler   1000 0.03 1.00000  0.03  0.00   NA  NA 

así que supongo que depende de si necesita velocidad y/o Entonces, compartir vs conveniencia. Si es solo para ti en un pequeño conjunto de datos, diría que es valioso.

EDIT: NUEVO COMPARATIVA

> benchmark(
+  tyler = {x <- mtcars$hp; x[x > 100 & x < 180]}, 
+  ken = ss(mtcars$hp, 100 <. & . < 180), 
+  ken2 = ss2(mtcars$hp, 100 <. & . < 180), 
+  joran = with(mtcars,hp[hp>100 & hp< 180 ]), 
+ replications=10000) 

    test replications elapsed relative user.self sys.self user.child sys.child 
4 joran  10000 0.83 2.677419  0.69  0.00   NA  NA 
2 ken  10000 3.79 12.225806  3.45  0.02   NA  NA 
3 ken2  10000 0.67 2.161290  0.35  0.00   NA  NA 
1 tyler  10000 0.31 1.000000  0.20  0.00   NA  NA 
+0

Sí, pensé en eso también - es esencialmente lo que estoy haciendo dentro de mi función 'ss()', por supuesto, pero mi 'x' se llama' .'. –

+0

En cuanto a la velocidad, tomé la sugerencia de @DWin y vi una mejora de 10x en este punto de referencia. 'punto de referencia ( tyler = {x <- mtcars $ hp; x [x> 100 & x <180]}, ken = ss (mtcars $ hp, 100 <. &. <180), ken2 = ss2 (mtcars $ hp, 100 <. &. <180), + replicaciones = 10000) replicaciones de prueba transcurrido relativo user.self sys.self user.child sys.child 2 ken 10000 2.26 15.06667 2.25 0 NA NA 3 ken2 10000 0.24 1.60000 0.25 0 NA NA 1 tyler 10000 0.15 1.00000 0.15 0 NA NA' –

+0

gah, ¡eso no es nada bonito! –

4

Soy consciente de que la solución Ken ofrece es más general que acaba de seleccionar elementos dentro de los rangos (ya que debería funcionar en cualquier expresión lógica) pero esto me hizo recordar que Greg nieve tiene operadores infijos de comparación en su paquete de Enseñanza Demos: (. = x)

library(TeachingDemos) 
x0 <- rnorm(100) 
x0[ 0 %<% x0 %<% 1.5 ] 
+0

¡Genial! Siempre he querido una construcción 'x

+0

Recuerdo cuando Perl recibió tal cosa: se dieron cuenta de que ya habían cometido un error fatal al decir "Usaste 'x

+0

Tenga en cuenta que 'a James

Cuestiones relacionadas