1. 曲面图
ggplot2暂不支持真正的三维曲面图,但内置了在二维平面上展示三维曲面的常见工具:等高线图、着色瓦片(colored tiles)以及气泡图。这些图形工作原理相近,只是第三维变量映射的图形属性有所不同
ggplot(faithfuld, aes(eruptions, waiting)) +
geom_contour(aes(z = density, color = ..level..))
ggplot(faithfuld, aes(eruptions, waiting)) +
geom_raster(aes(fill = density))
# 气泡图适用于观测点较少的情况
small <- faithfuld[seq(1, nrow(faithfuld), by = 10), ]
ggplot(small, aes(eruptions, waiting)) +
geom_point(aes(size = density), alpha = 1/3) +
scale_size_area()
2. 绘制地图
共有4类需要可视化的地图数据:矢量边界、点状元数据、区域元数据和光栅图
一般来说,这些数据的收集整合是绘制地图过程中的最大难点
1. 矢量边界
矢量边界数据通常为数据框格式,其中包含一个地理区域(如国家、州、县)的每个边界点数据
lat(latitude,纬度)和long(longitude,经度):表示边界点的坐标
group:每个毗邻区域的独特标记
id:记录一个地区的名称
区分group和id变量很要必要,因为一个地理单位形状未必是连续的多边形
比如由众多小岛构成的夏威夷,它的地图就不可能使用多边形绘制
使用ggplot::map_data()可以提取已有地图包中的数据,这些数据并不完全准确也不是最新的,不过用来入门的话很不错
mi_counties <- map_data("county", "michigan") %>%
select(lon = long, lat, group, id = subregion)
head(mi_counties)
可以使用geom_polygon()可视化矢量边界数据
ggplot(mi_counties, aes(lon, lat)) +
geom_polygon(aes(group = group)) +
coord_quickmap()
ggplot(mi_counties, aes(lon, lat)) +
geom_polygon(aes(group = group), fill = NA, color = "grey50") +
coord_quickmap()
请关注coord_quickmap()的使用:它可以对地图比例尺是否合适作出简易的判断
- USAboundaries包
- tigris包
- rnaturalearth包
- osmar包
- 地图数据集(.shp)
上述资源均会生成sp包定义下的空间数据框,可以通过fortify()作出转换
注意,以下代码可能已outdated,请跳到*处查看代码
library(USAboundaries)
c18 <- us_states("1820-01-01")
c18df <- fortify(c18)
head(c18df)
ggplot(c18df, aes(long, lat)) +
geom_polygon(aes(group = group), color = "grey50", fill = NA) +
coord_quickmap()
*
library(USAboundaries)
#?us_congressional to see other options
cong.map <- us_congressional(resolution = "high")
ggplot(cong.map) +
geom_sf()
cong.map <- filter(cong.map, state_name %in% state.name & !(state_name %in% c("Hawaii", "Alaska")))
ggplot(cong.map) +
geom_sf(color="black", fill="white") +
theme_void()
2. 点状元数据
点状元数据使用其它变量连接各个位点(由经纬度定义),比如下述代码提取密歇根州中最大的城市数据(2006年数据)
mi_cities <- maps::us.cities %>%
tbl_df() %>%
filter(country.etc == "MI") %>%
select(-country.etc, lon = long) %>%
arrange(desc(pop))
mi_cities
我们可以使用散点图展示这些数据,但需要一定解释说明才能让图像清晰有效。因此,我们通常需要在点状元数据上绘制另一图层
ggplot(mi_cities, aes(lon, lat)) +
geom_point(aes(size = pop)) +
scale_size_area() +
coord_quickmap()
ggplot(mi_cities, aes(lon, lat)) +
geom_polygon(aes(group = group), mi_counties,
fill = NA, color = "grey50") +
geom_point(aes(size = pop), color = "red") +
scale_size_area() +
coord_quickmap()
3. 光栅图
注意,以下代码可能已outdated,请跳到*处查看代码
如果你不需要在矢量边界图中进行解释说明,而只是绘制一幅传统地图,这就称为光栅图
绘制光栅图最简单的办法是使用ggmap包,它会从一系列包括OSM和谷歌地图的在线地图资源中提取数据。下载光栅图数据耗时通常较长,所以最好将他们存储维rds文件
if(file.exists("mi_raster.rds")){
mi_raster <- readRDS("mi_raster.rds")
}else{
bbox <- c(
min(mi_counties$lon), min(mi_counties$lat),
max(mi_counties$lon), max(mi_counties$lat)
)
mi_raster <- ggmap::get_openstreetmap(bbox, scale = 8735660)
saveRDS(mi_raster, "mi_raster.rds")
}
#(找到合适的scale变换通常需要大量实验,然后可以通过以下代码完成图像绘制)
ggmap::ggmap(mi_raster)
ggmap::ggmap(mi_raster) +
geom_point(aes(size = pop), mi_cities, color = "red") +
scale_size_area()
如果已经从raster包中获得了光栅图数据,可以通过以下代码将它转换为ggplot2支持的格式
df <- as.data.frame(raster::rasterToPoints(x))
names(df) <- c("lon", "lat", "x")
ggplot(df, aes(lon, lat)) +
geom_raster(aes(fill = x))
*
myMap <- get_map(location=bbox,
source="stamen", maptype="watercolor", crop=FALSE)
ggmap(myMap)
4. 区域元数据
有时元数据并不以点状呈现而是以区域表示。比如我们可以使用mi_census展示密歇根州各县人口普查数据
mi_census <- midwest %>%
tbl_df() %>%
filter(state == "MI") %>%
mutate(county = tolower(county)) %>%
select(county, area, poptotal, percwhite, percblack)
mi_census
我们不能直接把这类数据地图化,因为它没有提供空间数据,我们必须先将它与矢量边界数据合并。这会占用一定内存,但可以更清晰地看到绘图所使用地数据。此处使用dplyr::left_join()合并这两个数据集并绘制分级统计图
census_counties <- left_join(mi_census, mi_counties, by = c("county" = "id"))
census_counties
ggplot(census_counties, aes(lon, lat, group = county)) +
geom_polygon(aes(fill = poptotal)) +
coord_quickmap()
ggplot(census_counties, aes(lon, lat, group = county)) +
geom_polygon(aes(fill = percwhite)) +
coord_map()