R Language
* 기능 패밀리 적용 (기능)
수색…
비고
*apply
패밀리의 함수는 for
루프의 추상화입니다. for
루프와 비교할 때 *apply
함수에는 다음과 같은 장점이 있습니다.
- 적은 코드로 작성하십시오.
- 반복 카운터가 없습니다.
- 중간 결과를 저장하기 위해 임시 변수를 사용하지 않습니다.
그러나 for
루프는보다 일반적이며, *apply
함수를 사용하는 것이 쉽지 않은 복잡한 계산을 수행 할 수 있도록 더 많은 제어를 제공 할 수 있습니다.
관계 for
루프 및 *apply
기능이 설명된다 용 문서 for
루프 .
*apply
회원은 가족을 *apply
*apply
함수 계열 *apply
에는 주로 반환되는 출력의 종류에 따라 다른 동일한 원리의 여러 변형이 포함되어 있습니다.
기능 | 입력 | 산출 |
---|---|---|
apply | matrix , data.frame 또는 array | 벡터 또는 행렬 (반환 된 각 요소의 길이에 따라 다름) |
sapply | 벡터 또는 list | 벡터 또는 행렬 (반환 된 각 요소의 길이에 따라 다름) |
lapply | 벡터 또는 list | list |
vapply | 벡터 또는`리스트 | 반환 된 각 요소의 길이에 따라 사용자 지정 클래스의 벡터 또는 행렬 |
mapply | 여러 벡터, lists 또는 조합 | list |
이러한 함수가 어떻게 사용되는지 보려면 "예제"를 참조하십시오.
적용시 익명 함수 사용
apply
는 배열이나 행렬의 여백 위로 함수 (아마 익명의 것)를 평가하는 데 사용됩니다.
이 아이디어를 설명하기 위해 iris
데이터 세트를 사용합시다. iris
데이터 세트는 3 종의 150 가지 꽃을 측정합니다. 이 데이터 세트가 어떻게 구성되어 있는지 살펴 보겠습니다.
> head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
이제 각 변수의 평균을 알고 싶다고 상상해보십시오. 이 문제를 해결하는 한 가지 방법은 for
루프를 사용하는 것이지만, R 프로그래머는 종종 apply
를 사용하는 것을 선호합니다 (이유는 이유를 참조하십시오).
> apply(iris[1:4], 2, mean)
Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
- 첫 번째 매개 변수에서
mean
은 숫자 데이터에서만 작동하므로 첫 번째 4 개 열만 포함하도록iris
를 하위 집합으로 지정합니다. - 두 번째 매개 변수 값
2
는 열만 (rxC 배열의 두 번째 첨자)으로 작업하기를 원한다는 것을 나타냅니다.1
은 행의 의미를 나타냅니다.
같은 방법으로 더 의미있는 값을 계산할 수 있습니다.
# standard deviation
apply(iris[1:4], 2, sd)
# variance
apply(iris[1:4], 2, var)
주의 사항 : R에는 열 및 행 합계를 계산하는 데 colMeans
몇 가지 기본 제공 함수가 있으며 colMeans
및 rowMeans
의미합니다.
이제보다 의미있는 다른 작업을 해봅시다. 0.5
보다 큰 값에 대해서만 평균을 계산해 보겠습니다. 이를 위해 우리는 우리 자신의 mean
기능을 만들 것입니다.
> our.mean.function <- function(x) { mean(x[x > 0.5]) }
> apply(iris[1:4], 2, our.mean.function)
Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.665347
( Petal.Width
의 평균 차이점에 유의하십시오.)
그러나 나머지 코드에서이 함수를 사용하지 않으려면 어떻게해야합니까? 그런 다음 익명의 함수를 사용하여 다음과 같이 코드를 작성할 수 있습니다.
apply(iris[1:4], 2, function(x) { mean(x[x > 0.5]) })
이제까지 보았 듯이, apply
를 사용하여 하나의 행만 사용하여 데이터 세트의 열이나 행에 대해 동일한 연산을 실행합니다.
주의 사항 : apply
는 지정된 함수의 결과의 길이에 따라 매우 다른 종류의 결과를 반환하기 때문에 대화식으로 작업하지 않는 경우에는 최선의 선택이 아닐 수도 있습니다. 다른 *apply
가족 기능 중 일부는 더 예측 가능합니다 (비고 참조).
대량 파일로드
유사한 프로세스와 잘 구조화 된 파일 이름으로 작동되어야 할 수도있는 많은 수의 파일에 대해.
먼저 액세스 할 파일 이름의 벡터를 만들어야합니다. 여러 가지 옵션이 있습니다.
paste0()
하여 수동으로 벡터 만들기files <- paste0("file_", 1:100, ".rds")
list.files()
를 파일 유형에 대한 정규식 검색 용어와 함께 사용하면 동일한 유형의 다른 파일이 디렉토리에 있으면 정규 표현식 ( 정규식 )에 대한 지식이 필요합니다.files <- list.files("./", pattern = "\\.rds$", full.names = TRUE)
여기서 X
는 사용 된 파일 이름 지정 형식의 일부인 벡터입니다.
lapply
는 각 응답을 목록의 요소로 출력합니다.
readRDS
는 .rds
파일에만 해당되며 프로세스의 적용에 따라 변경됩니다.
my_file_list <- lapply(files, readRDS)
테스트에서 for 루프보다 반드시 빠를 필요는 없지만 모든 파일을 명시 적으로 지정하지 않고 목록의 요소로 사용할 수 있습니다.
마지막으로 한 번에 여러 패키지를로드해야하는 경우가 있습니다. 이 트릭은 우리가 가져 오기를 원하는 모든 라이브러리에 library()
를 적용함으로써 아주 쉽게 할 수 있습니다 :
lapply(c("jsonlite","stringr","igraph"),library,character.only=TRUE)
여러 개의`data.frames` (`lapply`,`mapply`)
이 연습에서는 4 개의 부트 스트랩 선형 회귀 모델을 생성하고 이러한 모델의 요약을 단일 데이터 프레임에 결합합니다.
library(broom)
#* Create the bootstrap data sets
BootData <- lapply(1:4,
function(i) mtcars[sample(1:nrow(mtcars),
size = nrow(mtcars),
replace = TRUE), ])
#* Fit the models
Models <- lapply(BootData,
function(BD) lm(mpg ~ qsec + wt + factor(am),
data = BD))
#* Tidy the output into a data.frame
Tidied <- lapply(Models,
tidy)
#* Give each element in the Tidied list a name
Tidied <- setNames(Tidied, paste0("Boot", seq_along(Tidied)))
이 시점에서 우리는 이름을 data.frame에 삽입하는 두 가지 접근법을 취할 수 있습니다.
#* Insert the element name into the summary with `lapply`
#* Requires passing the names attribute to `lapply` and referencing `Tidied` within
#* the applied function.
Described_lapply <-
lapply(names(Tidied),
function(nm) cbind(nm, Tidied[[nm]]))
Combined_lapply <- do.call("rbind", Described_lapply)
#* Insert the element name into the summary with `mapply`
#* Allows us to pass the names and the elements as separate arguments.
Described_mapply <-
mapply(
function(nm, dframe) cbind(nm, dframe),
names(Tidied),
Tidied,
SIMPLIFY = FALSE)
Combined_mapply <- do.call("rbind", Described_mapply)
magrittr
스타일 파이프 팬이라면, 전체 작업을 단일 체인으로 수행 할 수 있습니다 (모델 객체 자체와 같은 중간 객체가 필요한 경우에는 그렇게하지 않는 것이 좋습니다).
library(magrittr)
library(broom)
Combined <- lapply(1:4,
function(i) mtcars[sample(1:nrow(mtcars),
size = nrow(mtcars),
replace = TRUE), ]) %>%
lapply(function(BD) lm( mpg ~ qsec + wt + factor(am), data = BD)) %>%
lapply(tidy) %>%
setNames(paste0("Boot", seq_along(.))) %>%
mapply(function(nm, dframe) cbind(nm, dframe),
nm = names(.),
dframe = .,
SIMPLIFY = FALSE) %>%
do.call("rbind", .)
내장 함수를 사용하기
내장 함수 : lapply (), sapply () 및 mapply ()
R에는 내장 함수가 있으며, 그 중 가장 잘 알려진 함수가 적용됩니다. 다음은 가장 일반적인 적용 기능 중 일부에 대한 설명입니다.
-
lapply()
=는 목록을 인수로 취하여 지정된 함수를 목록에 적용합니다. -
sapply()
=lapply()
같지만 출력을 벡터 나 행렬로 단순화하려고합니다.-
vapply()
= 출력 객체의 유형을 지정sapply()
의 변형입니다.
-
-
mapply()
=mapply()
와lapply()
하지만 지정된 함수에 입력으로 여러 벡터를 전달할 수 있습니다.sapply()
처럼 단순화 될 수 있습니다.-
Map()
은mapply()
SIMPLIFY = FALSE
mapply()
의 별명입니다.
-
lapply ()
lapply()
는 두 가지 다른 반복과 함께 사용할 수 있습니다.
-
lapply(variable, FUN)
-
lapply(seq_along(variable), FUN)
# Two ways of finding the mean of x
set.seed(1)
df <- data.frame(x = rnorm(25), y = rnorm(25))
lapply(df, mean)
lapply(seq_along(df), function(x) mean(df[[x]))
sapply ()
sapply()
는 출력을 벡터 또는 행렬로 변환하려고 시도합니다.
# Two examples to show the different outputs of sapply()
sapply(letters, print) ## produces a vector
x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))
sapply(x, quantile) ## produces a matrix
mapply ()
mapply()
는 다중 벡터를 입력으로 취할 수 있다는 점을 제외하면 lapply()
와 매우 유사합니다 (따라서 다중 변수의 경우 m).
mapply(sum, 1:5, 10:6, 3) # 3 will be "recycled" by mapply
사용자 정의 함수식 사용
사용자 정의 함수식
사용자는 다양한 복잡성에 따라 자체 기능을 만들 수 있습니다. 다음은 Hadley Wickham의 Functionals 에서 나온 예제입니다.
randomise <- function(f) f(runif(1e3))
lapply2 <- function(x, f, ...) {
out <- vector("list", length(x))
for (i in seq_along(x)) {
out[[i]] <- f(x[[i]], ...)
}
out
}
첫 번째 경우, randomise
는 단일 인수 f
받아 들여 Uniform 임의 변수의 샘플에서 호출합니다. 동등성을 증명하기 위해 아래 set.seed
를 호출합니다.
set.seed(123)
randomise(mean)
#[1] 0.4972778
set.seed(123)
mean(runif(1e3))
#[1] 0.4972778
set.seed(123)
randomise(max)
#[1] 0.9994045
set.seed(123)
max(runif(1e3))
#[1] 0.9994045
두 번째 예제는 functionals를 사용하여리스트 ( x
)의 각 요소에 연산 ( f
)을 적용하는 base::lapply
의 재 구현입니다. ...
매개 변수를 사용하면 mean
함수의 na.rm
옵션과 같이 f
추가 인수를 전달할 수 있습니다.
lapply(list(c(1, 3, 5), c(2, NA, 6)), mean)
# [[1]]
# [1] 3
#
# [[2]]
# [1] NA
lapply2(list(c(1, 3, 5), c(2, NA, 6)), mean)
# [[1]]
# [1] 3
#
# [[2]]
# [1] NA
lapply(list(c(1, 3, 5), c(2, NA, 6)), mean, na.rm = TRUE)
# [[1]]
# [1] 3
#
# [[2]]
# [1] 4
lapply2(list(c(1, 3, 5), c(2, NA, 6)), mean, na.rm = TRUE)
# [[1]]
# [1] 3
#
# [[2]]
# [1] 4