985 votos

R las funciones de Agrupación: sapply vs. lapply vs. aplicar. vs tapply frente por frente de agregado

Cada vez que quiero hacer algo "mapa"py en R, generalmente trato de usar una función en la apply familia. (Lado de la pregunta: todavía no he aprendido plyr o reshape - plyr o reshape reemplazar a todos estos en su totalidad?)

Sin embargo, nunca he entendido las diferencias entre ellos [{sapply, lapply, etc.} aplicar la función para la entrada/agrupan de entrada, por lo que el resultado se parezca, o incluso lo que la entrada puede ser], así que a menudo se acaba de ir a través de todos ellos, hasta que yo consiga lo que quiero.

Puede alguien explicar cómo uso que uno cuando?

[Mi actual (probablemente incorrecta/incompleta) la comprensión es...

  1. sapply(vec, f): de entrada es un vector. la salida es un vector/matriz, donde el elemento i es f(vec[i]) [dándole una matriz si f tiene un multi-elemento de salida]
  2. lapply(vec, f): igual que sapply, pero la salida es una lista?
  3. apply(matrix, 1/2, f): de entrada es una matriz. la salida es un vector, donde el elemento i es f(fila/col i de la matriz)
  4. tapply(vector, grouping, f): de salida es una matriz/array, donde un elemento en la matriz/array es el valor de f en una agrupación g del vector, y g se inserta en la fila/col nombres
  5. by(dataframe, grouping, f): deje g ser una agrupación. se aplican f a cada columna de la grupo/dataframe. bastante de impresión de la agrupación y el valor de f en cada columna.
  6. aggregate(matrix, grouping, f): similar a by, pero en lugar de bastante impresión de la salida, agregar los palitos de todo en un dataframe.]

1271voto

joran Puntos 68079

R tiene muchos *aplicar funciones que son hábilmente descrito en los archivos de ayuda (por ej. ?apply). Hay bastantes de ellos, sin embargo, que los usuarios principiantes pueden tener dificultad para decidir cual es el adecuado para su situación o incluso recordar a todos ellos. Se puede tener una sensación general de que "yo debería ser el uso de un *aplique la función aquí", pero puede ser difícil de mantener en todos ellos recta en primer lugar.

A pesar de el hecho de que (se observó en otras respuestas) que gran parte de la funcionalidad de la *aplicar familia está cubierto por la extremadamente popular plyr paquete, las funciones base siguen siendo útiles y vale la pena conocer.

Esta respuesta es la intención de actuar como una especie de señal para que los nuevos usuarios de ayuda directa a la correcta *aplique la función de su problema en particular. Nota, esto es , no pretende simplemente regurgitar o reemplazar el R de la documentación! La esperanza es que esta respuesta le ayuda a decidir que *aplique la función se adapte a su situación y, a continuación, es a usted para estudiarlo más a fondo. Con una excepción, las diferencias de rendimiento no será abordado.

  • aplicar - Cuando se quiere aplicar una función a las filas o columnas de una matriz (y de mayores dimensiones análogos).

    # Two dimensional matrix
    M <- matrix(seq(1,16), 4, 4)
    
    # apply min to rows
    apply(M, 1, min)
    [1] 1 2 3 4
    
    # apply max to columns
    apply(M, 2, max)
    [1]  4  8 12 16
    
    # 3 dimensional array
    M <- array( seq(32), dim = c(4,4,2))
    
    # Apply sum across each M[*, , ] - i.e Sum across 2nd and 3rd dimension
    apply(M, 1, sum)
    # Result is one-dimensional
    [1] 120 128 136 144
    
    # Apply sum across each M[*, *, ] - i.e Sum across 3rd dimension
    apply(M, c(1,2), sum)
    # Result is two-dimensional
         [,1] [,2] [,3] [,4]
    [1,]   18   26   34   42
    [2,]   20   28   36   44
    [3,]   22   30   38   46
    [4,]   24   32   40   48
    

    Si desea fila/columna de los medios o de las cantidades de matriz 2D, asegúrese de investigar el altamente optimizado, rápido como un rayo colMeans, rowMeans, colSums, rowSums.

  • lapply - Cuando se quiere aplicar una función a cada elemento de un lista de turno, y obtener una lista de nuevo.

    Este es el caballo de batalla de muchos de los otros *aplicar las funciones. Pelar de nuevo su código y usted encontrará a menudo lapply por debajo.

       x <- list(a = 1, b = 1:3, c = 10:100) 
       lapply(x, FUN = length) 
       $a 
       [1] 1
       $b 
       [1] 3
       $c 
       [1] 91
    
       lapply(x, FUN = sum) 
       $a 
       [1] 1
       $b 
       [1] 6
       $c 
       [1] 5005
    
  • sapply - Cuando se quiere aplicar una función a cada elemento de un lista de turno, pero desea un vector de la espalda, en lugar de una lista.

    Si usted se encuentra escribiendo unlist(lapply(...)), detenerse y considerar sapply.

       x <- list(a = 1, b = 1:3, c = 10:100)
       #Compare with above; a named vector, not a list 
       sapply(x, FUN = length)  
       a  b  c   
       1  3 91
    
       sapply(x, FUN = sum)   
       a    b    c    
       1    6 5005 
    

    En usos más avanzados de sapply va a intentar coaccionar a los resultado de una matriz multidimensional, si es apropiado. Por ejemplo, si nuestra función devuelve un vector de la misma longitud, sapply va a utilizar como columnas de una matriz:

       sapply(1:5,function(x) rnorm(3,x))
    

    Si nuestra función devuelve un 2 dimensiones de la matriz, sapply se hace esencialmente lo mismo, el tratamiento de cada uno regresó de la matriz como un vector:

       sapply(1:5,function(x) matrix(x,2,2))
    

    A menos que se especifique simplify = "array", en cuyo caso se hará uso de las matrices individuales para construir una matriz multidimensional:

       sapply(1:5,function(x) matrix(x,2,2), simplify = "array")
    

    Cada una de estas conductas es, por supuesto, depende de que nuestra función de devolución de vectores o matrices de la misma longitud o dimensión.

  • vapply - Cuando se desea utilizar sapply pero quizás necesitan exprimir un poco más la velocidad de su código.

    Para vapply, que, básicamente, dar R un ejemplo de qué tipo de cosa su función devolverá, lo que puede ahorrar algo de tiempo coaccionar devuelto los valores para caber en un único atómica vector.

    x <- list(a = 1, b = 1:3, c = 10:100)
    #Note that since the advantage here is mainly speed, this
    # example is only for illustration. We're telling R that
    # everything returned by length() should be an integer of 
    # length 1. 
    vapply(x, FUN = length, FUN.VALUE = 0L) 
    a  b  c  
    1  3 91
    
  • mapply - Para cuando se tiene varias estructuras de datos (por ej. vectores, listas) y usted desea aplicar una función a la 1ª elementos de cada uno, y luego el 2º elementos de cada uno, etc., coaccionar el resultado para un vector/matriz como en sapply.

    Este es multivariantes en el sentido de que su función debe aceptar varios argumentos.

    #Sums the 1st elements, the 2nd elements, etc. 
    mapply(sum, 1:5, 1:5, 1:5) 
    [1]  3  6  9 12 15
    #To do rep(1,4), rep(2,3), etc.
    mapply(rep, 1:4, 4:1)   
    [[1]]
    [1] 1 1 1 1
    
    [[2]]
    [1] 2 2 2
    
    [[3]]
    [1] 3 3
    
    [[4]]
    [1] 4
    
  • rapply - Para cuando se desea aplicar una función a cada elemento de una lista anidada de la estructura, de forma recursiva.

    Para dar una idea de cómo infrecuente rapply es, se me olvidó cuando la primera publicación esta respuesta! Obviamente, estoy seguro de que mucha gente lo usa, pero YMMV. rapply se ilustra mejor con una función definida por el usuario para solicitar:

    #Append ! to string, otherwise increment
    myFun <- function(x){
        if (is.character(x)){
        return(paste(x,"!",sep=""))
        }
        else{
        return(x + 1)
        }
    }
    
    #A nested list structure
    l <- list(a = list(a1 = "Boo", b1 = 2, c1 = "Eeek"), 
              b = 3, c = "Yikes", 
              d = list(a2 = 1, b2 = list(a3 = "Hey", b3 = 5)))
    
    
    #Result is named vector, coerced to character           
    rapply(l,myFun)
    
    #Result is a nested list like l, with values altered
    rapply(l, myFun, how = "replace")
    
  • tapply - Para cuando se desea aplicar una función a de subconjuntos de un vector y los subconjuntos definidos por algún otro vector, generalmente de una factor.

    La oveja negra de la *aplicar familia, de todo tipo. El archivo de ayuda del uso de la frase "ragged " matriz" puede ser un poco confuso, pero en realidad es bastante simple.

    Un vector:

       x <- 1:20
    

    Un factor de la misma longitud!) definición de grupos:

       y <- factor(rep(letters[1:5], each = 4))
    

    Agregar los valores en x dentro de cada uno de los subgrupos definidos por y:

       tapply(x, y, sum)  
        a  b  c  d  e  
       10 26 42 58 74 
    

    Ejemplos más complejos puede ser manejado en donde los subgrupos se definen por las combinaciones únicas de una lista de varios factores. tapplyes similares en espíritu a la split-aplicar-se combinan las funciones que se común en R (aggregate, by, ave, ddply, etc.) De ahí su la oveja negra de estado.

181voto

JoFrhwld Puntos 4142

En la nota de lado, aquí es cómo los diversos plyr funciones corresponden a la base *apply funciones (de la introducción a plyr documento de la plyr página web http://had.co.nz/plyr/)

Base function   Input   Output   plyr function 
---------------------------------------
aggregate        d       d       ddply + colwise 
apply            a       a/l     aaply / alply 
by               d       l       dlply 
lapply           l       l       llply  
mapply           a       a/l     maply / mlply 
replicate        r       a/l     raply / rlply 
sapply           l       a       laply 

Uno de los objetivos de plyr es proporcionar coherente de las convenciones de nomenclatura para cada una de las funciones, la codificación de los datos de entrada y salida de los tipos en el nombre de la función. También proporciona consistencia en la producción, en que la salida de dlply() es fácilmente transitable a ldply() para producir un resultado útil, etc.

Conceptualmente, el aprendizaje plyr no es más difícil que la comprensión de la base *apply funciones.

plyr y reshape funciones han reemplazado casi todas estas funciones en mi uso diario. Pero, además de la Introducción a Plyr documento:

Funciones relacionadas con tapply y sweep no tienen ninguna función correspondiente en plyr, y siguen siendo útiles. merge es útil para combinar los resúmenes con los datos originales.

129voto

isomorphismes Puntos 1902

A partir de diapositiva 21 de http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy:

apply, sapply, lapply, by, aggregate

(Esperemos que sea claro, que apply corresponde a @Hadley del aaply y aggregate corresponde a @Hadley del ddply etc. Diapositiva 20 de la misma slideshare aclarar si no la de esta imagen.)

(a la izquierda de la entrada, en la parte superior es de salida)

96voto

Assad Ebrahim Puntos 1295

En primer lugar empezar con Joran excelente respuesta -- dudoso nada mejor que.

A continuación, los siguientes teclas de acceso puede ayudar a recordar las diferencias entre cada uno. Mientras que algunos son obvios, otros pueden ser menos así que --- para estos vas a encontrar justificación en Joran debates.

Teclas de acceso

  • lapply es un aplique que devuelve una lista (actúa sobre cualquier vector o lista y devuelve una lista)
  • sapply es un simple lapply (la función por defecto devuelve un vector o matriz, cuando sea posible)
  • vapply es a veces más rápido que sapply (permite que el objeto de retorno tipo de preespecificado)
  • rapply es un recursiva aplicar (para listas anidadas, es decir. listas dentro de listas)
  • tapply es un etiquetado de aplicar (las etiquetas identificar los subconjuntos)
  • apply es genérico: (se aplica una función a una matriz de filas o de columnas)

Edificio del Fondo a la Derecha

Si el uso de la apply familia todavía se siente un poco ajenos a usted, entonces podría ser que falta un punto clave de la vista.

Estos dos artículos que puede ayudar. Ellos proporcionan la formación necesaria para motivar a la programación funcional de las técnicas que están siendo proporcionados por el apply familia de funciones.

Los usuarios de Lisp reconocerá el paradigma de inmediato. Si usted no está familiarizado con Lisp, una vez que llegue a su cabeza alrededor de FP, deberás de tener un potente punto de vista para su uso en R -- y apply va a tener mucho más sentido.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X