आर में बहुभुज की साजिश को कैसे गति दें?


24

मैं एक रेखापुंज छवि पर उत्तरी अमेरिका की देश की सीमाओं को कुछ चर का चित्रण करना चाहता हूं और फिर आर का उपयोग करके भूखंड के शीर्ष पर ओवरले कॉन्ट्रोवर्सीज करता हूं। मैं बेस ग्राफिक्स और जाली का उपयोग करके ऐसा करने में सफल रहा हूं, लेकिन ऐसा लगता है कि प्लॉटिंग प्रक्रिया बहुत धीमी गति से! मैंने अभी तक ggplot2 में ऐसा नहीं किया है, लेकिन मुझे संदेह है कि यह गति के मामले में बेहतर होगा।

मैं एक gbb फ़ाइल से बनाई गई netcdf फ़ाइल में डेटा है । अभी के लिए, मैं कनाडा, अमेरिका और मेक्सिको, जिसमें से rdata फ़ाइलों में उपलब्ध थे के लिए देश की सीमाओं से डाउनलोड GADM जो आर में पढ़ SpatialPolygonsDataFrame वस्तुओं के रूप में।

यहाँ कुछ कोड है:

# 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 क्षमा करें, मैं बहुभुज, अनुमानों आदि सहित आर से संबंधित चीजों की मैपिंग में नया हूं ... मुझे आपका प्रश्न समझ में नहीं आ रहा है
ialm

2
आप प्लॉट विंडो के अलावा किसी अन्य डिवाइस पर प्लॉटिंग की कोशिश कर सकते हैं। पीडीएफ या जेपीईजी (संबद्ध तर्कों के साथ) में प्लॉट फ़ंक्शन लपेटें और इन प्रारूपों में से एक को आउटपुट करें। मैंने पाया है कि यह काफी तेज है।
जेफरी इवांस

@ जेफ्री इवान्स वाह, हाँ। मैंने ऐसा नहीं माना। प्लॉट विंडो में तीन आकार की फाइलों को प्लॉट करने में लगभग 60 सेकंड लगे, लेकिन एक फाइल के लिए प्लॉटिंग में केवल 14 सेकंड लगे। फिर भी हाथ में कार्य के लिए बहुत धीमा है, लेकिन नीचे दिए गए उत्तर में कुछ तरीकों के साथ संयुक्त होने पर यह उपयोगी साबित हो सकता है। धन्यवाद!
अय्यम

जवाबों:


30

मुझे आर। के लिए आकार की फ़ाइलों से देश की सीमाओं की साजिश रचने की गति बढ़ाने के 3 तरीके मिले। मुझे यहाँ और यहाँ से कुछ प्रेरणा और कोड मिला ।

(1) हम पॉलीगोन के देशांतर और अक्षांश प्राप्त करने के लिए आकृति फ़ाइलों से निर्देशांक निकाल सकते हैं। फिर हम उन्हें एक डेटा फ्रेम में डाल सकते हैं जिसमें पहला कॉलम लॉन्गिट्यूड और दूसरा कॉलम जिसमें लेटिट्यूड होता है। विभिन्न आकृतियों को NA द्वारा अलग किया जाता है।

(2) हम अपनी आकृति फ़ाइल से कुछ बहुभुज निकाल सकते हैं। आकार फ़ाइल बहुत, बहुत विस्तृत है, लेकिन कुछ आकार छोटे द्वीप हैं जो महत्वहीन हैं (मेरे भूखंडों, वैसे भी)। हम बड़े बहुभुज रखने के लिए एक न्यूनतम बहुभुज क्षेत्र सीमा निर्धारित कर सकते हैं।

(३) हम डगलस-पीकर एल्गोरिथ्म का उपयोग करके अपनी आकृतियों की ज्यामिति को सरल बना सकते हैं । हमारे बहुभुज आकृतियों के किनारों को सरल बनाया जा सकता है, क्योंकि वे मूल फ़ाइल में बहुत जटिल हैं। सौभाग्य से, एक पैकेज है 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 वस्तु के प्रक्षेपण के रूप में रखने की तुलना में यहां कुछ जानकारी खो देते हैं। हालांकि, हम इसे वापस ऑब्जेक्ट में बदल सकते हैं और प्रक्षेपण जानकारी को वापस जोड़ सकते हैं, और यह मूल डेटा को साजिश रचने की तुलना में अभी भी तेज है।

ध्यान दें कि यह कोड मूल फ़ाइल पर बहुत धीरे-धीरे चलता है क्योंकि इसमें बहुत सारे आकार हैं, और परिणामस्वरूप डेटा फ़्रेम ~ 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: छोटे बहुभुजों को हटा दें

कई छोटे द्वीप हैं जो बहुत महत्वपूर्ण नहीं हैं। यदि आप बहुभुज के लिए क्षेत्रों के कुछ मात्राओं की जांच करते हैं, तो हम देखते हैं कि उनमें से कई miniscule हैं। कनाडा के प्लॉट के लिए, मैं एक हजार पॉलीगोन से अधिक सैकड़ों पॉलीगॉन की साजिश रचने से नीचे चला गया।

कनाडा के लिए बहुभुज के आकार के लिए मात्राएँ:

          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अपने प्लॉटिंग समय को बेंचमार्क करने के लिए इस्तेमाल किया । ध्यान दें कि ये समोच्च लाइनों और अन्य अतिरिक्त चीजों के बिना, देशों की साजिश रचने का समय है। सपा वस्तुओं के लिए, मैं सिर्फ plotफ़ंक्शन का उपयोग करता हूं । डेटा फ़्रेम ऑब्जेक्ट्स के लिए, मैंने 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, जिसे कोई संदेह नहीं है कि भविष्य के पाठक उपयोगी पाएंगे।
धीरे

3

हर किसी को एसपी के स्थान पर एसएफ (स्थानिक सुविधाओं) पैकेज में स्थानांतरित करना चाहिए। यह काफी तेज है (इस मामले में 1/60 वां) और उपयोग करने में आसान है। यहाँ एक shp में पढ़ने और ggplot2 के माध्यम से साजिश रचने का एक उदाहरण है।

नोट: आपको ggplot2 को github पर सबसे हालिया बिल्ड से पुनर्स्थापित करने की आवश्यकता है (नीचे देखें)

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

जीएडीएम डेटा में कोस्टलाइन्स का बहुत उच्च स्थानिक रिज़ॉल्यूशन है। यदि आपको आवश्यकता नहीं है कि आप अधिक सामान्यीकृत डेटा सेट का उपयोग कर सकते हैं। ialm के दृष्टिकोण बहुत ही रोचक हैं, लेकिन एक सरल विकल्प 'रैप्ड_सिमप्ल' डेटा का उपयोग करना है जो 'सप्तऋषि' के साथ आता है

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

मैं अपने डेटा सेट में आकृतियों को संरक्षित करना चाहता था क्योंकि इसमें देश के अंदर के क्षेत्र (जैसे प्रांत और राज्य) के लिए सीमाएं थीं। अन्यथा मैंने मैप डेटा पैकेज में नक्शे का उपयोग किया होता!
इलियम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.