R 中带有 fortify 的 ggplot 处理小地理空间数据的时间太长

ggplot in R with fortify takes too long to process small geospatial data

我正在尝试使用 ggplot 绘制加拿大地图并根据总销售额对每个区域进行颜色编码。地理空间文件来自 GADM,仅包含 12 个省(级别 1)。当我强化数据时,结果 data.frame 超过 400 万行。当我尝试用 ggplot 绘制地图时,它似乎挂起了。我已经离开它 30 分钟,不得不放弃。

问题出在fortify结果的大小上吗?我不知道如何减小尺寸。我试过在 fortify 中使用 'region' 参数,但这会导致 fortify 似乎挂起。

我已经包含了我的所有代码和 URL 以下载我正在使用的数据。

require(dplyr)

# loaded from: https://raw.githubusercontent.com/Technology-Hatchery/Rcode/master/Data/Sample%20-%20Superstore%20Sales%20(Excel).csv
orders <- read.csv(file='Data/Orders.csv', sep=',', header=TRUE, na.strings = '')
orders$Order.Date <- as.Date(orders$Order.Date, '%m/%d/%y')
orders$Order.Priority <- as.factor(orders$Order.Priority)
orders$Customer.Name <- as.character(orders$Customer.Name)
orders$Ship.Date <- as.Date(orders$Ship.Date, '%m/%d/%y')
orders$Order.Total <- orders$Unit.Price * orders$Order.Quantity
orders <- tbl_df(orders)

require(raster)
require(ggplot2)
require(RColorBrewer)
require(rgdal)
require(rgeos)

# map from GADM: http://biogeo.ucdavis.edu/data/gadm2.7/rds/CAN_adm1.rds
canada <- readRDS('../../Geo/GADM/Canada/CAN_adm1.rds')
canada <- spTransform(canada, CRS("+proj=longlat +datum=WGS84"))

# Add my data to spatial polygon data.frame
canada.df <- fortify(canada)
summary(canada.df)

nrow(canada.df)

# [1] 4005898

# Build region list and add to spatial DF
provinces <- canada@data %>% dplyr::select(OBJECTID, NAME_1) %>% dplyr::rename(id = OBJECTID, Province = NAME_1)
head(provinces)

# Add total sales to spatial DF
provinceOrders <- orders %>% mutate(Province = as.character(Province)) %>%
       left_join(., provinces, by='Province') %>%
       group_by(id, Province) %>%
       dplyr::summarise(Total = sum(Order.Total)) %>%
       dplyr::select(id, Total)
head(provinceOrders)

canada.df <- merge(canada.df, provinceOrders, by='id', all.x=TRUE)
canada.df <- arrange(canada.df, order, group)
head(canada.df)

ggplot() +
geom_polygon(data=canada.df, aes(x=long, y=lat, group=group, fill=Total), color='white') +
scale_fill_gradient(high='Red', low= 'Blue')
#geom_text(aes(label=Province, x=long, y=lat))

试试这个来自 NOAA 的 shapefile。它拥有所有省份,但没有超精确的海岸线多边形(不需要):

library(rgdal)
library(ggplot2)
library(ggthemes)

url <- "http://www.nws.noaa.gov/geodata/catalog/national/data/province.zip"
fil <- basename(url)
if (!file.exists(fil)) download.file(url, fil)
fils <- grep("shp", unzip(fil), ignore.case=TRUE, value=TRUE)
ca <- readOGR(fils, ogrListLayers(fils)[1])

ca_map <- fortify(ca, region="NAME")

gg <- ggplot()
gg <- gg + geom_map(data=ca_map, map=ca_map,
                    aes(x=long, y=lat, map_id=id),
                    color="black", fill="white", size=0.15)
gg <- gg + coord_map("lambert", 44, 85)
gg <- gg + theme_map()
gg

一个system.time(ca_map <- fortify(ca, region="NAME"))显示:

##    user  system elapsed 
##   0.517   0.005   0.523 

对我来说非常一致。

评论太长了。

确实 ggplot 对于大 data.frames 来说很慢,但是当我下载你的 .rds 文件和 运行 你的代码时,fortify(...) 需要几秒钟,绘制地图大约需要 2 分钟。

您也可以使用 raster 包中的 getData(...) 直接获取 spatialPolygonsDataFrame,尽管奇怪的是这个文件只有您的一半大小 (50MB)。该文件绘制大约需要 1 分钟,其中一半转换为兰伯特投影(删除 coord_map(...) 调用,大约需要 25 秒)

library(ggplot2)
library(raster)   # for getData()

canada <- getData("GADM", country="CAN", level=1)
canada.df <- fortify(canada)
system.time(
  plot(ggplot()+
         geom_polygon(data=canada.df, aes(x=long, y=lat, group=group), 
                      fill="lightblue",color="grey20", size=0.15)+
         coord_map(projection="lambert", 44, 85))
)
#    user  system elapsed 
#   46.75    2.76   49.72 

不管怎样,ggplot肯定不会挂。

如果您能提供您的 orders.csv 文件,或许可以弄清楚发生了什么。