source

그룹화 기능(적용, 기준, 집계) 및 *적용 제품군

lovecheck 2023. 7. 6. 22:19
반응형

그룹화 기능(적용, 기준, 집계) 및 *적용 제품군

제가 R에서 "맵" 파이를 하고 싶을 때마다, 저는 보통 R에서 함수를 사용하려고 노력합니다.apply가족.

하지만, 저는 그들 사이의 차이점을 제대로 이해하지 못했습니다. 어떻게 {}sapply,lapplyetc/그룹화된 , 에 대해서도 합니다. 그래서을 얻을 .}은(는) 입력/그룹화된 입력, 출력이 어떻게 보일지, 심지어 입력이 무엇인지에 대해서도 함수를 적용합니다. 그래서 저는 종종 원하는 것을 얻을 때까지 모든 것을 거칩니다.

어떤 것을 언제 사용하는지 누가 설명해 줄 수 있나요?

현재 제가 이해하고 있는 것은...

  1. sapply(vec, f)입이벡다니터입matrix. 은 벡터/벡터로, 서 요소는 출은/이며, 여서요입니다.i이라f(vec[i])합니다.f을 가지고 .

  2. lapply(vec, f)과 같은sapply하지만 출력은 목록입니까?

  3. apply(matrix, 1/2, f)입력이 행렬입니다.출력은 벡터이며, 여기서 요소는i f) is f(행렬의 행/대장균)
  4. tapply(vector, grouping, f)는 출은행배/열이며배, 여서행렬/열의요다값의 입니다.fg, 그의, 고리고.g names "/"에.
  5. by(dataframe, grouping, f)셋방살이g 그룹화를 적용합니다. 적용합니다.f그룹/데이터 프레임의 각 열로 이동합니다.그룹화와 가치를 예쁘게 인쇄합니다.f각 란에
  6. aggregate(matrix, grouping, f)와비한과 한.by그러나 출력물을 예쁘게 인쇄하는 대신 Aggregate는 모든 것을 데이터 프레임에 고정합니다.

측면 질문:저는 아직 플라이어나 모양 바꾸기를 배우지 못했습니다.plyr또는reshape이 모든 것을 완전히 대체할 수 있습니까?

할 수 있는 *apply 이 많이 있습니다( R적많예이있기습니 *다능이설된용도움말명파일에는에예▁which적(있:습).?apply에, 처음 은 어떤 에 적합한지 그것들을 모두 하는 데 을 겪을 수 있습니다 그러나 초기 사용자들은 어떤 것이 자신의 상황에 적합한지를 결정하거나 심지어 모두 기억하는 데 어려움을 겪을 수 있습니다.이들은 "여기에 *적용 기능을 사용해야 한다"는 일반적인 감각을 가지고 있을 수 있지만, 처음에는 모든 기능을 똑바로 유지하는 것이 어려울 수 있습니다.

중 상당 이 매우 있는 *apply 제품군에 있음에도 됨)plyr패키지, 기본 기능은 유용하고 알 가치가 있습니다.

이 답변은 새로운 userR이 특정 문제에 대해 올바른 *적용 기능을 사용할 수 있도록 안내하는 일종의 표지판 역할을 하기 위한 것입니다.참고로, 이것은 단순히 R 문서를 반복하거나 대체하기 위한 것이 아닙니다!희망 사항은 이 답변이 귀하의 상황에 맞는 *적용 기능을 결정하는 데 도움이 될 것이며, 이를 추가로 조사하는 것은 귀하에게 달려 있습니다.한 가지 예외를 제외하고는 성능 차이는 해결되지 않습니다.

  • apply - 함수를 행렬의 또는(및 고차원 아날로그)에 적용하려는 경우, 행렬에 먼저 강제 적용되므로 일반적으로 데이터 프레임에는 권장되지 않습니다.

     # 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밑에

     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.

     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"배열을 합니다: 경 우 개 행 사 여 다 배 구 합 성 니 을 다 열 원 이 차 하 용 별 렬 을 니 합 다 ▁in 구 성 : 이 배 ▁to 을 ▁it ▁a ▁will ▁the

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

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

  • vapply - 사용하고 싶지만 코드에서 속도를 내야 하거나많은 유형 안전을 원할사용합니다.

    위해서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
    
  • 매플리 - 여러 데이터 구조(예: 벡터, 목록)가 있는 경우 데이터 구조의 첫 번째 요소에 함수를 적용한 다음 요소의 번째 요소에 함수를 적용하여 결과를 벡터/어레이에 강제로 적용하려는 경우에 사용합니다.

    이것은 함수가 다중 인수를 수용해야 한다는 의미에서 다변량입니다.

     #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(sum, 1:5, 1:5, 1:5)
     [[1]]
     [1] 3
    
     [[2]]
     [1] 6
    
     [[3]]
     [1] 9
    
     [[4]]
     [1] 12
    
     [[5]]
     [1] 15
    
  • 래플리 - 중첩된 리스트 구조의 각 요소에 함수를 재귀적으로 적용하려는 경우에 사용합니다.

    당신에게 얼마나 흔하지 않은지에 대해 알려주는 것.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")
    
  • 태플리 - 벡터의 부분 집합에 함수적용하고 부분 집합이 다른 벡터(일반적으로 요인)에 의해 정의되는 경우에 사용합니다.

    *적용 가족의 흑양, 일종의.도움말 파일에서 "ragged array"라는 문구를 사용하는 것은 다소 혼란스러울 수 있지만 실제로는 매우 간단합니다.

    벡터:

     x <- 1:20
    

    그룹을 정의하는 요인(같은 길이의 요인!):

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

    다니합의 합니다.x의 정된 각부내로 된 각 y:

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

    부분군이 여러 요인 리스트의 고유한 조합으로 정의되는 경우 더 복잡한 예제를 처리할 수 있습니다. tapplyR에서 공통적으로 사용되는 분할-적용-결합 함수와 정신적으로 유사합니다(aggregate,by,ave,ddply등) 따라서 흑양의 지위.

참고로, 여기 다양한 방법이 있습니다.plyr 기에해저수는함하에 합니다.*applyfunctions (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는 각 함수에 대해 일관된 명명 규칙을 제공하여 함수 이름에 입력 및 출력 데이터 유형을 인코딩합니다.또한 출력의 일관성을 제공합니다.dlply() 쉽게 전달할 수 있습니다.ldply()유용한 산출물 등을 생산하기 위해

배우는 은 습학으로, 개념적입니다.plyr.*apply기능들.

plyr그리고.reshape기능은 제 일상적인 사용에서 거의 모든 기능을 대체했습니다.그러나 Plyr 소개 문서에서도 다음과 같이 설명합니다.

기능 관련함수tapply그리고.sweep에 .plyr유용하게 사용할 수 있습니다. merge요약을 원본 데이터와 결합하는 데 유용합니다.

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

apply, sapply, lapply, by, aggregate

요, 확한것은바대실건라▁(바.apply@ @Hadley's 당합니다해에합니다.aaply그리고.aggregate@ @Hadley's 당합니다해에합니다.ddply기타. 이 이미지에서 얻을 수 없는 경우 동일한 슬라이드 공유의 슬라이드 20이 명확합니다.)

(왼쪽은 입력, 위는 출력)

먼저 조란의 훌륭한 답변으로 시작합니다. 무엇이든 그것보다 더 좋을 수 있을지 의심스럽습니다.

그런 다음 다음 니모닉은 각각의 차이를 기억하는 데 도움이 될 수 있습니다.일부는 분명하지만, 다른 일부는 덜 그럴 수도 있습니다. 이것들은 조란의 토론에서 정당성을 찾을 수 있습니다.

니모닉

  • lapply목록 또는 벡터에 작용하고 목록을 반환하는 목록 적용입니다.
  • sapply단순한 lapply을 반환하는 으로 기본 설정됨 ("함수"는 벡터나 행렬을 반환합니다.
  • vapply검증된 적용입니다(반복 객체 유형을 사전 지정해야 합니다.
  • rapply중첩된 목록, 즉 목록 내 목록에 대한 재귀적 적용입니다.
  • tapply태그가 하위 집합을 식별하는 태그 적용입니다.
  • apply일반: 행렬의 행 또는 열(또는 더 일반적으로 배열의 차원)에 함수를 적용합니다.

올바른 배경 구축

apply가족은 여전히 당신에게 약간 이질적이라고 생각합니다, 그렇다면 당신이 핵심적인 관점을 놓치고 있는 것일 수도 있습니다.

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

리스프 사용자는 즉시 패러다임을 인식할 것입니다.만약 당신이 리스프에 익숙하지 않다면, 일단 당신이 FP에 대해 머리를 쓰면, 당신은 R에서 사용할 수 있는 강력한 관점을 얻게 될 것입니다.apply훨씬 더 말이 될 겁니다

는 이 한) 것을 때문입니다.by그리고.aggregate한 바가 .이것이 제 공헌입니다.

타고

by처럼 함수는 "준한에"의 "wrapper될 수 .tapply의의 힘 by우리가 작업을 계산하고 싶을 때 발생합니다.tapply감당할 수 없습니다.한 가지 예로 다음 코드가 있습니다.

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 

이 두 가지 물건을 인쇄하면,ct그리고.cb우리는 "본질적으로" 같은 결과를 가지고 있고 유일한 차이점은 그것들이 어떻게 보여지는지와 다른지입니다.class 각의속성각by위해서cb그리고.array위해서ct.

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

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

R은 인수의 길이가 같아야 한다고 말합니다. "우리는 계산하고 싶습니다.summary 매다한양에 있는 모든 의.iris라는 .Species하지만 R은 어떻게 처리해야 할지 모르기 때문에 그렇게 할 수 없습니다.

by함수 R은 특정 방법을 디스패치합니다.data frame를 한 the 업하고내둬려버나서수▁the.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     

그것은 실제로 효과가 있고 그 결과는 매우 놀랍습니다.은 클래스의 입니다.by도 마찬가지로Species(를 들어,는 (으)ㄹ 수 있다, ㄹ 수 있다)를 summary각 변수의

첫 번째 인수가 다음과 같은 경우에 주의하십시오.data framedispatched 함수에는 해당 클래스의 개체에 대한 메서드가 있어야 합니다.를 들어, 는 이 를 예를들어다, 같사를이용다니합음과와 함께 사용합니다.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는 또 볼 수 있습니다.tapply우리가 그런 식으로 사용한다면요.

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 (필수가 아님) 목록이 될 수 있으며 의 출력은aggregate는 데이터 프레임인 반면에 다음 중 하나입니다.tapply입니다.array.

의의 힘 aggregate, 데터 하집쉽 처수있다습으로 집합을 할 수 .subset이▁for에 대한 방법을 가지고 입니다.ts와 체객및formula뿐만 아니라.

이 요소들은 다음을 만듭니다.aggregate그것으로 일하는 것이 더 쉽습니다.tapply은 몇 예입니다(다음은 몇 가지 예입니다(설명서 참조).

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그러나 구문이 약간 더 어렵고 출력(경우에 따라) 가독성이 떨어집니다.

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 = TRUEformulaaggregate으로 함는기다같습니다가 있습니다.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 함수한다는 것을 수 . (이 높은 인 우는사다함호것반그달을수없다성니습할는다것환다러리아있니입관함을제이련와수된공그한오마것은도류나를출수이실음그▁(▁we▁call▁returns,▁(but▁that▁in▁it▁an▁can▁just▁following▁error다▁function▁likely▁most▁supplied'▁function▁the니것▁achievet▁the▁fact▁related.mean):

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

결과가 동일하고 차이가 클래스에만 있는 경우(표시/인쇄 방법뿐만 아니라 예제, 하위 집합을 지정하는 방법):

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

이전 코드는 동일한 목표와 결과를 달성하며, 어떤 시점에서 어떤 도구를 사용할지는 개인의 취향과 요구의 문제일 뿐입니다. 이전 두 개체는 부분 집합화 측면에서 매우 다른 요구를 가지고 있습니다.

각 기능별 사용 사례의 차이를 논의하는 훌륭한 답변들이 많이 있습니다.성능의 차이를 논하는 답은 없습니다.다양한 기능이 다양한 입력을 기대하고 다양한 출력을 생성하지만 대부분의 기능은 시리즈/그룹별로 평가해야 하는 일반적인 공통 목표를 가지고 있기 때문에 합리적입니다.제 대답은 성능에 초점을 맞출 것입니다.위의 이유로 벡터로부터의 입력 생성은 타이밍에 포함됩니다. 또한apply함수가 측정되지 않습니다.

는 두 했습니다.sum그리고.length 입니다.테스트된 볼륨은 입력 시 50M, 출력 시 50K입니다. 두 현재 인기 있는 인 질이있을당개시널에는리문사다않니패있 2포습했함도지키는인기현을 했습니다.data.table그리고.dplyr좋은 성과를 목표로 한다면 두 가지 모두 분명히 볼 가치가 있습니다.

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

있는 모든 두 더. 한 기능인 있모개답불구고하도변에여다가있언급, 치가기는기본능있이 2더습니에할기는든훌륭한▁despite▁that개▁the다▁useful▁more▁functions있니▁base▁there,,▁here▁2. 유용합니다.outer한 무명과능기▁function.eapply를 수행

바깥쪽의

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

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

이플리

eapply는 것과 같은lapply목록의 모든 요소에 함수를 적용하는 대신 환경의 모든 요소에 함수를 적용합니다.예를 들어 글로벌 환경에서 사용자 정의 함수 목록을 찾으려는 경우:

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 

솔직히 나는 이것을 잘 사용하지 않지만, 만약 당신이 많은 패키지를 만들거나 많은 환경을 만든다면 그것은 도움이 될 것입니다.

그것은 아마 언급할 가치가 있을 것입니다.ave.ave이라tapply할 수 합니다.데이터 프레임에 직접 연결할 수 있는 형태로 결과를 반환합니다.

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
##   ...

에는 기본패에다같음작것없습다니처럼 작동하는 .ave프레임에 (전체데터프에대한임레이대한▁for에)by는 것과 같은tapply데이터 프레임의 경우).하지만 당신은 그것을 속일 수 있습니다.

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
## ...

나는 최근에 꽤 유용한 것을 발견했습니다.sweep완전성을 위해 기능하고 여기에 추가합니다.

쓸다

기본 아이디어는 배열을 행 단위 또는 열 단위로 스위프하고 수정된 배열을 반환하는 것입니다.예를 들어 다음과 같이 확인할 수 있습니다(출처: 데이터캠프).amp).

행렬이 있고 행렬을 열 단위로 표준화하려고 합니다.

dataPoints <- matrix(4:15, nrow = 4)

# Find means per column with `apply()`
dataPoints_means <- apply(dataPoints, 2, mean)

# Find standard deviation with `apply()`
dataPoints_sdev <- apply(dataPoints, 2, sd)

# Center the points 
dataPoints_Trans1 <- sweep(dataPoints, 2, dataPoints_means,"-")

# Return the result
dataPoints_Trans1
##      [,1] [,2] [,3]
## [1,] -1.5 -1.5 -1.5
## [2,] -0.5 -0.5 -0.5
## [3,]  0.5  0.5  0.5
## [4,]  1.5  1.5  1.5

# Normalize
dataPoints_Trans2 <- sweep(dataPoints_Trans1, 2, dataPoints_sdev, "/")

# Return the result
dataPoints_Trans2
##            [,1]       [,2]       [,3]
## [1,] -1.1618950 -1.1618950 -1.1618950
## [2,] -0.3872983 -0.3872983 -0.3872983
## [3,]  0.3872983  0.3872983  0.3872983
## [4,]  1.1618950  1.1618950  1.1618950

NB이 동일한 결과를 더 수 .
apply(dataPoints, 2, scale)

최근 CRAN에 공개된 축소 패키지에서 저는 대부분의 일반적인 적용 기능을 단 두 가지 기능으로 압축하려고 시도했습니다.

  1. dapplydata.의 행 각인 경우 및 (Data-Apply) (Data-Apply) 데이터.frames는 (데이터 적용) 입니다).drop = TRUE)와 비슷한 성능은 다음과 같습니다.lapply열의 , data.frame보다 약 더 .apply행렬 행 또는 열의 경우.병렬 처리는 다음을 통해 사용할 수 있습니다.mclapply(MAC에만 해당).

구문:

dapply(X, FUN, ..., MARGIN = 2, parallel = FALSE, mc.cores = 1L, 
       return = c("same", "matrix", "data.frame"), drop = TRUE)

예:

# Apply to columns:
dapply(mtcars, log)
dapply(mtcars, sum)
dapply(mtcars, quantile)
# Apply to rows:
dapply(mtcars, sum, MARGIN = 1)
dapply(mtcars, quantile, MARGIN = 1)
# Return as matrix:
dapply(mtcars, quantile, return = "matrix")
dapply(mtcars, quantile, MARGIN = 1, return = "matrix")
# Same for matrices ...
  1. BY는 벡터, 매트릭스 및 data.frame 메서드를 사용하는 분할 적용 결합 컴퓨팅을 위한 S3 일반형입니다.은 보다훨빠다릅니씬다니릅빠▁than보다 훨씬 빠릅니다.tapply,by그리고.aggregate( (보다) plyr 에 대해dplyr더 빠르긴 하지만).

구문:

BY(X, g, FUN, ..., use.g.names = TRUE, sort = TRUE,
   expand.wide = FALSE, parallel = FALSE, mc.cores = 1L,
   return = c("same", "matrix", "data.frame", "list"))

예:

# Vectors:
BY(iris$Sepal.Length, iris$Species, sum)
BY(iris$Sepal.Length, iris$Species, quantile)
BY(iris$Sepal.Length, iris$Species, quantile, expand.wide = TRUE) # This returns a matrix 
# Data.frames
BY(iris[-5], iris$Species, sum)
BY(iris[-5], iris$Species, quantile)
BY(iris[-5], iris$Species, quantile, expand.wide = TRUE) # This returns a wider data.frame
BY(iris[-5], iris$Species, quantile, return = "matrix") # This returns a matrix
# Same for matrices ...

은 그화변목다제수있도다니습할공음에룹에 제공될 .g.

성능에 대해 말씀드리겠습니다.붕괴의 주요 목표는 R에서 고성능 프로그래밍을 육성하고 분할 적용 결합을 넘어서는 것입니다.이를 위해 패키지에는 C++ 기반 고속 일반 기능이 모두 포함되어 있습니다.fmean,fmedian,fmode,fsum,fprod,fsd,fvar,fmin,fmax,ffirst,flast,fNobs,fNdistinct,fscale,fbetween,fwithin,fHDbetween,fHDwithin,flag,fdiff그리고.fgrowth데이터를 통해 그룹화된 계산을 단일 경로로 수행합니다(즉, 분할 및 재결합 없음).

구문:

fFUN(x, g = NULL, [w = NULL,] TRA = NULL, [na.rm = TRUE,] use.g.names = TRUE, drop = TRUE)

예:

v <- iris$Sepal.Length
f <- iris$Species

# Vectors
fmean(v)             # mean
fmean(v, f)          # grouped mean
fsd(v, f)            # grouped standard deviation
fsd(v, f, TRA = "/") # grouped scaling
fscale(v, f)         # grouped standardizing (scaling and centering)
fwithin(v, f)        # grouped demeaning

w <- abs(rnorm(nrow(iris)))
fmean(v, w = w)      # Weighted mean
fmean(v, f, w)       # Weighted grouped mean
fsd(v, f, w)         # Weighted grouped standard-deviation
fsd(v, f, w, "/")    # Weighted grouped scaling
fscale(v, f, w)      # Weighted grouped standardizing
fwithin(v, f, w)     # Weighted grouped demeaning

# Same using data.frames...
fmean(iris[-5], f)                # grouped mean
fscale(iris[-5], f)               # grouped standardizing
fwithin(iris[-5], f)              # grouped demeaning

# Same with matrices ...

패키지 vignetes에서 벤치마크를 제공합니다.고속 기능을 사용한 프로그래밍은 dplyr 또는 data.table사용한 프로그래밍보다 훨씬 빠릅니다. 특히 작은 데이터에서도 그렇지만 큰 데이터에서도 그렇습니다.

0부터, R4.3.부터,tapply과 데터프둘지다니다합원및을 모두 합니다.tapply그리고.by에서는 공식을 사용하여 데이터 프레임 행을 그룹화할 수 있습니다.

> R.version.string
[1] "R version 4.3.0 beta (2023-04-07 r84200)"
> dd <- data.frame(x = 1:10, f = gl(5L, 2L), g = gl(2L, 5L))
    x f g
1   1 1 1
2   2 1 1
3   3 2 1
4   4 2 1
5   5 3 1
6   6 3 2
7   7 4 2
8   8 4 2
9   9 5 2
10 10 5 2
> tapply(dd, ~f + g, nrow)
   g
f   1 2
  1 2 0
  2 2 0
  3 1 1
  4 0 2
  5 0 2
> by(dd, ~g, identity)
g: 1
  x f g
1 1 1 1
2 2 1 1
3 3 2 1
4 4 2 1
5 5 3 1
------------------------------------------------------------ 
g: 2
    x f g
6   6 3 2
7   7 4 2
8   8 4 2
9   9 5 2
10 10 5 2

위에서 설명하지 않은 일부 패키지의 대안도 있습니다.

parApply()에서 합니다.parallels패키지는 클러스터에서 병렬 계산을 실행하기 위한 함수 제품군을 적용할 수 있는 대안을 제공합니다. 다른 으로는 R 서 계 산 위 다 대 포 다 함 합 니 다 을 음 은 안 른 병 에 렬 한 을 ▁other ▁the 니 다 합 포 atives ▁for 함 ▁r ▁r ▁altern ▁include ▁comput ation ▁parallel ▁in 을foreach 및 패지및doParallel패키지 - 루프 및 함수의 병렬 실행을 허용합니다.future패키지는 표현식을 병렬 또는 순차적으로 비동기식으로 평가하는 방법인 미래를 사용하기 위한 간단하고 일관된 API를 제공합니다.추가적으로,purrr 및 접근 하며, 패지는반매복대프접제며공하, 을 통해 를 지원합니다.future꾸러미

여기 몇 가지 예가 있어요.

parApply() 예:

library(parallel)

# Create a matrix
m <- matrix(1:20, nrow = 5)

# Define a function to apply to each column of the matrix
my_fun <- function(x) {
  x^2
}

# Apply the function to each column of the matrix in parallel
result <- parApply(cl = makeCluster(2), X = m, MARGIN = 2, FUN = my_fun)

# View the result
result

각 예:

library(foreach)
library(doParallel)

# Register a parallel backend
registerDoParallel(cores = 2)

# Create a list of numbers
my_list <- list(1, 2, 3, 4, 5)

# Define a function to apply to each element of the list
my_fun <- function(x) {
  x^2
}

# Apply the function to each element of the list in parallel
result <- foreach(i = my_list) %dopar% my_fun(i)

# View the result
result

미래의 예:

library(future)

# Plan to use a parallel backend
plan(multiprocess)

# Create a list of numbers
my_list <- list(1, 2, 3, 4, 5)

# Define a function to apply to each element of the list
my_fun <- function(x) {
  x^2
}

# Apply the function to each element of the list in parallel using futures
result <- future_map(my_list, my_fun)

# View the result
result

purr 예:

library(purrr)
library(future)

# Plan to use a parallel backend
plan(multiprocess)

# Create a list of numbers
my_list <- list(1, 2, 3, 4, 5)

# Define a function to apply to each element of the list
my_fun <- function(x) {
  x^2
}

# Apply the function to each element of the list in parallel using purrr
result <- future_map(my_list, my_fun)

# View the result
result

언급URL : https://stackoverflow.com/questions/3505701/grouping-functions-tapply-by-aggregate-and-the-apply-family

반응형