用R软件绘制中国分省市地图

【注】新版本的maptools包对很多函数进行了修改,对于修改的内容,文章中用红色的文字进行了说明。

鉴于最近有不少人在讨论用R软件绘制地图的问题,我也就跟着凑了凑热闹,对相应的方法学习了一番。下面的这篇文章是一个初步的介绍,还有很多内容仍在学习和探索中,如果大家有什么意见或建议,我将根据自己学习的情况对文章进行进一步的补充。

在R中绘制地图其实是十分方便的,最直接的办法大概就是安装mapsmapdata这两个包,然后输入下面的命令:

library(maps)
library(mapdata)
map("china")

其中map()函数还可以加上很多参数,在这里就不一一详述,具体的用法只需问号之。然而仔细看一看这张地图你会发现重庆市和四川省仍然是浑然一体,可见该地图的数据应该是有些年头了。

幸运的是,通过谢益辉的这篇博文我们已经可以大体知道该如何操作了,下面就为大家介绍一下具体的步骤。

首先,从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf、bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下,并在R中设好相应的工作空间,然后安装maptools包,运行如下程序:

library(maptools);
x=read.shape('bou2_4p.shp');#下文中会继续用到x这个变量,
                            #如果你用的是其它的名称,
                            #请在下文的程序中也进行相应的改动。
plot(x);

【修改】新版本的maptools包不再提供read.shape()函数,请用readShapePoly()代替。

这时一张完整的中国地图就已经画好了。但是在实际使用的过程中,我们往往会根据自己的需要对地图中的某些省份着以特定的颜色,这时就可以通过调节plot命令中的fg参数来予以实现。然而为了清楚地说明这部分的内容,我需要插播一段R绘制地图的原理。

======================传说中的分割线=====================

在绘制地图时,每一个省市自治区或者岛屿都是用一个多边形来表示的。之前的GIS数据,其实就是提供了每一个行政区其多边形逐点的坐标,然后R软件通过顺次连接这些坐标,就绘制出了一个多边形区域。在上面的数据中,一共包含了925个多边形的信息,之所以有这么多是因为一些省份有很多小的附属岛屿。在这925个多边形中,每一个都对应一个唯一的ID,编号分别从1到925。

======================传说中的分割线=====================

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

plot(x,fg=gray(924:0/924));

【修改】新版本的maptools包的绘图参数也有所改变,请将fg换成col

于是自然就产生了一个问题:如何获取某一个特定地区的ID,进而设置我们想要的颜色?事实上,在变量x中,就已经存储了我们想要的信息。在R中输入“x[[2]]”或“x$att.data”,会得到一个925行7列的数据框,这其实是bou2_4p.dbf这个文件中存储的信息,之前的read.shape()函数虽然读取的是bou2_4p.shp文件,但在默认情况下会把dbf文件的信息也放到变量之中。对于这个数据框,其行名就是每一个区域的ID编号,第一列和第二列分别是面积和周长,最后一列是该区域所属的行政区名,其它的列应该也是一些编号性质的变量。于是,通过查找相应的行政区对应的行名,就可以对fg参数进行赋值了。下面是我编的一个函数,用来生成所需的fg向量:

getColor=function(mapdata,provname,provcol,othercol)
{
	f=function(x,y) ifelse(x %in% y,which(y==x),0);
	colIndex=sapply(mapdata$att.data$NAME,f,provname);
	fg=c(othercol,provcol)[colIndex+1];
	return(fg);
}

【修改】地图数据的组织形式有所变化,上面函数中的mapdata$att.data$NAME需要替换为mapdata@data$NAME

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

provname=c("北京市","天津市","上海市","重庆市");
provcol=c("red","green","yellow","purple");
plot(x,fg=getColor(x,provname,provcol,"white"));

map00

注意provname一定要写地区的全称,写法可以参照下面这条命令生成的向量:

as.character(na.omit(unique(x$att.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(x,fg=getColor(x,provname,provcol,"white"),xlab="",ylab="");

map01

其中颜色越深的地方代表人口数越多,反之为人口数越少。

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

getID=function(mapdata,provname)
{
	index=mapdata$att.data$NAME %in% provname;
	ids=rownames(mapdata$att.data[index,]);
	return(as.numeric(ids));
}
midchina=c("河南省","山西省","湖北省","安徽省","湖南省","江西省");
plot(x,recs=getID(x,midchina),fg="green",ol="white",xlab="",
		ylab="");

map02
上面的getID()是我编写的一个功能与getColor()类似的函数,用来返回指定省份的ID。

【修改】新版本的maptools包的绘图函数已经取消了recs这个参数,现在要实现这个功能,可以在颜色上把不需要的省份变成白色,其中填充色用col参数,边界颜色用border参数。例如上面的例子可以用下面的函数来实现:

plot(x, col = getColor(x, midchina, rep("green", 6),
    "white"), border = "white", xlab = "", ylab = "")

最后要说的是,在画出的图上仍然可以用points()函数和text()函数加上点和文字,而maptools包中还提供了一个pointLabel()函数,用来解决文本标签的重叠问题。这部分内容请参阅博文:用R画中国地图并标注城市位置,以及避免文本标签重叠:maptools中的pointLabel()

从以上的内容来看,本文所述的都是一些最基本的绘图方法,还没有对地理信息数据进行更进一步的分析。如果有机会的话,这一主题的下一篇文章将为大家介绍地图数据的组成结构,并说明如何将不同格式的地理数据整合起来,例如如何在上面的地图上绘制出我国的铁路、水系分布等内容。

用R软件绘制中国分省市地图》有183个想法

  1. 顶了,这篇文对空间统计分析很有用哈~
    如果可以对地图上的距离长度信息进行提取的话那么就更完美了!

  2. 假定地球为半径为R的球体,只要知道地图上两点的坐标(经纬度),就可以算出两点之间的大圆弧长,也就是最短距离。

  3. 太好了!我太喜欢了!!!!
    以前要做个报告想把中国地图放进去,然后把不同的省份运用不同的颜色表示出来简直就是一件非常让人头疼得事情。所以就扫描然后自己ps处理。可是遇到需要外文标注的时候就异常的痛苦!!所以这次总算有了解决的方案!
    多谢多谢!!

  4. 对不起,刚才一激动,感叹号居然超过了3个,犯了谢老大的版规。自我反省一下。

    “再激动感叹号也不要超过三个!!”

  5. 建议补充上澳门的数据,否则不好在学术或正式场合引用。

  6. 不错不错,以前我做的时候用了很麻烦的笨方法,现在好了,语句简化但用途更强大了:)

  7. 导入GIS数据后,发现省名在R里显示是乱码,请问应该如何解决? 谢谢!

  8. 我也遇到了与bo一样的问题。应该是语言设置的问题,当我读入x的时候发现:
    Shapefile type: Polygon, (5), # of Shapes: 925
    Warning message:
    use readShapeSpatial:
    objects other than Spatial objects defined in the sp package are deprecated

    之后也就没有办法对每个省的颜色进行改变!
    正在想法解决

  9. 我试着运行程序,提示

    > x<-read.shape('bou2_4p.shp');
    错误: 没有"read.shape"这个函数
    求解答,先谢了

    1. 新版本的maptools包把很多原来的函数都改掉了,如果你要用的话可能得重新读一下它的帮助。

    2. readShapePoly()函数。如x = readShapePoly('bou2_4p.shp')

      邱怡轩得更新正文了。我刚看了一下,新的函数读进来的数据的子元素直接就是NAME那一级的,原来的x$att.data$NAME就是现在的x$NAME,比如plot(x, col = rainbow(length(levels(x$NAME)))[as.integer(x$NAME)])

      1. 哈哈。太感谢了。终于成功了。我用的是2.10.1

  10. plot(x,fg=gray(924:0/924))
    错误于plot.window(xlim = xlim, ylim = ylim, asp = asp, …) :
    图形参数”fg”的长度不对

  11. 这个是怎么回事?

    > getID=function(mapdata,provname)
    + {
    + index=mapdata$att.data$NAME %in% provname;
    + ids=rownames(mapdata$att.data[index,]);
    + return(as.numeric(ids));
    + }
    > midchina=c(“河南省”,”山西省”,”湖北省”,”安徽省”,”湖南省”,”江西省”);
    > plot(x,recs=getID(x,midchina),col=”green”,ol=”white”,xlab=””,
    + ylab=””);
    警告多于50个(用warnings()来显示第一个到第五十个)
    >

    1. 新版本的maptools包改动很大,我已经把文章更新了一下,参见文中的红色部分。

    1. 什么意思?getColor()不是写在前面吗?只是需要把里面的mapdata$att.data$NAME改成mapdata@data$NAME

      1. getColor()按照要求修改了,但是还是显示“graphical parameter “fg” has the wrong length”。是什么原因?

  12. 有两个问题期待大家帮助:
    1、原文“首先,从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf、bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下,并在R中设好相应的工作空间,然后安装maptools包,运行如下程序:”
    请问“工作空间”指的是什么?如何设置?

    2、这个地图能精细到地级市级别吗?是不是在“mapdata”包里可以看到都有什么样的数据?可我找不到包的路径。

    1. 1、用R软件时可能经常要读取一些外部文件,引用这些文件有两种方式,一种是绝对路径,比如“C:/AAA.txt”,另一种就是把工作空间设在C:/,然后只要用相对路径“AAA.txt”就行了。说白了就是少写了一大串路径名。R中的函数是setwd()
      2、地图的精确度与数据有关,mapdata里自带了一些,如果要更精确的,可以到网上去搜GIS数据。要读取mapdata里的数据可以这样做:
      cnmapdata=map("china"),然后cnmapdata$xcnmapdata$y就分别是经度和维度了。

      1. 谢谢,弄明白了。
        那个工作空间,原来R for beginners里就有提到。

  13. Very good, very strong!

    跟着老师给的链接找过来的,非常有帮助,谢谢楼主

    ps:“如果有机会的话,这一主题的下一篇文章将为大家介绍地图数据的组成结构,并说明如何将不同格式的地理数据整合起来,例如如何在上面的地图上绘制出我国的铁路、水系分布等内容。” 这部分有帖子说明吗?

  14. 你好,你讲的这个方法很有用,但是能否绘一个省的带地市边界的图呢?
    比如用R绘广东省带地市边界的图?

    1. 你需要下载地市边界数据,我不知道国家基础地理信息中心是否提供这种细类数据下载,你自己可以去查看一下。画图的方法都是一样的,读入shp数据,然后plot()。

  15. 你好,我在国家基础地理信息中心上没找到这种数据,哪里有呢?

  16. 这个数据估计没有用,你绘了一个中国带省界图很漂亮,能否也绘一个省图带市县界的图呢

  17. 另外,数据包中(bou2_4l.dbf、bou2_4l.shp和bou2_4l.shx),的bout2_4l.shp为什么读不了呢?

    1. 应该是被删了,但可以从地图信息中提取,你试一下下面的代码,函数会返回一个列表,其中每一个元素是一个矩阵,第一列是多边形横坐标,第二列是多边形纵坐标。

      myMap2poly=function(mapdata)
      {
          lapply(x@polygons,function(x) x@Polygons[[1]]@coords);
      }
      mapPolygon=myMap2poly(x);
      hlj.x=mapPolygon[[1]][,1];
      hlj.y=mapPolygon[[1]][,2];
      plot(1,xlim=range(hlj.x),ylim=range(hlj.y),type="n");
      polygon(hlj.x,hlj.y);
      
      1. 我读进去SHP数据后,运行
        myMap2poly=function(mapdata)
        {
        lapply(x@polygons,function(x) x@Polygons[[1]]@coords);
        }
        mapPolygon=myMap2poly(x)
        出现错误提示Error in is.vector(X) : object ‘x’ not found
        是什么问题?

    2. 我犯糊涂了,应该把那个函数中的x改成mapdata,正确的函数应该是

      myMap2poly=function(mapdata)
      {
          lapply(mapdata@polygons,function(x) x@Polygons[[1]]@coords);
      }
  18. 在R中输入“x[[2]]”得到包含925个元素的数组
    [1] 68.489 129.933 84.905 41.186 38.379 76.781 44.874 8.498 0.088
    [10] 0.047 0.096 0.114 0.061 0.052 0.041 0.066 0.056 0.064
    用“x$att.data”得到NULL
    我用attributes(x)发现里边有乱码$data
    AREA PERIMETER BOU2_4M_ BOU2_4M_ID ADCODE93 ADCODE99 NAME
    0 54.447 68.489 2 23 230000 230000 ºÚÁú½­Ê¡
    1 129.113 129.933 3 15 150000 150000 ÄÚÃɹÅ×ÔÖÎÇø
    这些问题怎么解决?请指教

    1. maptools包进行改版后,数据结构也发生了变化,原来的x[[2]]x$att.data相当于现在的x@data。乱码问题应该是编码造成的,在我这里没问题,你再试试看。

      1. 我在加拿大放学一年,有个项目是关于加拿大北方森林物种特征时空变异的项目,需要把一些物种在加拿大地图上标记出来,并且预测30,60年后的分布情况,您在什么单位,能否单独联系您,我邮箱是liujs606@gmail.com

  19. 您好,现在我有两个问题,假如把各省份用不同颜色区分后,想加个图例,把每个颜色代表的身份用图例表示出来,怎么加?
    第二个问题,我如果有中国分省市地图的SHP数据,还有包括经纬度的样品数据,我可以把样品的分布在该地图上表示出来,根据这两个数据,能否把我样品数据中的各个记录按照省份归类?进而可以对每个省份的数据分布进行分析。

    不知道有没有表达明白我的问题,想上传两个图片,但是不知道这里怎么上传,期待您的答复

    1. 图例可以用legend()函数;第二个问题是不是相当于给定一个经纬度,然后判断它在哪个省?

      1. 请问:
        只用中国某省的地图,
        绘制某事件(可以以人口数为例)在该省各个地市的频数分布,
        这个的code该如何修改?
        谢谢!

      2. 基本上差不多,就是地图的数据,还有城市名称等地方需要更新。

      3. 请问我如何获取该省的地图数据?
        我不知道去哪里能够下载到数据.
        谢谢!

      4. 谢谢!

        在gadm中下载了china的shapefile压缩文件,
        解压后把后缀为.shp/.dbf及相应同名的SHX文件放入getwd()中,
        运行下面这段code,
        提示: 错误于colIndex + 1 : 二进列运算符中有非数值参数.

        是因为省名是汉字导致该错误?
        还是因为其他原因?
        请高手帮忙查看一下,
        谢谢!

        我初学R,
        又需要绘制一幅某省的各地市某事件频数分布地图.

        library(maps)
        library(mapdata)
        map(“china”)
        library(maptools)
        x=readShapePoly(“CHN_adm3.shp”)
        plot(x)
        plot(x,col=gray(924:0/924))
        #####全国地图中突出显示湖北
        getColor=function(mapdata,provname,provcol,othercol)
        {
        f=function(x,y) ifelse(x %in% y, which(y==x),0)
        colIndex=sapply(mapdata@data$NAME,f,provname)
        col=c(othercol,provcol)[colIndex+1]
        return(col)
        }

        provname=c(“湖北省”)
        provcol=c(“red”)
        plot(x,col=getColor(x,provname,provcol,”white”))
        错误于colIndex + 1 : 二进列运算符中有非数值参数

      5. 这个数据是包含了城市的,直接用原来的代码肯定不行。如果时间允许的话我想重新整理一篇地图绘制的文章,只是可能得等一段时间了。

      6. 哦,
        期待中…

        现在关键是不知道有城市的shapefile的3个文件转化成我需要的分布地图的思路,
        又是初学,
        所以不知从何下手.

      7. 最强悍的一点是它直接提供RData格式的数据,在R里load()一下就进去了。

  20. 第二个问题是,样品数据中有经纬度,关键是怎么能从GIS数据中分离出每个省的经纬度范围,您有没有好的建议?

  21. 用SAS试一下:
    data china2;
    length IDNAME $18;
    input ID IDNAME $;
    cards;
    1 安徽省
    22 北京市
    33 重庆市
    7 福建省
    15 甘肃省
    30 广东省
    16 广西壮族自治区
    18 贵州省
    31 海南省
    10 河北省
    8 黑龙江省
    9 河南省
    34 香港特别行政区
    12 湖北省
    11 湖南省
    4 江苏省
    3 江西省
    5 吉林省
    19 辽宁省
    35 澳门特别行政区
    20 内蒙古自治区
    21 宁夏回族自治区
    6 青海省
    26 陕西省
    25 山东省
    23 上海市
    24 山西省
    32 四川省
    36 台湾省
    28 天津市
    13 新疆维吾尔自治区
    14 西藏自治区
    29 云南省
    2 浙江省
    ;
    run;

    %annomac;
    %MAPLABEL (maps.china,china2,labelout,idname,id,font=simhei,color=crimson,size=2,hsys=3);

    proc gmap map=maps.china data=china2 all;
    id id;
    choro idname / nolegend levels=1 anno=labelout;
    run;quit;

  22. 不好意思,由于maptools程序包更改的太多,而且上文用到的GIS数据也有更新,所以,现在看您的博文有很多地方对应不上。
    您能按现在的GIS数据和maptools程序包重新更新一下内容吗?
    正在写论文,很急需这部分内容,查找了很多书,书上没有这部分。看您的文章有很大的提示,很感谢您。麻烦您按照现在的内容更新一下代码好吗,谢谢。

    1. 呃,关键的地方我已经用红色的文字重新修正了,不知道还有哪些地方需要更新?最好是能列出一个清单,我重新更新一下。

  23. 您好,非常不好意思麻烦您。
    由于maptools和Gis文件的更新都比较大,您可以重新更新一下博文吗?
    很着急学这部分内容,谢谢您了。

  24. 研究了一下数据结构:
    更新之后的maptools读入bou2_4p.shp之后,形成一个SpatialPolygonsDataFrame对象 (class(x)).这个对象有”data”,”polygons” , “plotOrder”,”bbox”,”proj4string”五个slot组成(slotNames(x)),如果想提取每个slot的数据可以通过x@slotname, slot(x,”slotname”)获得。

    每个slot中包含不同的内容
    data: 是一个data.frame, 包含925行,7列数据(”AREA” ,”PERIMETER” “BOU2_4M_”, “BOU2_4M_ID”, “ADCODE93″, “ADCODE99” , “NAME”),而最重要的各个省市的名称就在NAME这一列中。
    plotOrder,是一个长度925的vector

    bbox是一个2×2的矩阵,包含x,y值的最大和最小值

    proj4string 在该数据情况下没有值(NA)

    polygons: 它的情况比较复杂,本身是一个list, 长度925, 其中每个元素又为一个polygons对象,又有几层结构:
    $ :Formal class ‘Polygons’ [package “sp”] with 5 slots
    .. ..@ Polygons :List of 1
    .. .. ..$ :Formal class ‘Polygon’ [package “sp”] with 5 slots
    .. .. .. .. ..@ labpt : num [1:2] 114.3 22.2
    .. .. .. .. ..@ area : num 8.6e-06
    .. .. .. .. ..@ hole : logi FALSE
    .. .. .. .. ..@ ringDir: int 1
    .. .. .. .. ..@ coords : num [1:9, 1:2] 114 114 114 114 114 …
    .. ..@ plotOrder: int 1
    .. ..@ labpt : num [1:2] 114.3 22.2
    .. ..@ ID : chr “924”
    .. ..@ area : num 8.6e-06

    具体内容还没有彻底弄明白!

    现在这个数据的主要局限是没有办法在英文系统下使用,或者没有办法以各个省的拼音名称进行索引和赋值。所以我想 把NAME 部分的中文名称改为拼音(这个不难实现),之后不知道有谁知道如何把修改后的数据输出保存到一个新的shp文件中?或者把这个修改后的SpatialPolygonsDataFrame对象直接保存为data, 然后就可以在英文系统上操作了!
    请多帮忙!
    ps:留言时候的那个认证太难了,失败了几次才成!!

    1. 读写shapefile应该可以借助一些第三方的工具,我大概搜了一下,似乎有很多OpenGIS什么的开源软件,应该可以做到吧。

      1. 多谢!
        这个问题已经通过maptools包中的
        writePolyShape()搞定!

        此外,对于画某些特定省份的问题可以如下解决:
        plot(y[y$NAME%in%provname,],col=”green”,border=”black”)

  25. 请问用R能不能画出按四位数邮政编码分区的中国地图
    每一地区按照资料而有不同颜色

  26. 将这三个文件解压到同一个目录下?可以直接把这三个文件放在桌面上的文件夹里吗?还是要放在特定程序包里面?

    我用x=readShapePoly(‘bou2_4p.shp’),然后出来的结果是:Error in getinfo.shape(filen) : Error opening SHP file,求解答,先谢了

    1. 你应该是没有把R的工作目录设为文件所在的目录,见getwd()命令。

      1. 谢谢,果然有用了~ 我现在是把china-province-border-data.tar这个文件夹里的东西拷到R的bin(即getwd()所在文件)文件里了,是这样的意思吗?

      2. 我之前其实说得还不准确,getwd()是获取工作目录,事实上R是可以自己设定工作目录的,相应的命令是setwd(),里面加上三个文件所在的目录就行了,比如setwd("D:\\work"),表达反斜杠的时候要写两个。

  27. 有没有人知道某个省的各个区,甚至更小地理单位的GIS地图那里找得到?

  28. 请教老师:

    执行了

    > provname=c("北京市","天津市")
    > provcol=c("red","green")
    > plot(x,col=getColor(x,provname,provcol,"white"))

    但是提示错误: 类别为’closure’的对象不可以取子集

    为什么呢?

      1. 最大的问题是x@data结果的925行和33行name都完全乱码,可能是R识别不了中文所致? 用的MAC版本.谢谢!

  29. 对SpatialPolygonsDataFrame这个东西搞不懂。希望有更多参考资料。

  30. getColor这个函数是不是也不行了?
    我试了着色不上了……

    1. 需要做些修改
      colIndex=sapply(mapdata$att.data$NAME,f,provname);
      改成
      colIndex=sapply(mapdata$NAME,f,provname);

  31. 我们用GIS做,但是美中不足,就是总是画不出美丽的画。这是天赋问题么

  32. 以前曾经画过这类图,没有用上述统计包,具体思路是这样的:
    (1)准备要画的底图,用别的计算机语言编程(或许R语言也有类似的包吧),提取出需要的底图区域的像素值,并保存到数据库中;
    (2)在R中,按照提取的底图的比例建立绘图区(如果比例不一致,可能会变形),读取数据库中保存的像素值并绘制出来;
    (3)在底图上绘制需要的图形。
    这样不仅可以画分省的,还可以画一个市的、一个县的。。。随你怎么画。

  33. 我想问一下地图绘制出来之后希望添加一个colorbar用以表示不同的数值,如何添加?谢谢!

  34. 请问能不能在部分省份上标注该省的环境信息如:海拔、年平均气温、年均降水量、年平均光照强度、水质溶氧量、PH值、平均水温、河床比降、水流速、矿化度、硬度等信息,我要做一个物种在各省的分布情况及该省的环境参数,该怎么实现,谢谢

  35. 非常感谢这篇文章!如果数据更多,比如在一个excel表格里,如何把这个excel和R的地图功能联系在一起,划出这种类似你文章里人口的density 图呢?谢了

  36. 这个软件可以自己画一个局部的地图吗(比如一个县)?可以自己添加城市吗?

  37. 对于我这种似懂非懂的人来说,写得太详细了。
    太好了,非常感谢。

  38. i was going to use it to get Australian map, somehow there is no maptools in my latest version R. can anyone please offer me some help?

    cheers.
    tilly

    1. 1. Do you have the shapefile(*.shp) of Australian map?
      2. Have you installed maptools package in R? Try install.packages("maptools")?

      1. hi, 邱怡轩,
        Yes, i have, i have successfully loaded shx file of Australian map:

        > getColor=function(mapdata,provname,provcol,othercol)
        + {
        +     f=function(x,y) ifelse(x %in% y,which(y==x),0);
        +     colIndex=sapply(mapdata$att.data$NAME,f,provname);
        +     col=c(othercol,provcol)[colIndex+1];
        +     return(col);
        + }
        > 
        > 
        > provname=c("Canberra")
        > provcol=c("red")
        > plot(ozDATA,col=getColor(ozDATA,provname,provcol,"White"))
        Error in colIndex + 1 : non-numeric argument to binary operator
        

        see the Error msg above, why is that?

    2. As I mentioned in the article, some functions have been changed with the new version of maptools package, and your code should be modified as

      > getColor=function(mapdata,provname,provcol,othercol)
      + {
      +     f=function(x,y) ifelse(x %in% y,which(y==x),0);
      +     colIndex=sapply(mapdata@data$NAME,f,provname);
      +     col=c(othercol,provcol)[colIndex+1];
      +     return(col);
      + }
      > provname=c("Canberra")
      > provcol=c("red")
      > plot(ozDATA,col=getColor(ozDATA,provname,provcol,"White"))
      

      Hope this works for you.

      1. hi, 邱怡轩,

        after ran second slot, below is the error msg i have got.

        Error: unexpected ‘}’ in:
        ” + return(col);
        + }”

        Sorry for being a pain.

        Cheers,
        Tilly

  39. (bou2_4p.dbf、bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下,并在R中设好相应的工作空间

    你好 我还是不明白这个是怎么设相应工作空间 你能说下具体的位置吗
    谢谢

  40. 请教两个问题:
    1.如何在省界的地图中加上地级市的边界。我能分别画出有省界的地图,和地级市界的线,但是不知到怎么重叠在一起,并对部分城市着色

    2. 如何解决在ubuntu下地图信息文件中,中文的省名不能识别乱码? 我在win7不用设置GB2312就可以识别中文省名,但在ubuntu11.10下即使设置GB2312还是不能正常显示

    1. 对于中文显示问题,暂时找到一个方法
      将getColor函数稍作修改:colIndex=sapply(chinamap@data$NAME,f,cityname); 改为colIndex=sapply(iconv(chinamap@data$NAME,from=”CP936″, to=”UTF-8″),f,cityname);
      这样可以暂时显示中文省名并着色

  41. 向您请教一个问题:我想在这幅地图上标上省名,位置尽量不重合,省名是我自己写的(北京,天津,而不是文件中的“北京市”,”天津市”),请问怎么做呢?

  42. getColor=function(mapdata,provname,provcol,othercol)
    + {
    + f=function(x,z)
    + ifelse(x%in%z,which(z==x),0)
    + colIndex=sapply(mapdata@data$NAME,f,provname)
    + col=c(othercol,provcol)[colIndex+1]
    + return(col)
    + }
    > provname=(“武汉市”)
    > provcol=(“blue”)
    > plot(x,col=getColor(x,provname,provcol,”white”))
    错误于colIndex + 1 : 二进列运算符中有非数值参数
    > provname=c(“北京市”,”天津市”,”上海市”,”重庆市”);
    > provcol=c(“red”,”green”,”yellow”,”purple”);
    > plot(x,fg=getColor(x,provname,provcol,”white”));
    错误于colIndex + 1 : 二进列运算符中有非数值参数
    >
    老师。这个错误是为什么呢?求解答。
    等待您的回复。

    1. 这个地图是用省边界绘制的,武汉市应该画不出来,网上有市边界的数据包。
      plot(x,fg=getColor(x,provname,provcol,”white”));
      应该是plot(x,col=getColor(x,provname,provcol,”white”))吧,fg改为col试试~

  43. 这个中国地图能用ggplot2画吗?貌似x的对象类型很难转化成数据框

  44. 非常感谢这个共享。另外请教一个问题,如果我需要对省份除了填充颜色外,还要填充斜线(有些地方只能打印黑白色,颜色没法区分),那么要怎样做呢,期待您的回复。

  45. x=readShapePoly("bou2_4p.shp")
    错误: 没有"readShapePoly"这个函数
    求解答

  46. Hi, 邱怡轩,我在linux环境下,打开x@data可以看到NAME列为乱码,所以给直辖市填充颜色时匹配肯定不成功,就更不能填充相应的颜色了。后来我到windows下测试,发现可以。想问问linux下怎样才能跑起来,主要是如何解决这个编码问题。

  47. 大神,请问我用gpclib包时,发生了如下问题,该怎么办呢?
    load("C:\Program Files\R\CHN_adm1.RData")
    > gpclibPermit()
    FALSE
    china.map <- fortify(gadm,region=’ID_1′)
    错误: 不是所有的isTRUE(gpclibPermitStatus())都是TRUE
    vals <- data.frame(id =unique(china.map$id),val=water)
    错误于unique(china.map$id) : 找不到对象’china.map’

  48. x = readShapePloy(‘bou2_4p.shp’)
    错误: 没有"readShapePloy"这个函数

    怎么解决呢?

  49. city=readShapePoly(‘F:\gis\city.shp’)
    plot(city)

    > getColor=function(mapdata,provname,provcol,othercol)
    {
    f=function(x,y) ifelse(x %in% y,which(y==x),0);
    colIndex=sapply(mapdata@data$NAME_2,f,provname);
    col=c(othercol,provcol)[colIndex+1];
    return(col);
    }
    provname=c("Jinghua","Ningbo")
    provcol=c("red","green")
    plot(x,col=getColor(x,provname,provcol,"white"))
    错误于colIndex + 1 : 二进列运算符中有非数值参数
    我把这个代码 改变后用在自己数据上 怎么出这个错误啊。。r代码小白 求指导
    我估摸着 是因为我的shp数据 属性是英文的,这个代码怎么改才能适合英文啊

  50. city=readShapePoly(‘F:\gis\city.shp’)
    plot(city)

    > getColor=function(mapdata,provname,provcol,othercol)
    {
    f=function(x,y) ifelse(x %in% y,which(y==x),0);
    colIndex=sapply(mapdata@data$NAME_2,f,provname);
    col=c(othercol,provcol)[colIndex+1];
    return(col);
    }
    provname=c("Jinghua","Ningbo")
    provcol=c("red","green")
    plot(x,col=getColor(x,provname,provcol,"white"))
    错误于colIndex + 1 : 二进列运算符中有非数值参数
    我把这个代码 改变后用在自己数据上 怎么出这个错误啊。。r代码小白 求指导
    我估摸着 是因为我的shp数据 属性是英文的,这个代码怎么改才能适合英文啊, 求助啊 在线等。你改的那个英文解决了么 。。。ps 我懂shp 那是我们专业一种数据类型

    1. 这段代码只适用于当时的那个数据……你要不看下你的x@data$NAME_2是什么?当然也可能你的数据把城市名存储在了其他的地方。

  51. Hi Yixuan,
    我按照您的介绍输入,可是显示:
    package ‘maptools’ successfully unpacked and MD5 sums checked
    > library(maptools)
    Error: package ‘sp’ required by ‘maptools’ could not be found
    > plot(x,fg=gray(924:0/924));
    Error in plot(x, fg = gray(924:0/924)) : object ‘x’ not found
    试着重新从CRAN下载了maptools package,但是仍然没有“sp”。怎么解决呢?

  52. 在划分重庆市和四川省的时候也是找不到“sp”:
    > utils:::menuInstallLocal()
    package ‘maptools’ successfully unpacked and MD5 sums checked
    > library(maptools);
    Error: package ‘sp’ required by ‘maptools’ could not be found
    > x=read.shapePoly(‘bou2_4p.shp’);
    Error: could not find function "read.shapePoly"
    > plot(x);
    Error in plot(x) : object ‘x’ not found
    是不是maptools package又有变化?求助^^~

  53. 老师你好,这个数据画出来是一些破碎的线条,这是怎么回事啊

  54. levels(china.map$NAME) <- iconv(levels(china.map$NAME),"gb2312","utf-8")转换编码

  55. 还是搞不定“乱码”的小伙伴看过来
    rm(list=ls())
    library(maptools)
    setwd("/Users/YUE/Documents/study/econ/2nd year/demo2/Empirical_Examples_/0415/china-province-border-data")
    x=readShapePoly("bou2_4p.shp")
    plot(x)
    as.character(na.omit(unique(x$NAME)))
    #################我是分割线#######################################
    ###这时候会输出一大堆数字########

    # "351273221351276231346261237347234201"
    # #”3452062053502222313452172443502072523462622733452142#72"
    # #”3462262603472262063472732643452202763452602243502072#52346262273345214272"
    # "345220211346236227347234201"
    # "350276275345256201347234201"
    # "347224230350202203347234201"
    # "346262263345214227347234201"
    # "345214227344272254345270202"
    # "345261261350245277347234201"
    #[10] "345244251346264245345270202"
    #[11] "351231225350245277347234201"
    #[12] #”3452562013452442173452332363462272173502072523462622#73345214272"
    #[13] "351235222346265267347234201"
    #[14] "345261261344270234347234201"
    #[15] "350245277350227217350207252346262273345214272"
    #[16] "346262263345215227347234201"
    #[17] "346261237350213217347234201"
    #[18] "345256211345276275347234201"
    #[19] "345233233345267235347234201"
    #[20] "346271226345214227347234201"
    #[21] "351207215345272206345270202"
    # "344270212346265267345270202"
    #[23] "346265231346261237347234201"
    #[24] "346271226345215227347234201"
    #[25] "346261237350245277347234201"
    #[26] "344272221345215227347234201"
    #[27] "350264265345267236347234201"
    #[28] "347246217345273272347234201"
    #[29] #”3452712773502452773452432563462272173502072523462622#73345214272"
    #[30] "345217260346271276347234201"
    #[31] "345271277344270234347234201"
    #[32] #”3512462313462702573472112713452102533502412143462242#77345214272"
    #[33] "346265267345215227347234201"
    ####之前参考一个修改乱码的办法调出了各省市的CODE,惊异地(笨拙地)发现原来数字和城市是一一对应的。先给出查看方法:
    ################分割线(此部分不影响主题代码可以越过)##########3
    levels<-iconv(levels(x$NAME),"gb2312","utf-8”)#解决乱码使得其与中文一一对应#
    getColor=function(mapdata,provname,provcol,othercol){f=function(x,y) ifelse(x %in% y, which(y==x),0); colIndex=sapply(levels, to="UTF-8"),f,provname);col=c(othercol,provcol)[colIndex+1];return(col)}#重新定义getColor#
    provname=c("北京市","天津市","河北省","山西省","内蒙古自治区",
    "辽宁省","吉林省","黑龙江省","上海市","江苏省",
    "浙江省","安徽省","福建省","江西省","山东省",
    "河南省","湖北省","湖南省","广东省",
    "广西壮族自治区","海南省","重庆市","四川省","贵州省",
    "云南省","西藏自治区","陕西省","甘肃省","青海省",
    "宁夏回族自治区","新疆维吾尔自治区","台湾省",
    "香港特别行政区”)#查阅乱码对应的省市#

    # "345214227344272254345270202"
    # "345244251346264245345270202"
    # "346262263345214227347234201"
    # "345261261350245277347234201"
    # #”3452062053502222313452172443502072523462622733
    #45214272"
    # "350276275345256201347234201"
    # "345220211346236227347234201"
    # "351273221351276231346261237347234201"
    # "344270212346265267345270202"
    #[10] "346261237350213217347234201"
    #[11] "346265231346261237347234201"
    #[12] "345256211345276275347234201"
    #[13] "347246217345273272347234201"
    #[14] "346261237350245277347234201"
    #[15] "345261261344270234347234201"
    #[16] "346262263345215227347234201"
    #[17] "346271226345214227347234201"
    #[18] "346271226345215227347234201"
    #[19] "345271277344270234347234201"
    #[20] #”3452712773502452773452432563462272173502072523#46262273345214272"
    #[21] "346265267345215227347234201"
    # "351207215345272206345270202"
    #[23] "345233233345267235347234201"
    #[24] "350264265345267236347234201"
    #[25] "344272221345215227347234201"
    #[26] #”350245277350227217350207252346262273345214272"
    #[27] "351231225350245277347234201"
    #[28] "347224230350202203347234201"
    #[29] "351235222346265267347234201"
    #[30] #”3452562013452442173452332363462272173502072523#46262273345214272"
    #[31] #”3462262603472262063472732643452202763452602243#50207252346262273345214272"
    #[32] "345217260346271276347234201"
    #[33] #”3512462313462702573472112713452102533502412143#46224277345214272"#
    #######################分割线#############
    ###看出来,两组数字每组一个三位数代表一个汉字,比如234201代表省。#
    #########################################################
    ##然后我采用笨方法,还是把代码当成名字运行画图,举例##
    getColor=function(mapdata,provname,provcol,othercol){f=function(x,y) ifelse(x %in% y, which(y==x),0); colIndex=sapply(mapdata@data$NAME,f,provname);col=c(othercol,provcol)[colIndex+1];return(col);}
    provname=c("272243304317312241”)#海南省#
    provcol=c("red")
    plot(x,col=getColor(x,provname,provcol,"white"))

    #######被小乱码烦了一天终于在前辈牛人的各种语句下搞出了图,如果是MAC的同##学真的想转换拼音,可以下载QGIS,然后添加矢量图层,添加SHP文件,右键#####切换编辑状态修改NAME(跑题了)。最后还是特别感谢前辈的文件分享###

    1. 看出来,两组数字每组一个三位数代表一个汉字,比如234201代表省。
      这个地方有误,是三组数字每组一个三位数代表一个汉字,如347234201代表省

    2. ## 这样似乎更简便些
      levels<-iconv(levels(x$NAME),"gb2312","utf-8")
      levels(x$NAME)<-levels

  56. 你好,我从gadm那下载了RData格式数据,用load("CHN_adm0.RData")导入,发现是空白的,能请教是什么问题吗?

  57. 你好,我也遇到同样问题,想要把NAME项转化成英语,能具体说下怎么用 writePolyShpe()完成这一项吗?

  58. 还是有些Bug,待整理
    provname=c("北京市","天津市","上海市","重庆市");
    > provcol=c("red","green","yellow","purple");
    > plot(x,fg=getColor(x,provname,provcol,"white"));
    错误于plot.window(xlim = xlim, ylim = ylim, asp = asp, …) :
    图形参数"fg"的长度不对

  59. 请问R能不能把部分省市用斜杠,部分省市横线之类区分啊,意思就是不用颜色区分不同类别的省市,谢谢

  60. “首先,从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf、bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下,并在R中设好相应的工作空间,”我想问怎么算是在R中设好相应的工作空间啊?我在运行的时候出现“Error in getinfo.shape(filen) : Error opening SHP file”,是不是我把这三个文件解压的位置不对啊?谢谢

  61. getColor=function(mapdata,provname,provcol,othercol)
    {
    f=function(x,y) ifelse(x %in% y,which(y==x),0);
    colIndex=sapply(mapdata@data$NAME,f,provname);
    col=c(othercol,provcol)[colIndex+1];
    return(col);
    }

    provname=c(“北京市”,”天津市”,”上海市”,”重庆市”);
    provcol=c(“red”,”green”,”yellow”,”purple”);
    plot(x,col=getColor(x,provname,provcol,”white”));

    为什么按照这个命令运行,结果四个直辖市的颜色显示不出来呢?

    1. fengliwubi,
      你好,我和你运行的code一样,结果四个直辖市的颜色也是显示不出来,不知道是什么原因,你后来解决了吗?

      1. 我解决了,应该是数据的编码问题,你输入的“北京市”“上海市”等省市信息和mapdata中的省市信息编码不一致,所以你getColor函数返回的全部都是white

  62. 我也是,用的老师提供的完全一样的代码,但是显示不出颜色

    getColor=function(mapdata,provname,provcol,othercol)
    {
    f=function(x,y) ifelse(x %in% y,which(y==x),0);
    colIndex=sapply(mapdata@data$NAME,f,provname);
    col=c(othercol,provcol)[colIndex+1];
    return(col);
    }

    provname=c(“北京市”,”12″,”上海市”,”重庆市”);
    provcol=c(“red”,”green”,”yellow”,”purple”);
    plot(x,col=getColor(x,provname,provcol,”white”));

    1. 我遇到了同样的问题,x@data$NAME显示的是乱码,发现是系统使用了英文的,导致R默认英文,不识别省份汉字,修改下默认语言就好了。

  63. 好多函数或者对象的属性都变啦,这篇文章是不是该更新一下…不然新手完全画不出来

  64. 大感谢。。但画中国的人这么多,有没有更完善一点的package呢?每次都要从外部加载GIS再读成图,好麻烦。。。

  65. 那个数据包好像不能用了,
    错误: 復原文件幻数出错(文件可能有损坏)– 没有载入任何数据

  66. 刚学习R的新手,想问一下,如果想画中国地图,可以通过选择不同的图例,在地图上显示图例对应的省份, 这种动态的图如何实现?求解

  67. 你好,想要请教以下如果在下载的底图中,其中一个城市的一条边界时缺失的,应该如何修正呢?期待您的回复。

  68. getColor=function(mapdata,provname,provcol,othercol)
    {
    f=function(x,y) return(ifelse(x %in% y,which(y==x),0));
    colIndex=sapply(mapdata$att.data$NAME,f,provname);
    fg=c(othercol,provcol)[colIndex+1];
    return(fg);
    }
    学习中,发现没有f函数,没有return是不行的。

    1. 哦对了,mapdata@data$NAME复制的时候忘记修改了。前面没有显示颜色的,估计是f函数没有return的缘故吧

  69. getColor=function(mapdata,provname,provcol,othercol)
    {
    f=function(x,y) ifelse(x %in% y,which(y==x),0);
    colIndex=sapply(mapdata@data$NAME,f,provname);
    col=c(othercol,provcol)[colIndex+1];
    return(col);
    }

    provname=c(“北京市”,”12″,”上海市”,”重庆市”);
    provcol=c(“red”,”green”,”yellow”,”purple”);
    plot(x,col=getColor(x,provname,provcol,”white”));
    新手使用,就是卡到这一点,显示不出几个地方的颜色

  70. 关于如何解决省份中文乱码的问题,可以试试这个办法:

    run代码:system(“defaults write org.R-project.R force.LANG en_US.UTF-8”) ;重启R。

    我用的是Mac,完美解决中文乱码的问题。
    详细请看这里:https://ozh2014.wordpress.com/2017/01/09/让r读取中文数据/

  71. 我想问问“”从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf、bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下,并在R中设好相应的工作空间,然后安装maptools包,运行如下程序:“”

    我下载了,解压了,但是不知道怎样设好R相应的工作空间?我尝试几次都是不成功?求具体一点指导

    1. 用绝对地址,就是你放的路径就可以,类似这样:readShapePoly(“D:/地图/bou2_4p.shp”)

  72. > setwd(‘F:\Program Files\R\R-3.4.0\bin\china-province-border-data’);
    > library(maptools);
    > x=readShapePoly(‘bou2_4p.shp’);
    Error in getinfo.shape(filen) : Error opening SHP file
    此外: Warning message:
    use rgdal::readOGR or sf::st_read
    > plot(x);
    这样该怎么做??

  73. 为什么标注中国地图时,只显示了乌鲁木齐、呼和浩特、澳门?

发表评论

邮箱地址不会被公开。 必填项已用*标注