N久不分享学习心得的小Q终于有时间冒个泡了,这次分享一个小Q改良后的在地图上任意画饼图,直方图的R代码(其实是摸清了数据结构后自己多加了几行代码+),这里以饼图为例。
画图原理
1.利用R包rworldmap & rworldxtra来作图。
2.已有的map数据中一个国家对应一个坐标,一个国家边界,利用这些已有数据+用户数据构建新的画图数据(其他新添加的图均是如此)。
rworldmap包的介绍
1.如果想查看rworldmap包的情况
help(package="rworldmap")
2.了解high resolution map情况
a<-getMap(resolution = "high")
# Map是一个sp对象,SpatialLinesDataFrame类
# 结构如下:
# a@data
# a@polygons
# a@plotOrder
# a@bbox
# a@proj4string
# 我们主要利用a@data和a@polygons
v<-a@data
colnames(v)
[1] "ne_10m_adm" "ScaleRank"
[3] "LabelRank" "FeatureCla"
[5] "OID_" "SOVEREIGNT"
[7] "SOV_A3" "ADM0_DIF"
[9] "LEVEL" "TYPE"
[11] "ADMIN" "ADM0_A3"
[13] "GEOU_DIF" "GEOUNIT"
[15] "GU_A3" "SU_DIF"
[17] "SUBUNIT" "SU_A3"
[19] "NAME" "ABBREV"
[21] "POSTAL" "NAME_FORMA"
[23] "TERR_" "NAME_SORT"
[25] "MAP_COLOR" "POP_EST"
[27] "GDP_MD_EST" "FIPS_10_"
[29] "ISO_A2" "ISO_A3"
[31] "ISO_N3" "ISO3"
[33] "LON" "LAT"
[35] "ISO3.1" "ADMIN.1"
[37] "REGION" "continent"
[39] "GEO3major" "GEO3"
[41] "IMAGE24" "GLOCAF"
[43] "Stern" "SRESmajor"
[45] "SRES" "GBD"
[47] "AVOIDnumeric" "AVOIDname"
[49] "LDC" "SID"
[51] "LLDC"
# ***这里主要使用***:
# 第11列:类对象属性ID
# 第19列:后期绘图匹配项
# 第33列:绘图时的经度
# 第34列:绘图时的纬度
3.实例操作
1)输入文件格式说明
文件逗号分隔,每列的说明:
1.ID
新的类对象属性ID,自定义,等于原来map中的11列ADMIN
2.Name
后期绘图匹配项,同ID即可,等于原来map中的19列NAME
3.LON
绘图时的经度33列LON
4.LAT
绘图时的纬度34列LAT
注意:这里的经纬度是你自己想要标记饼图的经纬度(起到随意标记点的作用)
5.国家名
和原始map文件中的第11列ADMIN ID对应,每个国家都有一个坐标多边形区域,必须把坐标点画在某个国家内
6.饼图分块-1
7.饼图分块-2
8.legend名字
这里一个饼图只分成2部分,用户可自定义添加更多
2)画图的具体代码如下:
rm(list=ls())
library(rworldmap)
library(rworldxtra)
#---------------------------------
# 读入输入文件
dat<-read.table("test.txt",header = T,sep=",",stringsAsFactors = F)
> dat
ADMIN NAME LON LAT rawName P1 P2 legendName
1 Philippines Philippines 121.41825 15.95318 Philippines 0.5 0.5 legendName
2 Bangladesh Bangladesh 90.22658 23.88242 Bangladesh 0.4 0.6 legendName
3 Myanmar Myanmar 96.48873 21.21545 Myanmar 0.2 0.8 legendName
#---------------------------------
# 提取原始high resolution map的数据,作为map对应的新数据
a<-getMap(resolution = "high")
rawData<-a@data[,c(11,19,33,34)]
#---------------------------------
# 注意下面的操作,因为我的饼图只区分2块,所以只需要多增加2列数据
rawData[,5]<-NaN # A1_freq 作图时不出现
rawData[,6]<-NaN # A2_freq 作图时不出现
colnames(rawData)<-colnames(dat)[c(1:4,6,7)]
IDname<-c()
for(i in 1:length(a@plotOrder)){IDname[i]<-a@polygons[[i]]@ID}
#---------------------------------
# 将新数据data覆盖原始的数据data
rawData<-rbind(rawData,dat[,c(1:4,6,7)]) # 合并新旧数据
a@data<-rawData
#---------------------------------
# 添加新加入的城市对应的对象属性polygons,添加一个对象到list中
# polygons是一个list;每个成员是一个sp
# 每个sp的polygons又是一个list,每个成员是一个sp
# 每个sp都有其自己的对象属性,相同或不同
#
for(i in 1:dim(dat)[1])
{
index<-which(IDname==dat[i,5]) # 获得新坐标点所在国家[第五列]在原有map中的下标
tmpPolygon<-a@polygons[[index]] # 提取国家的polygon信息{ID=国家名}
tmpPolygon@labpt<-as.numeric(dat[i,3:4]) # 坐标更换为新坐标点的经纬度
tmpPolygon@ID<-dat[i,1] # 对象ID更换为新坐标点的名字
a@polygons<-c(a@polygons,list(tmpPolygon)) # 将新生成的polygon添加到原有的polygon List中
# 相当于把新坐标点的polygon信息添加到map中
# 新坐标点的polygon取所在国家的polygon
}
#---------------------------------
# plot map pie
par(oma=c(0,0,0,0),
mar=c(0,0,0,0),
fig=c(0,1,0,1),
mai=c(0,0,0,0)
)
# 因为我的饼图只区分2块,所以只需要2个颜色
color_array<-c("black","red")
mapPies(a,
nameZs = c(colnames(a@data)[5],
colnames(a@data)[6]), # 用作画图的两列
zColours=color_array, # 不同比例的颜色
symbolSize = 0.5, # pie的大小
addCatLegend=F, # 不添加默认的legend
oceanCol = "lightblue",
landCol = "wheat")
legend(60,0, # legend所在的横纵坐标/经纬度
legend = c(colnames(a@data)[5],
colnames(a@data)[6]), # legend中的指示文字
fill = color_array, # legend 指示box的颜色,要求顺序同上zColours
title = dat[1,8], # legend title
bty="n", # 不做legen的背景框
title.adj = c(1)
)
成品如下
转载请标明出处和作者 ^+^
撰文&编辑:VickieQ
校对:HCLO4 & 花毛