如何将条形图绘制到ggplot2地图上 [英] How to plot barchart onto ggplot2 map

查看:253
本文介绍了如何将条形图绘制到ggplot2地图上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了类似于这个问题的类似答案,但其中大多数都使用包 rworldmap ggmap ggsubplot geom_subplot2d 。请参阅



让我们为barlotots生成数据。

  set.seed(1)
geo_data< - data.frame(who = rep(c(1:length(map.kt $ OBJECTID)),每个= 2),
值= as.numeric(样本(1:100,长度(map.kt $ OBJECTID)* 2,replace = T)),
id = rep(c(1:长度(map.kt $ OBJECTID)),2))

现在制作47个应该绘制的条形图在稍后的中心点。

  bar.testplot_list < -  
lapply(1:length(map.kt $ OBJECTID),function(i ){
gt_plot< - ggplotGrob(
ggplot(geo_data [geo_data $ id == i,])+
geom_bar(aes(factor(id),value,group = who),填充=彩虹(length(map.kt $ OBJECTID))[i],
position ='dodge',stat ='identity',color =black)+
labs(x = NULL, y = NULL)+
theme(legend.position =none,rect = element_blank(),
line = element_blank(),text = element_blank())

panel_coords< - gt_plot $ layout [gt_plot $ layout $ name ==panel,]
gt_plot [panel_coords $ t:panel_coords $ b,panel_coords $ l:panel_coords $ r]
})

这里我们将 ggplot s转换为 gtable s,然后裁剪它们以仅包含每个barplot的面板。您可以修改此代码以保持缩放比例,添加图例,标题等。

借助 annotation_custom,我们可以将这些条形图添加到初始映射中

  bar_annotation_list<  -  lapply(1:length(map.kt $ OBJECTID),function (i)
annotation_custom(bar.testplot_list [[i]],
xmin = map.test.centroids $ x [map.test.centroids $ OBJECTID == as.character(map.kt $ OBJECTID [i])] - 5e3,
xmax = map.test.centroids $ x [map.test.centroids $ OBJECTID == as.character(map.kt $ OBJECTID [i])] + 5e3,
ymin = map.test.centroids $ y [map.test.centroids $ OBJECTID == as.character(map.kt $ OBJECTID [i])] - 5e3,
ymax = map.test.centroids $ y [map.test.centroids $ OBJECTID == as.character(map.kt $ OBJECTID [i])] + 5e3))

result_plot< - Reduce(`+`,bar_annotation_list,map .test)


I have found similar answers to questions like this one, but most of them are using packages rworldmap, ggmap, ggsubplot or geom_subplot2d. See for example here or here.

I'd like to know how I can plot other ggplot-objects such as a bar-chart onto a map, that is created from a shapefile. The one I'm using can be downloaded here.

EDIT

As @beetroot correctly pointed out, the new file which can be downloaded under the link posted above has changed significantly. Therefore the names of the shapefile etc. are adjusted.

library(rgdal)
library(ggplot2)
library(rgeos)
library(maptools)

map.det<- readOGR(dsn="<path to your directory>/swissBOUNDARIES3D100216/swissBOUNDARIES3D/V200/SHAPEFILE_LV03", layer="VECTOR200_KANTONSGEBIET")
map.kt <- map.det[map.det@data$KANTONSNUM=="CH01000000"|map.det@data$KANTONSNUM=="CH19000000",]


#get centroids
map.test.centroids <- gCentroid(map.kt, byid=T)
map.test.centroids <- as.data.frame(map.test.centroids)
map.test.centroids$KANTONSNR <- row.names(map.test.centroids)

#create df for ggplot
kt_geom <- fortify(map.kt, region="KANTONSNUM")

#Plot map
map.test <- ggplot(NULL)+
        geom_polygon(data=kt_geom, aes(long, lat, group=group), fill="white")+
        coord_fixed()+
        geom_path(data=kt_geom, color="gray48", mapping=aes(long, lat, group=group), size=0.2)+
        geom_point(data=map.test.centroids, aes(x=x, y=y), size=9, alpha=6/10)

mapp

This results in such a map. So far so good.

However, I'm having difficulties combining two plots such as the map map.test and, for example, this one:

geo_data <- data.frame(who=rep(c(1:2), each=2),
                   value=as.numeric(sample(1:100, 4, replace=T)),
                   KANTONSNR=rep(c(1,19), 2))

bar.testplot <- ggplot()+
     geom_bar(data=geo_data, aes(factor(id),value,group=who),position='dodge',stat='identity')

The barcharts should lie at the center of the two polygons, i.e. where the two points are. I could produce the barcharts and plot them onto the map separately, if that makes things easier.

解决方案

I've modified a little your code to make the example more illustrative. I'm plotting not only 2 kantons, but 47.

library(rgdal)
library(ggplot2)
library(rgeos)
library(maptools)
library(grid)
library(gridExtra)

map.det<- readOGR(dsn="c:/swissBOUNDARIES3D/V200/SHAPEFILE_LV03", layer="VECTOR200_KANTONSGEBIET")
map.kt <- map.det[map.det$ICC=="CH" & (map.det$OBJECTID %in% c(1:73)),]

# Merge polygons by ID
map.test <- unionSpatialPolygons(map.kt, map.kt@data$OBJECTID)

#get centroids
map.test.centroids <- gCentroid(map.test, byid=T)
map.test.centroids <- as.data.frame(map.test.centroids)
map.test.centroids$OBJECTID <- row.names(map.test.centroids)

#create df for ggplot
kt_geom <- fortify(map.kt, region="OBJECTID")

#Plot map
map.test <- ggplot(kt_geom)+
  geom_polygon(aes(long, lat, group=group), fill="white")+
  coord_fixed()+
  geom_path(color="gray48", mapping=aes(long, lat, group=group), size=0.2)+
  geom_point(data=map.test.centroids, aes(x=x, y=y), size=2, alpha=6/10)

map.test

Let's generate data for barplots.

set.seed(1)
geo_data <- data.frame(who=rep(c(1:length(map.kt$OBJECTID)), each=2),
                       value=as.numeric(sample(1:100, length(map.kt$OBJECTID)*2, replace=T)),
                       id=rep(c(1:length(map.kt$OBJECTID)), 2))

Now making 47 barplots which should be plotted at center-points later.

bar.testplot_list <- 
  lapply(1:length(map.kt$OBJECTID), function(i) { 
    gt_plot <- ggplotGrob(
      ggplot(geo_data[geo_data$id == i,])+
        geom_bar(aes(factor(id),value,group=who), fill = rainbow(length(map.kt$OBJECTID))[i],
                 position='dodge',stat='identity', color = "black") +
        labs(x = NULL, y = NULL) + 
        theme(legend.position = "none", rect = element_blank(),
              line = element_blank(), text = element_blank()) 
    )
    panel_coords <- gt_plot$layout[gt_plot$layout$name == "panel",]
    gt_plot[panel_coords$t:panel_coords$b, panel_coords$l:panel_coords$r]
    })

Here we convert ggplots into gtables and then crop them to have only panels of each barplot. You may modify this code to keep scales, add legend, title etc.

We can add this barplots to the initial map with the help of annotation_custom.

bar_annotation_list <- lapply(1:length(map.kt$OBJECTID), function(i) 
  annotation_custom(bar.testplot_list[[i]], 
                    xmin = map.test.centroids$x[map.test.centroids$OBJECTID == as.character(map.kt$OBJECTID[i])] - 5e3,
                    xmax = map.test.centroids$x[map.test.centroids$OBJECTID == as.character(map.kt$OBJECTID[i])] + 5e3,
                    ymin = map.test.centroids$y[map.test.centroids$OBJECTID == as.character(map.kt$OBJECTID[i])] - 5e3,
                    ymax = map.test.centroids$y[map.test.centroids$OBJECTID == as.character(map.kt$OBJECTID[i])] + 5e3) )

result_plot <- Reduce(`+`, bar_annotation_list, map.test)

这篇关于如何将条形图绘制到ggplot2地图上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆