reference:
How to plot a Taiwan Map colored with Population by ggplot2
R语言中国地图绘制 用R画中国地图并标注城市位置

library(maptools)
## Loading required package: sp
## Checking rgeos availability: FALSE
##      Note: when rgeos is not available, polygon geometry     computations in maptools depend on gpclib,
##      which has a restricted licence. It is disabled by default;
##      to enable gpclib, type gpclibPermit()
library(ggplot2)
library(plyr)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:plyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
setwd("f:/R-notes/plot_map/") #确定文件路径

china_map <-readShapePoly("bou2_4p.shp") # 读取地图空间数据
## Warning: readShapePoly is deprecated; use rgdal::readOGR or sf::st_read
china_map <- fortify(china_map) #转化为数据框
## Regions defined for each Polygons
#china_data<-read.csv("chinaprovincecity.csv") #读取省会城市坐标

ggplot()+
  
  geom_polygon(data=china_map, aes(x=long, y=lat, group=group),fill="grey95", colour="grey60",size=0.25)+ #中国地图
  
  #geom_point(data=china_data, aes(x = jd,y = wd),size=4,fill="black", alpha=1,shape=21, colour="white")+ #散点图
  
coord_map("polyconic") 

# + theme_nothing()#图表元素设定 这一行代码过时了

R语言绘制地图

library(maptools);
mapdata=readShapePoly('bou2_4p.shp')
## Warning: readShapePoly is deprecated; use rgdal::readOGR or sf::st_read
plot(mapdata);

我们往往会根据自己的需要对地图中的某些省份着以特定的颜色,这时就可以通过调节plot命令中的col参数来予以实现。然而为了清楚地说明这部分的内容,我需要插播一段R绘制地图的原理。 在绘制地图时,每一个省市自治区或者岛屿都是用一个多边形来表示的。之前的GIS数据,其实就是提供了每一个行政区其多边形逐点的坐标,然后R软件通过顺次连接这些坐标,就绘制出了一个多边形区域。在上面的数据中,一共包含了925个多边形的信息,之所以有这么多是因为一些省份有很多小的附属岛屿。在这925个多边形中,每一个都对应一个唯一的ID,编号分别从1到25。

实际上python中用basemap画地图也是这个原理.多边形的个数不一定是925个,应该是900+. 读取bou2_4p.shp文件,在默认情况下会把dbf文件的信息也读取进来.

plot命令中的fg参数在本例中应该是一个长度为925的向量,其第i个分量的取值就代表了地图中第i个多边形的颜色。一个简单的尝试是运行下面这个命令看看效果:

plot(mapdata,col=gray(924:0/924));

# mapdata[2]; # mapdata@data
# mapdata[2][1,]
1:6 %in% 0:10
## [1] TRUE TRUE TRUE TRUE TRUE TRUE
0:10 %in% 1:6
##  [1] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE
a = c(5,7,2,9)
ifelse(a %% 2 == 0,"even","odd")
## [1] "odd"  "odd"  "even" "odd"
x = 1:3
y = 2:4
print(x)
## [1] 1 2 3
print(y)
## [1] 2 3 4
which(x == y)
## integer(0)
x = c(1,3,4,5)
y = c(1,2,4,6)
print(x)
## [1] 1 3 4 5
print(y)
## [1] 1 2 4 6
which(x == y) # 返回相等元素的索引
## [1] 1 3

Embed this directly in the Rmarkdown script that contains the Chinese character comment(s): https://stackoverflow.com/questions/41717781/warning-input-string-not-available-in-this-locale

#Sys.setlocale('LC_ALL','C')
getColor=function(mapdata,provname,provcol,othercol){
  f = function(x,y) ifelse(x %in% y,which(y==x),0);
  # x是一个向量,y也是一个向量,如果x与y的对应位置的元素相同,则填充该元素在y中的索引,若不相同则记为0
  colIndex=sapply(mapdata@data$NAME,f,provname);
  #colIndex :925维的向量,不上色的地方对应的元素 存的是0,
  #上色的地方对应的元素 存的是要上的颜色的对应的索引,
  #注:索引从1开始
  color_vec=c(othercol,provcol)[colIndex+1];
  return(color_vec);
}

这一行比较难理解

 f = function(x,y) ifelse(x %in% y,which(y==x),0);

用python改写下

def f(x,y):
  """
  y == unique(y)
  """
  res = []
  for item in x:
    has_equal_num = False
    for idx,item_ in enumerate(y):
      if item_ == item:
        res.append(idx+1)
        has_equal_num = True
        break
    if not has_equal_num:
      res.append(0)

联想python中pandas的df.['列1']apply(f),对列中的每一行并行应用函数f()

f = function(x,y) ifelse(x %in% y,which(y==x),0);
sapply(mapdata@data$NAME,f,provname)

这两行配合起来,相当于对x的每个元素并行使用f函数,且参数y皆为provname,最后将每个函数调用返回的结果按顺序组装成向量

其中mapdata是存放地图数据的变量,在上面的例子中就是x,provname是需要改变颜色的地区的名称,provcol是对应于provname的代表颜色的向量(名称和数字均可),othercol是其它地区的颜色。举例如下:

othercol = 'white'
provcol=c("red","green","yellow","purple");
temp = c(othercol,provcol)
print(temp)
## [1] "white"  "red"    "green"  "yellow" "purple"
colIndex = c(0,2,3,1,4,0,0,0)
t = colIndex + 1
print(t)
## [1] 1 3 4 2 5 1 1 1
color_vec=c(othercol,provcol)[t];
print(color_vec)
## [1] "white"  "green"  "yellow" "red"    "purple" "white"  "white"  "white"

R语言中向量语法和python中numpy相当不一样,color_vec=c(othercol,provcol)[t]; 其实可以理解为

merge = othercol + provcol
color_vec = []
for idx in t:
  color_vec.append(merge[idx])
provname=c("北京市","天津市","上海市","重庆市");
provcol=c("red","green","yellow","purple");
plot(mapdata,col=getColor(mapdata,provname,provcol,"white"));

注意provname一定要写地区的全称,写法可以参照下面这条命令生成的向量:
as.character(na.omit(unique(mapdata@data$NAME)));

由此生成的向量有33个元素,少了澳门特别行政区,这是这个数据中的一块瑕疵。在x$att.data的第899行有一个NA,不知道它代表的是否就是澳门。

利用类似的方法就可以根据自己的需要对不同的区域进行着色,下面再举一例。从国家统计局获取2007年我国各地区的人口数据,然后根据人口的多少对各省份进行着色。程序如下:

provname=c("北京市","天津市","河北省","山西省","内蒙古自治区",
                "辽宁省","吉林省","黑龙江省","上海市","江苏省",
                "浙江省","安徽省","福建省","江西省","山东省",
                "河南省","湖北省","湖南省","广东省",
                "广西壮族自治区","海南省","重庆市","四川省","贵州省",
                "云南省","西藏自治区","陕西省","甘肃省","青海省",
                "宁夏回族自治区","新疆维吾尔自治区","台湾省",
                "香港特别行政区");
pop=c(1633,1115,6943,3393,2405,4298,2730,3824,1858,7625,
                5060,6118,3581,4368,9367,9360,5699,6355,9449,
                4768,845,2816,8127,3762,4514,284,3748,2617,
                552,610,2095,2296,693);
provcol=rgb(red=1-pop/max(pop)/2,green=1-pop/max(pop)/2,blue=0);
plot(mapdata,col=getColor(mapdata,provname,provcol,"white"),xlab="",ylab="");

局部
此外,在绘制地图的过程中,还有一个比较有用的参数是recs,它是一个由多边形ID组成的向量,表示在地图中只画出这些ID所代表的区域。利用这个参数,就可以画出某一部分的地图,例如下面的例子是我国中部六省的地图:

http://f.dataguru.cn/thread-330558-1-1.html(用R画中国地图并标注城市位置)

getID=function(mapdata,provname){
  index=mapdata@data$NAME %in% provname; # bool vector
  ids=rownames(mapdata@data[index,]); # rownames 返回行号的向量
  return(as.numeric(ids));
}


midchina=c("河南省","山西省","湖北省","安徽省","湖南省","江西省");
#plot(mapdata,recs=getID(mapdata,midchina),col="blue",ol="white",xlab="",ylab="");

新版本的maptools包的绘图函数已经取消了recs这个参数,替代方法如下:

midchina=c("河南省","山西省","湖北省","安徽省","湖南省","江西省");
plot(mapdata,col=getColor(mapdata,midchina,rep('blue',6),'white'),border="white",xlab="",ylab="")