2011-04-26 24 views
12

Si deseo seleccionar un subconjunto de datos en R, puedo usar la función de subconjunto. Quería basar un análisis en datos que coincidiera con uno de los pocos criterios, p. que una determinada variable fue ya sea 1, 2 o 3. me trataronUso de criterios múltiples en la función de subconjunto y operadores lógicos

myNewDataFrame <- subset(bigfive, subset = (bigfive$bf11==(1||2||3))) 

Siempre tan solo seleccione los valores que coinciden con el primero de los criterios, aquí hizo 1. Mi hipótesis era que iba a comenzar con 1 y si evalúa como "falso" pasaría a 2 y luego a 3, y si ninguno coincide con la declaración después de == es "falsa" y si una de ellas coincide, es "verdadera".

me dieron el resultado correcto usando

newDataFrame <- subset(bigfive, subset = (bigfive$bf11==c(1,2,3))) 

Pero me gustaría ser capaz de seleccionar los datos a través de operadores lógicos, así que: ¿por qué el primer enfoque no funciona?

+0

Eche un vistazo a la página de ayuda de "Logic". la forma '||' opera de izquierda a derecha y solo examina el primer elemento en el vector. '% in%' también sería un operador útil para usar en estas situaciones. una búsqueda SO para '[r]% in%' debería ser esclarecedora. – Chase

+2

@Chase '||' y '|' son inútiles aquí: '1 || 2 || 3' y' 1 | 2 | 3' se evalúan como TRUE, por lo que el subconjunto solo incluiría aquellas donde 'bf11' era TRUE (o algo que evaluó a VERDADERO). '% in%' es más que útil aquí. –

+0

@Gavin - gracias por terminar mi oración allí - tuvo que correr a otra reunión. – Chase

Respuesta

19

El operador correcto es %in% aquí. Aquí hay un ejemplo con datos ficticios:

set.seed(1) 
dat <- data.frame(bf11 = sample(4, 10, replace = TRUE), 
        foo = runif(10)) 

entrega:

> head(dat) 
    bf11  foo 
1 2 0.2059746 
2 2 0.1765568 
3 3 0.6870228 
4 4 0.3841037 
5 1 0.7698414 
6 4 0.4976992 

El subconjunto de dat donde bf11 es igual a cualquiera de los conjuntos 1,2,3 se toma como sigue usando %in%:

> subset(dat, subset = bf11 %in% c(1,2,3)) 
    bf11  foo 
1  2 0.2059746 
2  2 0.1765568 
3  3 0.6870228 
5  1 0.7698414 
8  3 0.9919061 
9  3 0.3800352 
10 1 0.7774452 

En cuanto a por qué su original no funcionó, desglose para ver el problema. Mira lo que 1||2||3 se evalúa como:

> 1 || 2 || 3 
[1] TRUE 

y se obtendría utilizando la misma | lugar. Como resultado, la llamada subset() solo devolvería filas donde bf11 era TRUE (o algo que se evaluó en TRUE).

Lo que podría haber escrito habría sido algo así como:

subset(dat, subset = bf11 == 1 | bf11 == 2 | bf11 == 3) 

que da el mismo resultado que mi anterior subset() llamada. El punto es que necesita una serie de comparaciones individuales, no una comparación de una serie de opciones.Pero como puede ver, %in% es mucho más útil y menos detallado en tales circunstancias. Observe también que tengo que usar | ya que quiero comparar cada elemento de bf11 contra 1, 2 y 3, a su vez. Compare:

> with(dat, bf11 == 1 || bf11 == 2) 
[1] TRUE 
> with(dat, bf11 == 1 | bf11 == 2) 
[1] TRUE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE 
+0

¿Cómo puedo encontrar la página de ayuda sobre "% en%"? Usé?% En% pero no funcionó. – kostia

+2

@kostia Cita al operador: algo así como '?"% En% "' –

4

Para su ejemplo, creo que el siguiente debería funcionar:

myNewDataFrame <- subset(bigfive, subset = bf11 == 1 | bf11 == 2 | bf11 == 3) 

Véanse los ejemplos en ?subset por más. Sólo para demostrar, un subconjunto lógica más complicada sería:

data(airquality) 
dat <- subset(airquality, subset = (Temp > 80 & Month > 5) | Ozone < 40) 

Y como señala Chase, %in% sería más eficiente en su ejemplo:

myNewDataFrame <- subset(bigfive, subset = bf11 %in% c(1, 2, 3)) 

Como Chase también señala, asegúrese entienda la diferencia entre | y ||. Para ver las páginas de ayuda para los operadores, use ?'||', donde se cita al operador.

+0

'? '||'' funciona bien en R, ya que does '?" || "'. El punto es que estos operadores y algunos otros constructos deben ser _citados_. De ahí mi eliminación de las oraciones de su respuesta. –

Cuestiones relacionadas