2012-07-31 21 views
6

En la lectura R para los programadores que vi esta funciónUna función básica R

oddcount <- function(x) { 
    k <- 0 
    for (n in x) { 
    if (n %% 2 == 1) k <- k+1 
    } 
    return(k) 
} 

yo preferiría que escribirlo en un estilo más sencillo (es decir, en Lisp)

(defn odd-count [xs] 
    (count (filter odd? xs))) 

veo la función length es equivalente a contar y puedo escribir impar? entonces, ¿hay funciones incorporadas de mapa/filtro/eliminar tipo?

Respuesta

11

A más R manera de hacer esto sería evitar el bucle for, y el uso de vectorización:

oddcount <- function(x) { 
    sum(x %% 2) 
} 

La comparación entre x y 2 salidas de un vector como x en sí es un vector. Suma que calcula la suma del vector, donde TRUE es igual a 1 y FALSE es igual a cero. De esta forma, la función calcula el número de números impares en el vector.

Esto ya conduce a una sintaxis más simple, aunque para las personas no orientadas a la vectorización, el bucle for tiende a ser más fácil de leer. Yo prefiero mucho la sintaxis vectorizada, ya que es mucho más corta. Preferiría usar un nombre más descriptivo para x, por ejemplo, number_vector.

+1

En este caso, podría ser incluso más corto, realmente no necesita el '== 1' ya que' %% 'solo devolverá 0's y 1's. Use 'suma (x %% 2)'. Esto también puede ser un poco más rápido ya que no está generando lógicas y luego las está convirtiendo a numéricas. Algunos pueden encontrar que la versión más larga es más legible (y si tuvieras que expandir esto para buscar números que sean o no múltiplos de algo más que 2, entonces necesitarías la versión más larga. –

5

Usted debe echar un vistazo a la biblioteca funprog, que incluye map, filter, etc. reduce

+0

Gracias, la longitud (filtro (odd_p, xs)) parece hacer el trabajo, parece que estaba haciendo la pregunta incorrecta basada en la última respuesta sin embargo :) – ChrisR

+0

No hay nada de malo con el uso 'funprog', pero usando el estándar R puede obtener la misma brevedad en el código. –

+0

Ese es un buen punto, @Paul. Intentar forzar un lenguaje que usa un paradigma (vectorizado) en otro paradigma (funcional) a menudo resulta en un código innecesariomente detallado. –

12

En R, cuando se trabaja con vectores, la gente a menudo prefiere trabajar en todo el vector a la vez en lugar de recorrerlo (consulte, por ejemplo, this discussion).

En cierto sentido, R tiene un filtro "incorporado" y funciones de reducción: la forma en que puede seleccionar subconjuntos de un vector. Son muy útiles en R, y hay algunas maneras de hacerlo - Te mostraré un par, pero recogerás más si lees sobre R y miras el código de otras personas en un sitio como este. También consideraría mirar ?which y ?'[', que tiene más ejemplos que aquí.

La primera forma es simplemente seleccionar los elementos que desea.Puede usar esta opción si sabe los índices de los elementos que desee:

x <- letters[1:10] 
> x 
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" 

Si sólo queremos las cinco primeras letras, se puede escribir:

x[1:5] 
x[c(1,2,3,4,5)] # a more explicit version of the above 

También puede seleccionar qué elementos ¿no desee utilizando un signo menos, por ejemplo:

x[-(6:10)] 

Otra forma de seleccionar elementos es mediante el uso de un vector booleano:

x <- 1:5 
selection <- c(FALSE, TRUE, FALSE, TRUE, FALSE) 
x[selection] # only the second and fourth elements will remain 

Esto es importante porque podemos crear un vector tal poniendo un vector en una función de comparación:

selection <- (x > 3) 
> selection 
[1] FALSE FALSE FALSE TRUE TRUE 

x[selection] # select all elements of x greater than 3 
x[x > 3]  # a shorthand version of the above 

Una vez más, podemos seleccionar lo contrario de la comparación que utilizamos (tenga en cuenta que, dado es booleano, utilizamos ! y no -):

x[!(x > 3)] # select all elements less than or equal to 3 

Si usted quiere hacer comparaciones vector, se debe considerar la función %in%. Por ejemplo:

x <- letters[1:10] 
> x %in% c("d", "p", "e", "f", "y") 
[1] FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE 

# Select all elements of x that are also "d", "p", "e", "f", or "y" 
x[x %in% c("d", "p", "e", "f", "y")] 
# And to select everything not in that vector: 
x[!(x %in% c("d", "p", "e", "f", "y"))] 

Los anteriores son solo algunos ejemplos; Definitivamente recomendaría la documentación. Sé que este es un largo post después de que ya hayas aceptado una respuesta, pero este tipo de cosas es muy importante y comprenderás que te ahorrará mucho tiempo y dolor en el futuro si eres nuevo en R, así que pensé Compartiría un par de maneras de hacerlo con usted.

+0

Gracias, esto definitivamente es útil. – ChrisR

Cuestiones relacionadas