2010-02-03 28 views

Respuesta

122

Existen algunos problemas cuando el vector lógico contiene NA valores.
Véase, por ejemplo:

z <- c(TRUE, FALSE, NA) 
sum(z) # gives you NA 
table(z)["TRUE"] # gives you 1 
length(z[z==TRUE]) # f3lix answer, gives you 2 (because NA indexing returns values) 

Así que creo que es seguro

sum(z, na.rm=TRUE) # best way to count TRUE values 

(que da 1). Creo que la solución table es menos eficiente (mira el código de la función table).

Además, debe tener cuidado con la solución de "tabla", en caso de que no haya valores VERDADEROS en el vector lógico. Supongamos z <- c(NA, FALSE, NA) o simplemente z <- c(FALSE, FALSE)

table(z)["TRUE"] # gives you NA for both cases. 
10

Otra forma es

> length(z[z==TRUE]) 
[1] 498 

Mientras sum(z) es agradable y corto, para mí es más length(z[z==TRUE]) autoexplicativas. Sin embargo, creo que con una tarea sencilla como esta, realmente no hace la diferencia ...

Si es un vector grande, probablemente deberías ir con la solución más rápida, que es sum(z). length(z[z==TRUE]) es aproximadamente 10 veces más lento y table(z)[TRUE] es aproximadamente 200 veces más lento que sum(z).

En resumen, sum(z) es el más rápido de escribir y ejecutar.

71

Otra opción que no se ha mencionado es el uso de which:

length(which(z)) 

sólo para proporcionar realidad algún contexto en el "que es la pregunta más rápido", siempre es más fácil solo para ponerte a prueba. Hice el vector mucho más grande para la comparación:

z <- sample(c(TRUE,FALSE),1000000,rep=TRUE) 
system.time(sum(z)) 
    user system elapsed 
    0.03 0.00 0.03 
system.time(length(z[z==TRUE])) 
    user system elapsed 
    0.75 0.07 0.83 
system.time(length(which(z))) 
    user system elapsed 
    1.34 0.28 1.64 
system.time(table(z)["TRUE"]) 
    user system elapsed 
    10.62 0.52 11.19 

utilizando Así que claramente sum es el mejor enfoque en este caso. También es posible que desee comprobar los valores NA como sugirió Marek.

sólo para añadir una nota sobre los valores de NA y la función which:

> which(c(T, F, NA, NULL, T, F)) 
[1] 1 4 
> which(!c(T, F, NA, NULL, T, F)) 
[1] 2 5 

Tenga en cuenta que los que sólo comprueba lógica TRUE, por lo que esencialmente ignora los valores no-lógicos.

+0

Por cierto, había un buen truco con el tiempo en respuesta a Dirk: http://stackoverflow.com/questions/1748590/revolution-for-r/1748932#1748932 – Marek

6

which es una buena alternativa, especialmente cuando opera en matrices (marque ?which y observe el argumento arr.ind). Pero sugiero que se quede con sum, debido al argumento na.rm que puede manejar NA en un vector lógico. Por ejemplo:

# create dummy variable 
set.seed(100) 
x <- round(runif(100, 0, 1)) 
x <- x == 1 
# create NA's 
x[seq(1, length(x), 7)] <- NA 

Si escribe en sum(x)NA obtendrá como resultado, pero si pasa na.rm = TRUEsum en función, obtendrá el resultado que desea.

> sum(x) 
[1] NA 
> sum(x, na.rm=TRUE) 
[1] 43 

¿Su pregunta es estrictamente teórica, o tiene algún problema práctico con respecto a los vectores lógicos?

+0

yo estaba tratando de grado un concurso. Hacer algo como sum (youranswer == rightanswer) dentro de una aplicación. –

+0

Mi respuesta es demasiado larga, así que publiqué una nueva respuesta, ya que difiere de la anterior. – aL3xa

0

He estado haciendo algo similar hace unas semanas. Aquí hay una posible solución, está escrita desde cero, por lo que es una especie de versión beta o algo así. Trataré de mejorarlo eliminando bucles del código ...

La idea principal es escribir una función que tomará 2 (o 3) argumentos. El primero es un data.frame que contiene los datos recopilados del cuestionario, y el segundo es un vector numérico con respuestas correctas (esto solo se aplica al cuestionario de opción única). Alternativamente, puede agregar un tercer argumento que devolverá el vector numérico con puntaje final o data.frame con puntaje incrustado.

fscore <- function(x, sol, output = 'numeric') { 
    if (ncol(x) != length(sol)) { 
     stop('Number of items differs from length of correct answers!') 
    } else { 
     inc <- matrix(ncol=ncol(x), nrow=nrow(x)) 
     for (i in 1:ncol(x)) { 
      inc[,i] <- x[,i] == sol[i] 
     } 
     if (output == 'numeric') { 
      res <- rowSums(inc) 
     } else if (output == 'data.frame') { 
      res <- data.frame(x, result = rowSums(inc)) 
     } else { 
      stop('Type not supported!') 
     } 
    } 
    return(res) 
} 

Trataré de hacer esto de una manera más elegante con alguna función * ply. Tenga en cuenta que no puse na.rm argumento ... lo hará

# create dummy data frame - values from 1 to 5 
set.seed(100) 
d <- as.data.frame(matrix(round(runif(200,1,5)), 10)) 
# create solution vector 
sol <- round(runif(20, 1, 5)) 

Ahora aplicar una función:

> fscore(d, sol) 
[1] 6 4 2 4 4 3 3 6 2 6 

Si pasa hoja.de.datos argumento, se volverá hoja.de.datos modificado. Voy a tratar de arreglar este ... ¡Espero que ayude!

+6

Línea única: 'rowSums (t (t (d) == sol), na.rm = TRUE)'. R reciclar el vector para la comparación. Si su 'd' fuera matriz con casos en columnas, entonces se simplifica a' rowSums (d == sol, na.rm = TRUE) '. – Marek

0

acabo de tener un problema particular donde tenía que contar el número de verdaderas declaraciones de un vector lógico y esto funcionó mejor para mí ...

length(grep(TRUE, (gene.rep.matrix[i,1:6] > 1))) > 5 

Así que esto toma un subconjunto del gen objeto .rep.matrix, y aplica una prueba lógica, devolviendo un vector lógico. Este vector se pone como argumento para grep, que devuelve las ubicaciones de cualquier entrada TRUE. Longitud luego calcula cuántas entradas encuentra grep, dando así el número de entradas VERDADERAS.

4

Otra opción es usar la función de resumen. Da un resumen de los Ts, Fs y NA.

> summary(hival) 
    Mode FALSE TRUE NA's 
logical 4367  53 2076 
> 
+1

Además, para obtener solo los resultados "VERDADEROS" (que se mostrarán como una cadena, pero también incluye "VERDADERO" en la salida): 'summary (hival) [" TRUE "]'; – michael

Cuestiones relacionadas