그룹화 함수 (tapply, by, 집계) 및 * apply 제품군
R에서 "map"을하고 싶을 때마다 보통 apply패밀리 의 함수를 사용하려고합니다 .
그러나 나는 그들 사이의 차이점을 전혀 이해하지 못했습니다. { sapply,, lapplyetc.} 함수를 입력 / 그룹화 된 입력에 적용하는 방법, 출력이 어떻게 보일지, 심지어 입력이 될 수 있는지-그래서 저는 종종 내가 원하는 것을 얻을 때까지 모두 통과하십시오.
누군가 언제 어떤 것을 사용하는지 설명 할 수 있습니까?
나의 현재 (아마도 부정확하거나 불완전한) 이해는 ...
sapply(vec, f): 입력은 벡터입니다. 출력은 벡터 / 행렬입니다. 여기서 elementi는f(vec[i])이며f다중 요소 출력이있는 경우 행렬을 제공합니다.lapply(vec, f):와 동일sapply하지만 출력이 목록입니까?apply(matrix, 1/2, f): 입력이 행렬입니다. 출력은 벡터이며, 요소i는 f (행렬의 행 / 열)tapply(vector, grouping, f): 출력은 행렬 / 배열입니다. 여기서 행렬 / 배열의 요소 는 벡터f그룹g의 값이며g행 / 열 이름으로 푸시됩니다.by(dataframe, grouping, f):g그룹화 하자 .f그룹 / 데이터 프레임의 각 열에 적용 됩니다. 그룹화와f각 열의 값을 인쇄하십시오 .aggregate(matrix, grouping, f):와 유사by하지만 출력을 꽤 인쇄하는 대신 집계는 모든 것을 데이터 프레임에 고정합니다.
사이드 질문 : 난 아직도 배우지 plyr 또는 모양 변경이 - 것 plyr또는 reshape완전히 모든 이들의 대체?
R에는 도움말 파일 (예 :)에 설명되어있는 * apply 함수가 많이 있습니다 ?apply. 그러나 처음 사용하는 사람들은 자신의 상황에 적합한 것을 결정하거나 심지어 모두 기억하는 데 어려움을 겪을 수 있습니다. 그들은 "여기서 * 적용 기능을 사용해야한다"는 일반적인 감각을 가지고 있을지 모르지만 처음에는 모든 것을 똑바로 유지하는 것이 어려울 수 있습니다.
* apply 제품군의 많은 기능이 매우 인기있는 plyr패키지에 포함되어 있다는 사실에도 불구하고 (다른 답변에서 언급) 기본 기능은 유용하고 알 가치가 있습니다.
이 답변은 특정 문제에 대한 올바른 * 적용 기능을 안내하는 데 도움이되는 새로운 사용자를위한 일종의 표지판 역할을하기위한 것 입니다. 이것은 단순히 R 문서를 역류하거나 대체하기위한 것이 아닙니다 ! 희망은이 답변이 귀하의 상황에 맞는 * 적용 기능을 결정하는 데 도움이되고 더 자세히 조사하는 것은 귀하에게 달려 있습니다. 한 가지 예외를 제외하고 성능 차이는 해결되지 않습니다.
적용 - 행렬 (및 고차원 유사체)의 행 또는 열에 함수를 적용하려는 경우 데이터 프레임에는 일반적으로 권장되지 않습니다. 먼저 행렬로 강제 변환됩니다.
# 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 - 당신이 차례로리스트의 각 요소에 함수를 적용하고 목록 다시 싶어합니다.
이것은 다른 많은 * apply 함수의 주력입니다. 그들의 코드를 떼어 내면 종종
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] 5005sapply - 당신이 차례로리스트의 각 요소에 함수를 적용 할,하지만 당신이 원하는 때 벡터 오히려 목록보다는 다시.
타이핑하는 것을 발견했다면
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하면는 기본적으로 동일한 작업을 수행하여 반환 된 각 행렬을 단일 long 벡터로 취급합니다.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 91mapply - 당신은 몇 가지 데이터 구조를 (예를 들어, 벡터, 목록) 당신은 같이 벡터 / 배열에 결과를 강요 등 각각의 제 1 요소 및 각의 두 번째 요소에 함수를 적용 할 때
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] 4Map - with에 대한 래퍼 이므로 목록을 반환 할 수 있습니다.
mapplySIMPLIFY = FALSEMap(sum, 1:5, 1:5, 1:5) [[1]] [1] 3 [[2]] [1] 6 [[3]] [1] 9 [[4]] [1] 12 [[5]] [1] 15rapply - 당신은의 각 요소에 함수를 적용 할 때의 경우 중첩 된 목록 재귀 적 구조.
얼마나 드문 지에 대한 아이디어를 제공하기
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 - 당신이 기능을 적용 할 때의 부분 집합 벡터와 하위 집합이 다른 벡터, 보통 요인에 의해 정의된다.
* apply 가족의 검은 양, 일종의. 도움말 파일에서 "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하위 그룹이 여러 요인 목록의 고유 한 조합에 의해 정의되는 경우 더 복잡한 예를 처리 할 수 있습니다.
tapply스플릿 적용-R에 결합 공통된 기능 (영으로 유사aggregate,by,ave,ddply따라서 그 검은 양 상태 등)를 포함한다.
참고로, 다음은 다양한 plyr기능이 기본 *apply기능에 해당하는 방식입니다 (plyr 웹 페이지 http://had.co.nz/plyr/ 의 소개부터 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기능은 매일 사용하는 거의 모든 기능을 대체했습니다. 그러나 Intro to Plyr 문서에서 :
관련 기능
tapply과sweep에는 해당 기능이없는plyr, 유용한 남아있다.merge요약을 원래 데이터와 결합하는 데 유용합니다.
http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy의 슬라이드 21에서 발췌 :

(잘하면 것이 분명 apply대응 해들리의 @에 aaply및 aggregate대응에의 해들리 @ ddply이 이미지에서 그것을 얻을하지 않는 경우 등 같은 slideshare의 슬라이드 (20)는 명확합니다.)
(왼쪽은 입력, 상단은 출력)
먼저 Joran의 탁월한 답변으로 시작하십시오 .
그러면 다음 니모닉이 각각의 차이점을 기억하는 데 도움이 될 수 있습니다. 일부는 분명하지만 다른 일부는 그다지 덜할 수 있습니다. 이러한 경우 Joran의 토론에서 정당성을 찾을 수 있습니다.
기억술
lapplyA는 리스트 목록 또는 벡터에 작용하고 목록을 반환 적용됩니다.sapplyA는 단순lapply(a 벡터 또는 행렬 수를 반환하는 함수의 기본값)vapplyA는 적용 확인은 (반환 개체 유형이 미리 지정된 할 수 있습니다)rapplyA는 재귀가 중첩 된 목록, 목록 내에서 즉,리스트 신청tapply태그가 하위 집합을 식별 하는 태그 적용입니다.apply인 일반적인 : 행렬의 행 또는 컬럼에 함수를 적용 (또는보다 일반적으로, 어레이의 치수)
올바른 배경 구축
apply가족을 사용하는 것이 여전히 당신에게 약간 낯설다면 핵심 관점을 놓치고있을 수 있습니다.
이 두 기사가 도움이 될 수 있습니다. 그들은 기능apply 군 이 제공 하는 기능적 프로그래밍 기술 에 동기를 부여하는 데 필요한 배경 지식을 제공 합니다.
Lisp 사용자는 즉시 패러다임을 인식 할 것입니다. Lisp에 익숙하지 않은 경우 FP에 대해 머리를 숙이면 R에서 사용할 수있는 강력한 관점을 얻게 apply될 것이며 훨씬 더 이해가 될 것입니다.
- 고급 R : 함수형 프로그래밍 , by Hadley Wickham
- R의 간단한 함수형 프로그래밍 , Michael Barton
이 게시물에 대한 답변 by과 aggregate설명 이 부족하다는 것을 깨달았 기 때문에 . 여기 제 공헌이 있습니다.
으로
by로 문서에 명시된 기능을위한 "래퍼"로,하지만 될 수 있습니다 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클래스에 대한 특정 메서드를 디스패치 한 다음 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 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그런 식으로 사용 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 CAN (필수 생략)리스트하고 출력이 그 aggregate중 하나가 동시에 데이터 프레임 tapply이다 array.
의 힘은 인수 aggregate를 사용하여 데이터의 하위 집합을 쉽게 처리 할 수 있고 객체에 subset대한 메서드도 가지고 있다는 것 입니다.tsformula
이러한 요소를 사용 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 = TRUE갖기 때문에 를 호출해야 합니다 ).formulaaggregatena.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우리는 단지 사실에 다음 함수 호출 오류를 반환합니다 (그러나 대부분이 제공된 기능과 관련이 있음을 달성 할 수없는 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입니다. 또한 질문을 질문 할 때 널리 시간에 사용되지 않은이 개 현재 인기있는 패키지를 포함 한 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
언급 할 가치가있을 것 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에는 전체 데이터 프레임 과 같이 작동하는 것이 없습니다 (데이터 프레임 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
## ...
여기에 모든 훌륭한 답변에도 불구하고 언급해야 할 기본 기능이 두 가지 더 있습니다. 유용한 outer기능과 모호한 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
eapplylapply목록의 모든 요소에 함수를 적용하는 것이 아니라 환경의 모든 요소에 함수를 적용한다는 점을 제외하면 비슷 합니다. 예를 들어 글로벌 환경에서 사용자 정의 함수 목록을 찾으려면 다음을 수행하십시오.
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
솔직히 저는 이것을 많이 사용하지 않지만 많은 패키지를 빌드하거나 많은 환경을 만드는 경우 유용 할 수 있습니다.
나는 최근에 다소 유용한 sweep기능을 발견하고 완전성을 위해 여기에 추가했습니다.
스위프
기본 아이디어는 행 또는 열 방향으로 배열 을 스윕 하고 수정 된 배열을 반환하는 것입니다. 예를 들어이를 명확히 할 수 있습니다 (출처 : datacamp ) :
행렬이 있고 이를 열 단위 로 표준화 하고 싶다고 가정 해 보겠습니다 .
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,"-")
print(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
# 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
주의 :이 간단한 예의 경우 동일한 결과를 다음과 같이 더 쉽게 얻을 수 있습니다.
apply(dataPoints, 2, scale)
'Nice programing' 카테고리의 다른 글
| 치명적인 오류 : Python.h : 해당 파일 또는 디렉터리가 없습니다. (0) | 2020.09.27 |
|---|---|
| JavaScript에서 null과 undefined의 차이점은 무엇입니까? (0) | 2020.09.27 |
| Android Studio : jar를 라이브러리로 추가 하시겠습니까? (0) | 2020.09.27 |
| Android Studio에서 "Android SDK를 선택"하려면 어떻게합니까? (0) | 2020.09.27 |
| JavaScript 변수가 달러 기호로 시작하는 이유는 무엇입니까? (0) | 2020.09.27 |