그룹화 함수 (tapply, by, 집계) 및 * apply 제품군
R에서 "map"을하고 싶을 때마다 보통 apply
패밀리 의 함수를 사용하려고합니다 .
그러나 나는 그들 사이의 차이점을 전혀 이해하지 못했습니다. { sapply
,, lapply
etc.} 함수를 입력 / 그룹화 된 입력에 적용하는 방법, 출력이 어떻게 보일지, 심지어 입력이 될 수 있는지-그래서 저는 종종 내가 원하는 것을 얻을 때까지 모두 통과하십시오.
누군가 언제 어떤 것을 사용하는지 설명 할 수 있습니까?
나의 현재 (아마도 부정확하거나 불완전한) 이해는 ...
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] 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
하면는 기본적으로 동일한 작업을 수행하여 반환 된 각 행렬을 단일 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 91
mapply - 당신은 몇 가지 데이터 구조를 (예를 들어, 벡터, 목록) 당신은 같이 벡터 / 배열에 결과를 강요 등 각각의 제 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] 4
Map - with에 대한 래퍼 이므로 목록을 반환 할 수 있습니다.
mapply
SIMPLIFY = FALSE
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
위해이 답변을 처음 게시 할 때 잊어 버렸습니다! 분명히 많은 사람들이 그것을 사용한다고 확신하지만 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의 토론에서 정당성을 찾을 수 있습니다.
기억술
lapply
A는 리스트 목록 또는 벡터에 작용하고 목록을 반환 적용됩니다.sapply
A는 단순lapply
(a 벡터 또는 행렬 수를 반환하는 함수의 기본값)vapply
A는 적용 확인은 (반환 개체 유형이 미리 지정된 할 수 있습니다)rapply
A는 재귀가 중첩 된 목록, 목록 내에서 즉,리스트 신청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
대한 메서드도 가지고 있다는 것 입니다.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 = TRUE
갖기 때문에 를 호출해야 합니다 ).formula
aggregate
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
우리는 단지 사실에 다음 함수 호출 오류를 반환합니다 (그러나 대부분이 제공된 기능과 관련이 있음을 달성 할 수없는 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
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
솔직히 저는 이것을 많이 사용하지 않지만 많은 패키지를 빌드하거나 많은 환경을 만드는 경우 유용 할 수 있습니다.
나는 최근에 다소 유용한 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 |