그룹화 함수(tapply, by, aggregate)와*apply family




sapply r (8)

그것은 언급할만한 가치가 있습니다. avetapply 의 우호적 인 사촌입니다. 결과를 데이터 프레임에 곧바로 다시 연결할 수있는 형태로 결과를 반환합니다.

dfr <- data.frame(a=1:20, f=rep(LETTERS[1:5], each=4))
means <- tapply(dfr$a, dfr$f, mean)
##  A    B    C    D    E 
## 2.5  6.5 10.5 14.5 18.5 

## great, but putting it back in the data frame is another line:

dfr$m <- means[dfr$f]

dfr$m2 <- ave(dfr$a, dfr$f, FUN=mean) # NB argument name FUN is needed!
dfr
##   a f    m   m2
##   1 A  2.5  2.5
##   2 A  2.5  2.5
##   3 A  2.5  2.5
##   4 A  2.5  2.5
##   5 B  6.5  6.5
##   6 B  6.5  6.5
##   7 B  6.5  6.5
##   ...

기본 패키지에는 전체 데이터 프레임 (예 : 데이터 프레임의 경우처럼)처럼 작동하는 것도 없습니다. 그러나 당신은 그것을 퍼지 수 있습니다 :

dfr$foo <- ave(1:nrow(dfr), dfr$f, FUN=function(x) {
    x <- dfr[x,]
    sum(x$m*x$m2)
})
dfr
##     a f    m   m2    foo
## 1   1 A  2.5  2.5    25
## 2   2 A  2.5  2.5    25
## 3   3 A  2.5  2.5    25
## ...

R에서 "map"py를하고 싶을 때마다, 나는 보통 apply 패밀리에서 함수를 사용하려고합니다.

그러나, 나는 그들 사이의 차이점을 결코 이해하지 못했습니다 - 어떻게 { sapply , lapply , 등} 함수가 입력 / 그룹화 된 입력에 적용되는지, 출력이 어떻게 보이는지, 심지어 입력이 될 수 있는지도 이해합니다. 나는 내가 원하는 것을 얻을 때까지 종종 모든 것을 통과합니다.

어떤 사람이 어떤 것을 사용하는지 설명 할 수 있습니까?

나의 현재의 (아마도 부정확하거나 불완전한) 이해는 ...

  1. sapply(vec, f) : 입력 벡터입니다. 출력은 벡터 / 행렬입니다. 요소 if(vec[i]) 이고, f 가 다중 요소 출력을 갖는 경우 행렬을 제공합니다

  2. lapply(vec, f) : sapply 와 동일하지만 출력이 목록입니까?

  3. apply(matrix, 1/2, f) : 입력은 행렬입니다. 출력은 벡터이며 요소 i 는 f (행렬 / 행렬)
  4. tapply(vector, grouping, f) : 출력은 행렬 / 배열입니다. 행렬 / 배열의 요소는 벡터의 그룹화 g 에서 f 의 값이고, g 는 행 / 열 이름으로 푸시됩니다.
  5. by(dataframe, grouping, f) : g 를 그룹화하자. 그룹 / 데이터 프레임의 각 열에 f 를 적용합니다. 각 열에서 그룹핑과 f 의 값을 출력하십시오.
  6. aggregate(matrix, grouping, f) : by 와 비슷하지만 출력을 출력하는 대신 aggregate는 모든 것을 데이터 프레임에 집어 넣습니다.

옆 질문 : 나는 아직도 plyr 또는 reshape를 배웠다 - plyr 또는 reshape 는 이것 전부를 전부 대체 할 plyr 것입니다?


참고로, 다양한 plyr 함수가 기본 *apply 함수 (plyr 웹 페이지 http://had.co.nz/plyr/ 의 intro에서 plyr 문서까지)에 해당하는 방법은 다음과 같습니다 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 

plyr 의 목표 중 하나는 각 함수에 대해 일관된 명명 규칙을 제공하고 함수 이름에 입력 및 출력 데이터 유형을 인코딩하는 것입니다. 또한 ldply() 출력이 유용한 출력을 생성하기 위해 dlply() 에 쉽게 dlply() 될 수 있다는 점에서 출력의 일관성을 제공합니다.

개념적으로 plyr 학습은 기본 *apply 함수를 이해하는 것보다 어렵지 않습니다.

plyrreshape 함수가 일상적으로 사용하는 거의 모든 함수를 대체했습니다. 그러나 Intro에서 Plyr 문서에도 이르기까지 :

관련 함수 tapplysweeptapply 상응하는 함수를 가지고 있지 않고 유용하다. merge 은 요약을 원본 데이터와 결합하는 데 유용합니다.


먼저 Joran의 탁월한 대답으로 시작하십시오.

다음의 니모닉은 각각의 구별을 기억하는 데 도움이 될 수 있습니다. 일부는 분명한 반면 다른 일부는 덜 적을 수도 있습니다.이 때문에 Joran의 토론에서 정당성을 찾을 수 있습니다.

기억술

  • lapply 는 목록이나 벡터에서 작동하고 목록을 반환하는 목록 적용입니다.
  • sapply간단한 lapply (가능한 경우 벡터 또는 행렬을 반환하는 함수가 기본값 임)
  • vapply검증 된 적용입니다 (반환 객체 유형을 미리 지정할 수 있음).
  • rapply 는 중첩 목록, 즉 목록 내의 목록에 대한 재귀 적 적용입니다.
  • tapply 는 태그가 하위 집합을 식별하는 태그 적용입니다.
  • apply generic : 행렬의 행 또는 열 (또는 일반적으로 배열의 차원)에 함수를 적용합니다.

오른쪽 배경 만들기

apply 패밀리를 사용하는 것이 여전히 약간 외계인이라고 느껴질 경우 핵심 관점이 누락 된 것일 수 있습니다.

이 두 기사가 도움이 될 수 있습니다. 이들은 함수 apply 패밀리가 제공하는 함수 프로그래밍 기법 에 동기를 부여하는 데 필요한 배경을 제공합니다.

Lisp 사용자는 패러다임을 즉시 인식합니다. Lisp에 익숙하지 않다면, FP 주위에서 머리를 맞으면, R에서 사용하기위한 강력한 관점을 얻게 될 것이고, apply 은 훨씬 더 의미가있을 것입니다.


R에는 도움말 파일에 자세히 설명되어있는 많은 * 적용 기능이 있습니다 (예 : ?apply ). 하지만 사용하기 시작한 사람들이 자신의 상황에 적합한 것이 어느 것인지 결정하는 것이 어려울 수도 있고 심지어 모든 것을 기억하는 것조차 어려울 수도 있습니다. 그들은 "나는 여기에 * 적용 함수를 사용해야한다"는 일반적인 감각을 가지고 있을지도 모르지만 처음에는 모든 것을 똑바로 유지하는 것이 힘들 수 있습니다.

* 적용되는 패밀리의 기능 대부분이 매우 대중적인 plyr 패키지에 의해 보호된다는 사실 (다른 답변에서 언급 됨)에도 불구하고 기본 기능은 유용하고 가치있는 것으로 남아 있습니다.

이 답변은 새로운 useR에 대한 일종의 표지 로 작동하여 특정 문제에 대해 올바른 * 적용 기능을 제공하도록 돕기위한 것입니다. 이것은 R 문서를 간단히 거부하거나 대체하기위한 것이 아닙니다 ! 희망은이 대답이 당신의 상황에 맞는 함수를 결정하는 데 도움이되며, 더 자세히 연구하는 것은 당신에게 달려 있습니다. 한 가지 예외를 제외하고는 성능 차이가 해결되지 않습니다.

  • 적용 (apply) - 행렬의 행이나 열 (higher - dimensional analogues)에 함수를 적용하고자 할 때; 일반적으로 데이터 프레임에 적합하지는 않습니다.

    # 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
    

    2D 행렬에 대해 행 / 열 평균 또는 합계를 원할 경우 고도로 최적화되고 번개가 빠른 colMeans , rowMeans , colSums , rowSums 를 조사해야합니다.

  • lapply - 차례대로 목록의 각 요소에 함수를 적용하고 목록을 가져 오려고 할 때.

    이것은 다른 많은 적용 기능의 핵심 요소입니다. 그들의 코드를 떼어 lapply 종종 밑에 lapply 것을 발견 할 것입니다.

    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 - 목록의 각 요소에 차례로 함수를 적용하려고하지만 목록이 아닌 벡터 를 원할 때.

    unlist(lapply(...)) 입력하면, 멈추고 sapply 고려 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 
    

    좀 더 고급화 된 사 sapply 사용에서는 적절한 경우 결과를 다차원 배열로 강제 변환하려고 시도합니다. 예를 들어, 우리 함수가 같은 길이의 벡터를 반환하면, sapply 는 그것들을 행렬의 열로 사용합니다 :

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

    우리 함수가 2 차원 행렬을 반환하면, sapply 는 반환 된 각 행렬을 하나의 긴 벡터로 취급하면서 본질적으로 동일한 작업을 수행합니다.

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

    우리가 simplify = "array" 지정하지 않으면, 개별 매트릭스를 사용하여 다차원 배열을 생성합니다 :

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

    물론 이러한 각각의 동작은 동일한 길이 또는 차원의 벡터 또는 행렬을 반환하는 함수에 따라 달라집니다.

  • vapply - 당신이 sapply 를 사용하고 싶을 때 코드에서 좀 더 빠른 속도를 짜낼 필요가있을 때.

    vapply 경우 기본적으로 R에 함수가 반환 할 어떤 종류의 예제를 제공하여 반환 된 값을 단일 원자 벡터에 맞게 강제 변환하는 시간을 절약 할 수 있습니다.

    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 - 여러 개의 데이터 구조 (예 : 벡터,리스트)가 있고 각각의 첫 번째 요소에 함수를 적용한 다음 각 요소의 두 번째 요소 등에 함수를 적용하여 벡터 / 배열에 결과를 강제 적용하려는 경우 sapply .

    함수가 여러 인수를 받아 들여야한다는 점에서 이것은 다 변수입니다.

    #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
    
  • 맵 (Map) - mapply SIMPLIFY = FALSEmapply 하여 래퍼가 반환하므로 목록을 반환 할 수 있습니다.

    Map(sum, 1:5, 1:5, 1:5)
    [[1]]
    [1] 3
    
    [[2]]
    [1] 6
    
    [[3]]
    [1] 9
    
    [[4]]
    [1] 12
    
    [[5]]
    [1] 15
    
  • rapply - 중첩 된 목록 구조의 각 요소에 함수를 반복적으로 적용하려는 경우.

    rapply 가 얼마나 드문 rapply 대한 아이디어를 rapply 위해이 답변을 처음 게시 할 때 깜빡했습니다! 분명히 많은 사람들이 YMMV를 사용할 것이라고 확신합니다. rapply 는 적용 할 사용자 정의 함수로 가장 잘 설명됩니다.

    # 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 - 벡터의 하위 집합 에 함수를 적용하고 하위 집합 을 다른 벡터로 정의 할 때 사용합니다. 대개 요소입니다.

    *의 검은 양은 가족을 적용합니다. 도움말 파일에서 "불규칙한 배열"이라는 문구를 사용하는 것은 다소 confusing 수 있지만 실제로는 매우 간단합니다.

    벡터 :

    x <- 1:20
    

    그룹을 정의하는 요소 (동일한 길이 임) :

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

    y 정의 된 각 하위 그룹에서 x 의 값을 더합니다.

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

    여러 가지 요소의 목록을 고유하게 조합하여 하위 그룹을 정의하는 경우보다 복잡한 예제를 처리 할 수 ​​있습니다. tapply 는 R에서 공통적 인 split-apply-combine 함수 ( aggregate , by , ave , ddply 등)와 ddply 합니다. 그러므로 검은 양의 상태.


나는이 게시물에 대한 (매우 우수한) 답변이 부족하고 aggregate 설명이 없음을 깨달았 기 때문에. 여기 내 기여입니다.

으로

by 함수는 tapply 위한 "래퍼 (wrapper)"로서 문서에 명시된 바와 같이 사용될 수 있습니다. tapply 가 처리 할 수없는 작업을 계산할 때 by 의 힘이 발생합니다. 한 가지 예가이 코드입니다.

ct <- tapply(iris$Sepal.Width , iris$Species , summary )
cb <- by(iris$Sepal.Width , iris$Species , summary )

 cb
iris$Species: setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.300   3.200   3.400   3.428   3.675   4.400 
-------------------------------------------------------------- 
iris$Species: versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.525   2.800   2.770   3.000   3.400 
-------------------------------------------------------------- 
iris$Species: virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.200   2.800   3.000   2.974   3.175   3.800 


ct
$setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.300   3.200   3.400   3.428   3.675   4.400 

$versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.525   2.800   2.770   3.000   3.400 

$virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.200   2.800   3.000   2.974   3.175   3.800 

이 두 개의 객체 인 ctcb 출력하면 "본질적으로"같은 결과를 가지게되고 유일한 차이점은 cbct by 대해 각각 다른 class 속성과 어떻게 표시되는지에 있습니다.

우리가 말했듯이, 우리가 tapply 사용할 수 없을 때 발생합니다. 다음 코드는 한 가지 예입니다.

 tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary) : 
  arguments must have same length

R은 인수가 같은 길이 여야한다고 말합니다. "우리는 Species 따라 iris 의 모든 변수 summary 을 계산하려고합니다."라고 말하지만, R은 처리 방법을 모르기 때문에 그렇게 할 수 없습니다.

by 함수를 사용하여 R은 data frame 클래스에 대한 특정 메서드를 summary 다음 첫 번째 인수의 길이와 형식이 다른 경우에도 summary 함수가 작동하도록합니다.

bywork <- by(iris, iris$Species, summary )

bywork
iris$Species: setosa
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.300   Min.   :2.300   Min.   :1.000   Min.   :0.100   setosa    :50  
 1st Qu.:4.800   1st Qu.:3.200   1st Qu.:1.400   1st Qu.:0.200   versicolor: 0  
 Median :5.000   Median :3.400   Median :1.500   Median :0.200   virginica : 0  
 Mean   :5.006   Mean   :3.428   Mean   :1.462   Mean   :0.246                  
 3rd Qu.:5.200   3rd Qu.:3.675   3rd Qu.:1.575   3rd Qu.:0.300                  
 Max.   :5.800   Max.   :4.400   Max.   :1.900   Max.   :0.600                  
-------------------------------------------------------------- 
iris$Species: versicolor
  Sepal.Length    Sepal.Width     Petal.Length   Petal.Width          Species  
 Min.   :4.900   Min.   :2.000   Min.   :3.00   Min.   :1.000   setosa    : 0  
 1st Qu.:5.600   1st Qu.:2.525   1st Qu.:4.00   1st Qu.:1.200   versicolor:50  
 Median :5.900   Median :2.800   Median :4.35   Median :1.300   virginica : 0  
 Mean   :5.936   Mean   :2.770   Mean   :4.26   Mean   :1.326                  
 3rd Qu.:6.300   3rd Qu.:3.000   3rd Qu.:4.60   3rd Qu.:1.500                  
 Max.   :7.000   Max.   :3.400   Max.   :5.10   Max.   :1.800                  
-------------------------------------------------------------- 
iris$Species: virginica
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.900   Min.   :2.200   Min.   :4.500   Min.   :1.400   setosa    : 0  
 1st Qu.:6.225   1st Qu.:2.800   1st Qu.:5.100   1st Qu.:1.800   versicolor: 0  
 Median :6.500   Median :3.000   Median :5.550   Median :2.000   virginica :50  
 Mean   :6.588   Mean   :2.974   Mean   :5.552   Mean   :2.026                  
 3rd Qu.:6.900   3rd Qu.:3.175   3rd Qu.:5.875   3rd Qu.:2.300                  
 Max.   :7.900   Max.   :3.800   Max.   :6.900   Max.   :2.500     

실제로 작동하며 그 결과는 매우 놀랍습니다. Species (예 : 각자)이 각 변수의 summary 을 계산한다는 것은 클래스의 객체입니다.

첫 번째 인수가 data frame 이면 디스패치 된 함수에는 해당 클래스의 클래스에 대한 메서드가 있어야합니다. 예를 들어 우리는이 코드를 mean 함수와 함께 사용합니다.이 코드는 아무런 의미가 없습니다.

 by(iris, iris$Species, mean)
iris$Species: setosa
[1] NA
------------------------------------------- 
iris$Species: versicolor
[1] NA
------------------------------------------- 
iris$Species: virginica
[1] NA
Warning messages:
1: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
2: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
3: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA

골재

aggregate 는 우리가 그런 식으로 사용한다면 또 다른 사용 방법으로 볼 수 있습니다.

at <- tapply(iris$Sepal.Length , iris$Species , mean)
ag <- aggregate(iris$Sepal.Length , list(iris$Species), mean)

 at
    setosa versicolor  virginica 
     5.006      5.936      6.588 
 ag
     Group.1     x
1     setosa 5.006
2 versicolor 5.936
3  virginica 6.588

두 가지 직접적인 차이점은 aggregate 의 두 번째 인수는 목록 이어야 하고 tapply 필수 항목 일 수 있고 목록은 tapply 중 하나가 array 인 동안 aggregate 의 출력이 데이터 프레임이라는 것입니다.

aggregate 의 힘은 subset 인수로 데이터의 하위 집합을 쉽게 처리 할 수 ​​있으며 객체와 formula 대한 메서드도 가지고 있다는 것입니다.

이러한 요소를 통해 일부 상황에서는 해당 작업을보다 쉽게 ​​수행 할 수 있습니다. 다음은 몇 가지 예입니다 (문서에서 사용 가능).

ag <- aggregate(len ~ ., data = ToothGrowth, mean)

 ag
  supp dose   len
1   OJ  0.5 13.23
2   VC  0.5  7.98
3   OJ  1.0 22.70
4   VC  1.0 16.77
5   OJ  2.0 26.06
6   VC  2.0 26.14

우리는 tapply 하여 동일한 결과를 tapply 있지만 구문은 약간 더 어려워서 출력 (일부 경우)이 읽기 쉽지 않습니다.

att <- tapply(ToothGrowth$len, list(ToothGrowth$dose, ToothGrowth$supp), mean)

 att
       OJ    VC
0.5 13.23  7.98
1   22.70 16.77
2   26.06 26.14

by 또는 tapply 사용할 수없고 aggregate 를 사용해야하는 다른 경우가 있습니다.

 ag1 <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, mean)

 ag1
  Month    Ozone     Temp
1     5 23.61538 66.73077
2     6 29.44444 78.22222
3     7 59.11538 83.88462
4     8 59.96154 83.96154
5     9 31.44828 76.89655

한 번의 호출로 tapply 로 이전 결과를 얻을 수는 없지만 각 요소의 Month 를 따라 평균을 계산 한 다음 결합해야합니다 (또한 na.rm = TRUE 를 호출해야 함을 유의해야합니다. aggregate 함수의 formula 메소드 기본적으로 na.action = na.omit ) :

ta1 <- tapply(airquality$Ozone, airquality$Month, mean, na.rm = TRUE)
ta2 <- tapply(airquality$Temp, airquality$Month, mean, na.rm = TRUE)

 cbind(ta1, ta2)
       ta1      ta2
5 23.61538 65.54839
6 29.44444 79.10000
7 59.11538 83.90323
8 59.96154 83.96774
9 31.44828 76.90000

반면 by 우리는 실제로 다음 함수 호출이 오류를 반환한다는 사실을 알 수 없습니다 (그러나 이것은 제공된 함수와 관련이있을 가능성이 큽니다).

by(airquality[c("Ozone", "Temp")], airquality$Month, mean, na.rm = TRUE)

다른 시간은 결과가 같고 차이점은 클래스에 있습니다 (그리고 나서 어떻게 보이거나 인쇄 되는가, 예를 들어 어떻게 서브 세트화할 것인가) object :

byagg <- by(airquality[c("Ozone", "Temp")], airquality$Month, summary)
aggagg <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, summary)

이전 코드는 동일한 목표와 결과를 얻었습니다. 어떤 점에서 툴을 사용하는 것은 개인적인 취향과 요구 사항 일뿐입니다. 앞의 두 객체는 ​​하위 집합과 관련하여 매우 다른 요구 사항을 가지고 있습니다.


각 기능의 유스 케이스의 차이점을 설명하는 훌륭한 답변이 많이 있습니다. 어떤 대답도 성능의 차이점을 설명하지 못합니다. 다양한 기능이 다양한 입력을 기대하고 다양한 출력을 생성하지만, 대부분은 시리즈 / 그룹별로 평가할 수있는 일반적인 공통 목표를 가지고 있기 때문에 합리적입니다. 내 대답은 성과에 중점을 둘 것입니다. 위의 이유로 인해 벡터에서 입력 생성이 타이밍에 포함되며 apply 함수도 측정되지 않습니다.

한 번에 두 개의 다른 함수 sumlength 를 테스트했습니다. 볼륨 테스트시 입력시 50M, 출력시 50K입니다. 나는 또한 질문이 올 때 널리 사용되지 않았던 현재 인기있는 두 패키지 인 data.tabledplyr . 좋은 성과를 목표로한다면 두 가지 모두 가치가 있습니다.

library(dplyr)
library(data.table)
set.seed(123)
n = 5e7
k = 5e5
x = runif(n)
grp = sample(k, n, TRUE)

timing = list()

# sapply
timing[["sapply"]] = system.time({
    lt = split(x, grp)
    r.sapply = sapply(lt, function(x) list(sum(x), length(x)), simplify = FALSE)
})

# lapply
timing[["lapply"]] = system.time({
    lt = split(x, grp)
    r.lapply = lapply(lt, function(x) list(sum(x), length(x)))
})

# tapply
timing[["tapply"]] = system.time(
    r.tapply <- tapply(x, list(grp), function(x) list(sum(x), length(x)))
)

# by
timing[["by"]] = system.time(
    r.by <- by(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE)
)

# aggregate
timing[["aggregate"]] = system.time(
    r.aggregate <- aggregate(x, list(grp), function(x) list(sum(x), length(x)), simplify = FALSE)
)

# dplyr
timing[["dplyr"]] = system.time({
    df = data_frame(x, grp)
    r.dplyr = summarise(group_by(df, grp), sum(x), n())
})

# data.table
timing[["data.table"]] = system.time({
    dt = setnames(setDT(list(x, grp)), c("x","grp"))
    r.data.table = dt[, .(sum(x), .N), grp]
})

# all output size match to group count
sapply(list(sapply=r.sapply, lapply=r.lapply, tapply=r.tapply, by=r.by, aggregate=r.aggregate, dplyr=r.dplyr, data.table=r.data.table), 
       function(x) (if(is.data.frame(x)) nrow else length)(x)==k)
#    sapply     lapply     tapply         by  aggregate      dplyr data.table 
#      TRUE       TRUE       TRUE       TRUE       TRUE       TRUE       TRUE 

# print timings
as.data.table(sapply(timing, `[[`, "elapsed"), keep.rownames = TRUE
              )[,.(fun = V1, elapsed = V2)
                ][order(-elapsed)]
#          fun elapsed
#1:  aggregate 109.139
#2:         by  25.738
#3:      dplyr  18.978
#4:     tapply  17.006
#5:     lapply  11.524
#6:     sapply  11.326
#7: data.table   2.686

http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy 슬라이드 21에서 :

(희망 applyapply 이 @ Hadley의 aaply 해당하고 aggregate 가 @ Hadley의 aaply 와 일치한다는 것이 분명합니다. 같은 슬라이드 ddply 슬라이드 20은이 이미지에서 얻지 못하면 명확하게 나타낼 것입니다.)

(왼쪽에 입력, 상단에 출력)


모든 위대한 해답에도 불구하고 언급 할 가치가있는 2 가지 기본 함수, 유용한 outer 함수 및 애매한 함수

밖의

outer 은 더 평범한 것으로 숨겨진 매우 유용한 기능입니다. outer 대한 도움말을 읽으면 그 설명은 다음과 같습니다 :

The outer product of the arrays X and Y is the array A with dimension  
c(dim(X), dim(Y)) where element A[c(arrayindex.x, arrayindex.y)] =   
FUN(X[arrayindex.x], Y[arrayindex.y], ...).

이것은 선형 대수 형태의 것들에만 유용 할 것 같습니다. 그러나 이것은 두 개의 입력 벡터에 함수를 적용하기 위해 mapply 와 매우 비슷하게 사용될 수 있습니다. 차이점은 mapply 가 첫 번째 두 요소와 두 번째 두 요소에 함수를 적용하는 반면 outer 는 첫 번째 벡터와 한 요소의 모든 조합에 함수를 적용한다는 점입니다. 예 :

 A<-c(1,3,5,7,9)
 B<-c(0,3,6,9,12)

mapply(FUN=pmax, A, B)

> mapply(FUN=pmax, A, B)
[1]  1  3  6  9 12

outer(A,B, pmax)

 > outer(A,B, pmax)
      [,1] [,2] [,3] [,4] [,5]
 [1,]    1    3    6    9   12
 [2,]    3    3    6    9   12
 [3,]    5    5    6    9   12
 [4,]    7    7    7    9   12
 [5,]    9    9    9    9   12

저는 값의 벡터와 조건의 벡터를 가지고 어느 값이 어떤 조건을 만족하는지보고 싶을 때 이것을 개인적으로 사용했습니다.

응원하다

eapplyeapplylapply 합니다. 목록의 모든 요소에 함수를 적용하는 대신 환경의 모든 요소에 함수를 적용합니다. 예를 들어, 전역 환경에서 사용자 정의 함수의 목록을 찾으려면 다음을 수행하십시오.

A<-c(1,3,5,7,9)
B<-c(0,3,6,9,12)
C<-list(x=1, y=2)
D<-function(x){x+1}

> eapply(.GlobalEnv, is.function)
$A
[1] FALSE

$B
[1] FALSE

$C
[1] FALSE

$D
[1] TRUE 

솔직히 나는 이것을별로 사용하지 않지만 패키지를 많이 만들거나 많은 환경을 만드는 경우 유용 할 수 있습니다.







r-faq