【问题标题】:Why does spplot take so much time for multiple panels为什么 spplot 需要这么多时间来处理多个面板
【发布时间】:2019-06-14 07:52:17
【问题描述】:

我正在使用 spplot 绘制多个 shapefile。这是构建它的数据

library(raster)
library(randomcoloR)

my.shp <- getData('GADM', country = 'BRA', level = 2)
my.shp$ID<- 1:nrow(my.shp)

我的数据包含一个变量X 10 年,如图所示,每列是一年

df <- matrix(sample(100:5000, 55040, replace = T), nrow = 5504, ncol = 10)
df <- data.frame(ID = 1:nrow(my.shp), df)

my.dat <- merge(my.shp, df, by = "ID")

variable.names <- paste0("X",1:10)

spplot(my.dat, rev(variable.names), col = NA, at = seq(from = 100, to = 5000, by = 500), 
          col.regions = distinctColorPalette(length(seq(from = 100, to = 5000, by = 500))),
          main = list(label = "TEST")) 

我的问题是这个情节需要很长时间(大约一个小时)才能绘制出来,并且想知道代码本身是否存在固有的错误,以至于绘制时间过长。我的笔记本电脑有 32 GB RAM。

谢谢

【问题讨论】:

    标签: r geospatial raster shapefile sp


    【解决方案1】:

    我没有将此情节与您的spplot 进行比较,因为我不想花一个小时等待它。

    相反,我建议使用library(mapdeck) 绘制交互式地图,这需要几秒钟。

    注意两点

    1. 您需要一个 Mapbox 访问令牌
    2. 您需要将sp 对象转换为sf
    library(raster)
    
    my.shp <- getData('GADM', country = 'BRA', level = 2)
    my.shp$ID <- 1:nrow(my.shp)
    
    df <- matrix(sample(100:5000, 55040, replace = T), nrow = 5504, ncol = 10)
    df <- data.frame(ID = 1:nrow(my.shp), df)
    
    my.dat <- merge(my.shp, df, by = "ID")
    
    
    library(sf)
    sf <- sf::st_as_sf( my.dat )
    
    library(mapdeck)
    
    set_token( "YOUR_MAPBOX_TOKEN" )
    
    mapdeck() %>% 
      add_sf(
        data = sf
        , fill_colour = "GID_2"
        )
    

    【讨论】:

    • 谢谢,虽然它看起来是一个不错的选择,但不幸的是,我不能奖励我的赏金,因为我对解决我的确切问题感兴趣。我会用你的方法做其他事情。感谢您的时间和精力。
    • 有趣的是,我看到使用这种方法的空白页。有什么理由会是这个原因吗?我尝试同时使用公共和私人令牌
    • 尝试在浏览器中打开它。也见这里symbolixau.github.io/mapdeck/articles/issues.html
    • 好的,谢谢。看起来我只能在 linux 的网络浏览器上打开 rstudio。我只知道如何在 Windows 上工作。还是谢谢
    • 我的意思不是在浏览器中打开 RStudio,我的意思是在浏览器中打开绘图。见stackoverflow.com/a/52470812/5977215
    【解决方案2】:

    您是否愿意/能够切换到sf 而不是sp

    sf plot 函数比 spplot 快得多,尽管布局略有不同。

    library(sf)
    my.dat_sf <- st_as_sf(my.dat)
    plot(my.dat_sf[rev(variable.names)], max.plot=10, breaks=c(seq(from = 100, to = 5000, by = 500),5000),
         pal = distinctColorPalette(length(seq(from = 100, to = 5000, by = 500))),
         main = "TEST", border=NA, key.pos=4)
    

    此外,您可以尝试使用rmapshaper::ms_simplify() 用于空间*-objects 或sf::st_simplify() 用于SimpleFeatures 来简化多边形,这可以让您减少相当多的对象大小,具体取决于给定的dTolerance。因此,使用简化的多边形进行绘图也会更快。

    原来的SpatialPolygon:

    format(object.size(my.dat_sf), units="Kb")
    

    “25599.2 KB”

    还有一个简化的 SimpleFeature:

    dat_sf_simple <- st_transform(my.dat_sf, crs = 3035)
    dat_sf_simple <- st_simplify(dat_sf_simple, dTolerance = 1000, preserveTopology = T)
    dat_sf_simple <- st_transform(dat_sf_simple, crs = 4326)
    format(object.size(dat_sf_simple), units="Kb")
    

    “7864.2 KB”

    绘制简化的 SimpleFeature,在我的 8GB RAM 机器上大约需要 1 分钟。

    plot(dat_sf_simple[rev(variable.names)], max.plot=10, breaks=c(seq(from = 100, to = 5000, by = 500),5000),
         pal = distinctColorPalette(length(seq(from = 100, to = 5000, by = 500))),
         main = "TEST", border=NA, key.pos=4)
    

    您也可以尝试使用ggplot2,但我很确定最高效的解决方案将是 sf 情节。

    library(ggplot2)
    library(dplyr)
    library(tidyr)
    
    dat_sf_simple_gg <- dat_sf_simple %>% 
      dplyr::select(rev(variable.names), geometry) %>% 
      gather(VAR, SID, -geometry)
    
    ggplot() +
      geom_sf(data = dat_sf_simple_gg, aes(fill=SID)) + 
      facet_wrap(~VAR, ncol = 2) 
    

    【讨论】:

    • 好的。我有两个后续问题:我的解决方案允许我在所有地图上都有一个共同的图例。如何在您的解决方案中插入通用图例?其次,如果我想在顶部添加状态边界,在我的解决方案中我可以做latticeExtra::layer(sp.polygons(my.boundary, lwd = 0.05))。这在您的情况下如何运作?
    • 要查看州边界,请删除 border=NA。要添加图例,请在 plot 调用中添加 key.pos=4
    • 谢谢。我的意思是如果我想在这张地图上添加另一个多边形,我该怎么做。做边界 = NA 只会删除这个城市的当前边界
    • 您能否在示例中包含对latticeExtra::layer 的调用。我无法制作那个情节,因此我真的不知道结果应该是什么样子。但 sf plot 也采用了参数add。但我真的不知道它会如何添加到情节中,如果情节在绘制多列时有“方面”。
    猜你喜欢
    • 2016-04-30
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多