mapply로 이중 루프를 피해 보았습니다.

12210 단어 statisticsR통계학
R의 apply계 중에서도 이채를 내고 있는 mapply의 사용법의 예를 써 보았습니다. 아래 그림과 같이,
1. 50m×50m 안에 2000개의 점이 흩어져 있다.
2. 각 점에 대해 반경 5m 이내에 있는 다른 점의 수를 세는다.
라는 예로 생각해 보겠습니다.



데이터 준비
library(dplyr)
set.seed(4)
n <- 2000
gx <- runif(n, min=0, max=50)
gy <- runif(n, min=0, max=50)
samp_dat <- data_frame(ID = paste("ID", 1:n, sep = "_"), gx, gy) 

이 데이터에서 아래와 같은 결과를 원합니다.


ID
주변 수


ID_1
65

ID_2
37

ID_3
43

...
...

ID_2000
79


보통 루프 사용


  • 루프 1 : 대상 점과 주위 점 사이의 거리를 비교합니다.
  • 루프 2 : 루프 1을 모든 지점에서 수행합니다.

  • 루프만
    countR <- function(gx, gy, r){
     n_length <- length(gx)
     res <- numeric(n_length)
     for (i in 1:n_length){
      temp <- numeric(n_length)
       for (j in 1:n_length){
            if ((gx[i]-gx[j])^2 + (gy[i]-gy[j])^2 <= r^2) temp[j] <- 1
          }
          res[i] <- sum(temp)
          temp <- numeric(n_length)
        }
      res - 1
    }
    
    > system.time(res <- countR(samp_dat$gx, samp_dat$gy, r = 5))
       user  system elapsed
      6.989   0.027   7.015
    > str(res)
     num [1:2000] 65 37 43 65 57 59 58 52 52 65 ...
    

    mapply 사용


  • 첫 번째 루프를 벡터화.
  • 두 번째 루프에 mapply를 사용합니다.

  • mapply
    r <- 5
    countR2 <- function(n){
        temp <- (gx[n] - gx)^2 + (gy[n] - gy)^2 # gx[n]-gxでベクトル化
        temp[temp <= r^2] %>% length - 1
    }
    
    > system.time(res2 <- mapply(countR2, n = 1:n))
       user  system elapsed
      0.170   0.012   0.181
    
    > str(res2)
     num [1:2000] 65 37 43 65 57 59 58 52 52 65 ...
    

    짧게 쓸 수 있었고, 40배 정도 빨라졌습니다.

    좋은 웹페이지 즐겨찾기