R에서 다각형 플로팅 속도를 높이는 방법은 무엇입니까?


24

일부 변수를 나타내는 래스터 이미지 위에 북미의 국경을 그린 다음 R을 사용하여 플롯 위에 윤곽선을 오버레이하고 싶습니다. 기본 그래픽과 격자를 사용 하여이 작업을 성공적으로 수행했지만 플로팅 프로세스는 다음과 같습니다. 너무 느려! 나는 아직 ggplot2에서 이것을하지 않았지만 속도면에서 더 잘 지낼 것이라고 의심합니다.

grib 파일에서 작성된 netcdf 파일 의 데이터가 있습니다. 지금, 나는에서 RData에 파일에서 사용할 수 있었던 캐나다, 미국, 멕시코에 대한 국가의 경계 다운로드 GADM SpatialPolygonsDataFrame이 객체로 R로 읽습니다.

다음은 몇 가지 코드입니다.

# Load packages
library(raster)
#library(ncdf) # If you cannot install ncdf4
library(ncdf4)

# Read in the file, get the 13th layer
# fn <- 'path_to_file'
r <- raster(fn, band=13)

# Set the projection and extent
p4 <- "+proj=lcc +lat_1=50.0 +lat_2=50.0 +units=km +x_0=32.46341 +y_0=32.46341 +lon_0=-107 +lat_0=1.0"
projection(r) <- CRS(p4)
extent(r) <- c(-5648.71, 5680.72, 1481.40, 10430.62)

# Get the country borders
# This will download the RData files to your working directory
can<-getData('GADM', country="CAN", level=1)
usa<-getData('GADM', country="USA", level=1)
mex<-getData('GADM', country="MEX", level=1)

# Project to model grid
can_p <- spTransform(can, CRS(p4))
usa_p <- spTransform(usa, CRS(p4))
mex_p <- spTransform(mex, CRS(p4))

### USING BASE GRAPHICS
par(mar=c(0,0,0,0))
# Plot the raster
bins <- 100
plot(r, axes=FALSE, box=FALSE, legend=FALSE,
     col=rev( rainbow(bins,start=0,end=1) ),
     breaks=seq(4500,6000,length.out=bins))
plot(r, legend.only=TRUE, col=rev( rainbow(bins,start=0,end=1)),
     legend.width=0.5, legend.shrink=0.75, 
     breaks=seq(4500,6000,length.out=bins),
     axis.args=list(at=seq(4500,6000,length.out=11),
                labels=seq(4500,6000,length.out=11),
                cex.axis=0.5),
     legend.args=list(text='Height (m)', side=4, font=2, 
                      line=2, cex=0.8))
# Plot the borders
# These are so slow!!
plot(can_p, add=TRUE, border='white', lwd=2)
plot(usa_p, add=TRUE, border='white', lwd=2)
plot(mex_p, add=TRUE, border='white', lwd=2)
# Add the contours
contour(r, add=TRUE, nlevel=5)

### USING LATTICE
library(rasterVis)

# Some settings for our themes
myTheme <- RdBuTheme()
myTheme$axis.line$col<-"transparent"
myTheme$add.line$alpha <- 1
myTheme2 <- myTheme
myTheme2$regions$col <- 'transparent'
myTheme2$add.text$cex <- 0.7
myTheme2$add.line$lwd <- 1
myTheme2$add.line$alpha <- 0.8

# Get JUST the contour lines
contours <- contourplot(r, margin=FALSE, scales=list(draw=FALSE),
                        par.settings=myTheme2, pretty=TRUE, key=NULL, cuts=5,
                        labels=TRUE)

# Plot the colour
levels <- levelplot(r, contour=FALSE, margin=FALSE, scales=list(draw=FALSE),
                    par.settings = myTheme, cuts=100)

# Plot!
levels +  
  layer(sp.polygons(can_p, col='green', lwd=2)) +
  layer(sp.polygons(usa_p, col='green', lwd=2)) +
  layer(sp.polygons(mex_p, col='green', lwd=2)) +
  contours

다각형의 플로팅 속도를 높이는 방법이 있습니까? 내가 작업중 인 시스템에서 플로팅에는 몇 분이 걸립니다. 검사를 위해 이러한 많은 플롯을 쉽게 생성 할 수있는 함수를 만들고 싶습니다. 많은 맵을 플로팅 할 것이므로 플롯의 속도를 높이고 싶습니다!

감사!


다각형 아이디어 필드에 인덱스를 만들 수 있습니까?
레이더 아래

@ Burton449 죄송합니다, 다각형, 투영법 등 R의 매핑 관련 항목에
익숙

2
플롯 창 이외의 장치로 플로팅을 시도 할 수 있습니다. 플롯 함수를 pdf 또는 jpeg (관련 인수 포함)로 랩핑하고 이러한 형식 중 하나를 출력하십시오. 나는 이것이 훨씬 빠르다는 것을 발견했다.
Jeffrey Evans

@JeffreyEvans 와우. 나는 그것을 고려하지 않았다. 3 개의 모양 파일을 플롯 창에 플로팅하는 데 약 60 초가 걸렸지 만 파일에 플로팅하는 데 14 초 밖에 걸리지 않았습니다. 아직 과제가 너무 느리지 만 아래 답변의 일부 방법과 결합하면 유용 할 수 있습니다. 감사!
ialm

답변:


30

R에 대한 모양 파일에서 국가 경계를 그리는 속도를 높이는 3 가지 방법을 찾았습니다 . 여기여기 에서 영감과 코드를 찾았습니다 .

(1) 다각형의 경도와 위도를 얻기 위해 모양 파일에서 좌표를 추출 할 수 있습니다. 그런 다음 경도를 포함하는 첫 번째 열과 위도를 포함하는 두 번째 열이있는 데이터 프레임에 넣을 수 있습니다. 다른 모양은 NA로 구분됩니다.

(2) 모양 파일에서 일부 다각형을 제거 할 수 있습니다. 모양 파일은 매우 상세하지만 일부 모양은 중요하지 않은 작은 섬입니다 (어쨌든 음모에 대해서는). 더 큰 다각형을 유지하기 위해 최소 다각형 영역 임계 값을 설정할 수 있습니다.

(3) Douglas-Peuker 알고리즘을 사용하여 도형의 형상을 단순화 할 수 있습니다 . 다각형 모양의 가장자리는 원본 파일에서 매우 복잡하므로 단순화 할 수 있습니다. 다행히도 rgeos이를 구현 하는 패키지가 있습니다.

설정:

# Load packages
library(rgdal)
library(raster)
library(sp)
library(rgeos)

# Load the shape files
can<-getData('GADM', country="CAN", level=0)
usa<-getData('GADM', country="USA", level=0)
mex<-getData('GADM', country="MEX", level=0)

방법 1 : 모양 파일에서 좌표를 데이터 프레임으로 추출하고 선을 그립니다

가장 큰 단점은 투영과 같은 개체를 SpatialPolygonsDataFrame 개체로 유지하는 것과 비교할 때 일부 정보가 손실된다는 것입니다. 그러나이를 sp 객체로 다시 변환하고 투영 정보를 다시 추가 할 수 있으며 원본 데이터를 플롯하는 것보다 여전히 빠릅니다.

이 코드는 모양이 많기 때문에 원본 파일에서 매우 느리게 실행되며 결과 데이터 프레임의 길이는 약 2 백만 행입니다.

암호:

# Convert the polygons into data frames so we can make lines
poly2df <- function(poly) {
  # Convert the polygons into data frames so we can make lines
  # Number of regions
  n_regions <- length(poly@polygons)

  # Get the coords into a data frame
  poly_df <- c()
  for(i in 1:n_regions) {
    # Number of polygons for first region
    n_poly <- length(poly@polygons[[i]]@Polygons)
    print(paste("There are",n_poly,"polygons"))
    # Create progress bar
    pb <- txtProgressBar(min = 0, max = n_poly, style = 3)
    for(j in 1:n_poly) {
      poly_df <- rbind(poly_df, NA, 
                       poly@polygons[[i]]@Polygons[[j]]@coords)
      # Update progress bar
      setTxtProgressBar(pb, j)
    }
    close(pb)
    print(paste("Finished region",i,"of",n_regions))
  }
  poly_df <- data.frame(poly_df)
  names(poly_df) <- c('lon','lat')
  return(poly_df)
}

방법 2 : 작은 다각형 제거

별로 중요하지 않은 많은 작은 섬들이 있습니다. 다각형에 대한 영역의 일부 Quantile을 확인하면 그 중 많은 영역이 축소 된 것을 볼 수 있습니다. 캐나다 음모의 경우 천 개가 넘는 다각형을 그리는 것에서 수백 개의 다각형으로 줄었습니다.

캐나다의 다각형 크기에 대한 분위수 :

          0%          25%          50%          75%         100% 
4.335000e-10 8.780845e-06 2.666822e-05 1.800103e-04 2.104909e+02 

암호:

# Get the main polygons, will determine by area.
getSmallPolys <- function(poly, minarea=0.01) {
  # Get the areas
  areas <- lapply(poly@polygons, 
                  function(x) sapply(x@Polygons, function(y) y@area))

  # Quick summary of the areas
  print(quantile(unlist(areas)))

  # Which are the big polygons?
  bigpolys <- lapply(areas, function(x) which(x > minarea))
  length(unlist(bigpolys))

  # Get only the big polygons and extract them
  for(i in 1:length(bigpolys)){
    if(length(bigpolys[[i]]) >= 1 && bigpolys[[i]] >= 1){
      poly@polygons[[i]]@Polygons <- poly@polygons[[i]]@Polygons[bigpolys[[i]]]
      poly@polygons[[i]]@plotOrder <- 1:length(poly@polygons[[i]]@Polygons)
    }
  }
  return(poly)
}

방법 3 : 다각형 모양의 지오메트리 단순화

패키지 의 gSimplify함수를 사용하여 다각형 모양의 꼭짓점 수를 줄일 수 있습니다rgeos

암호:

can <- getData('GADM', country="CAN", level=0)
can <- gSimplify(can, tol=0.01, topologyPreserve=TRUE)

일부 벤치 마크 :

경과 시간 system.time을 사용 하여 플로팅 시간을 벤치마킹했습니다. 이것은 등고선과 다른 추가 사항없이 국가를 그리는 시간입니다. sp 객체의 경우 방금 plot함수를 사용했습니다 . 데이터 프레임 객체의 경우, I는 사용 plot과 기능 type='l'lines기능.

원래 캐나다, 미국, 멕시코 다각형 플로팅 :

73.009 초

방법 1 :

2.449 초

방법 2 :

17.660 초

방법 3 :

16.695 초

방법 2 + 1 사용 :

1.729 초

방법 2 + 3 사용 :

0.445 초

방법 2 + 3 + 1 사용 :

0.172 초

기타 비고 :

방법 2 + 3의 조합은 다각형 플로팅에 충분한 속도를 제공하는 것으로 보입니다. 2 + 3 + 1 방법을 사용하면 sp객체 의 멋진 속성을 잃어 버리는 문제가 추가 되고 내 주된 어려움은 투영을 적용하는 것입니다. 데이터 프레임 객체를 투영하기 위해 무언가를 해킹했지만 느리게 실행됩니다. 나는 방법 2 + 3을 사용하면 방법 2 + 3 + 1을 사용하여 꼬임을 얻을 수있을 때까지 충분한 속도를 제공한다고 생각합니다.


3
쓰기에 +1. 의심 할 여지없이 미래의 독자라면 유용 할 것입니다.
SlowLearner

3

모든 사람은 sp 대신 sf (공간 기능) 패키지로 전송해야합니다. 훨씬 빠르며 (이 경우 1/60) 사용하기가 더 쉽습니다. 다음은 shp로 읽고 ggplot2를 통해 플로팅하는 예입니다.

참고 : github의 최신 빌드에서 ggplot2를 다시 설치해야합니다 (아래 참조).

library(rgdal)
library(sp)
library(sf)
library(plyr)
devtools::install_github("tidyverse/ggplot2")
library(ggplot2)

# Load the shape files
can<-getData('GADM', country="CAN", level=0)
td <- file.path(tempdir(), "rgdal_examples"); dir.create(td)
st_write(st_as_sf(can),file.path(td,'can.shp'))


ptm <- proc.time()
  can = readOGR(dsn=td, layer="can")
  can@data$id = rownames(can@data)
  can.points = fortify(can, region="id")
  can.df = join(can.points, can@data, by="id")
  ggplot(can.df) +  geom_polygon(aes(long,lat,group=group,fill='NAME_ENGLISH'))
proc.time() - ptm

user  system elapsed 
683.344   0.980 684.51 

ptm <- proc.time()
  can2 = st_read(file.path(td,'can.shp'))  
  ggplot(can2)+geom_sf( aes(fill = 'NAME_ENGLISH' )) 
proc.time() - ptm

user  system elapsed 
11.340   0.096  11.433 

0

GADM 데이터는 해안선의 공간 해상도가 매우 높습니다. 필요하지 않은 경우보다 일반화 된 데이터 세트를 사용할 수 있습니다. ialm의 접근 방식은 매우 흥미롭지 만 간단한 대안은 'maptools'와 함께 제공되는 'wrld_simpl'데이터를 사용하는 것입니다.

library(maptools)
data(wrld_simpl)
plot(wrld_simpl)

데이터 세트의 모양을 국가 내부의 경계 (예 : 지방 및 주)가 포함되어 있기 때문에 데이터 세트의 셰이프를 유지하려고했습니다. 그렇지 않으면지도 데이터 패키지에서지도를 사용했을 것입니다!
ialm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.