標籤:

上帝視角——給世界一個特寫~

2017-05-05 杜雨 EasyCharts

最近在研究使用R包製作動畫圖表,也就是類似GIF動圖,感覺很有趣,也是動態圖表呈現的一個非常獨特的領域,剛剛研究出了些成果,今天這篇分享使用GIF動畫+球型投影來製作呈現地球轉動效果的動態GIF圖表。

過程要使用謝益輝大神的動畫包——animation,該包依賴可執行程序——,ImageMagic,所以導入animation包之前要提前下載並安裝該動畫軟體。

library(ggplot2)

library(maps)

library(plyr)

library(grid)

library(showtext)

library(Cairo)

library(xlsx)

library(RColorBrewer)

library(dplyr)

library("animation")

本次使用maps中的世界地圖素材:

world_map <- map_data("world")

為了區分大洲,我將該地圖中的國家按照地理位置進行了歸類(七大洲)

data<-read.csv("D:/R/mapdata/Word_State.csv",stringsAsFactors = FALSE,check.names = FALSE)

ggplot(data,aes(map_id=region))+

geom_map(aes(fill=Address),map=world_map,col="white")+

expand_limits(x=world_map$long,y=world_map$lat)+

scale_y_continuous(breaks=(-2:2)*30) +

scale_x_continuous(breaks=(-4:4)*45)+

coord_map("ortho", orientation = c(30,110,0))

篩選其中某一個州進行特定角度呈現:

data1<-data[data$Address=="North America",]

ggplot()+

geom_map(data=data,aes(map_id=region),map=world_map,col="white",fill="#A3A3A3")+

geom_map(data=data1,aes(map_id=region,fill=Address),map=world_map,col=NA)+

expand_limits(x=world_map$long,y=world_map$lat)+

scale_y_continuous(breaks=(-6:6)*15) +

scale_x_continuous(breaks=(-12:12)*15)+

coord_map("ortho", orientation = c(0,-95,0))+

guides(fill=FALSE) +

theme(

axis.ticks=element_blank(),

axis.text=element_blank(),

axis.title=element_blank(),

panel.background=element_rect(fill="white",colour=NA),

panel.grid.major = element_line(colour = "grey60",size=.25),

panel.grid.minor = element_line(colour = "grey60",size=.25)

)

world_map_data<-merge(world_map,data,all.x=TRUE)

midpos<-function(x) mean(range(x,na.rm=TRUE))

centres<-ddply(world_map_data,.(Address),colwise(midpos,.(long,lat)))

centres<-centres[centres$Address!="Antarctica",]

centres$angle<-0

centres$long[centres$Address=="Asia"]=100

centres$long[centres$Address=="North America"]=-100

centres$long[centres$Address=="Oceania"]=130

計算每個大洲的地區中心(個別中心偏離中心大陸太遠,需要手動調整)

#-------------------

使用grid的版面控制系統進行多圖排版:

setwd("E:/數據可視化/R/R語言學習筆記/可視化/Shiny/動態圖表")

world_map_data<-arrange(world_map_data,group,order)

CairoPNG(file="wordmap.png",width_=1600,height=1200)

showtext.begin()

grid.newpage()

pushViewport(viewport(layout=grid.layout(2,3)))

vplayout<-function(x,y){viewport(layout.pos.row =x,layout.pos.col=y)}

for(i in 1:nrow(centres)){

mydata<-world_map_data[world_map_data$Address==centres$Address[i],]

p<-ggplot()+

geom_polygon(data=world_map_data,aes(x=long,y=lat,group=group),fill="grey95",colour="grey",size=.25)+

geom_map(data=mydata,aes(map_id=region),map=world_map_data,colour="white",fill="#F8766D",size=.25)+

coord_map("ortho",orientation=c(centres$lat[i],centres$long[i],0))+

scale_y_continuous(breaks=(-6:6)*15) +

scale_x_continuous(breaks=(-12:12)*15)+

labs(title=centres$Address[i])+

theme(

panel.background=element_rect(fill="white",colour=NA),

panel.grid.major = element_line(colour = "grey60",size=.25),

panel.grid.minor = element_line(colour = "grey60",size=.25),

text=element_text(size=20),

axis.text=element_blank(),

axis.title=element_blank(),

axis.ticks=element_blank(),

plot.title=element_text(size=20,family="myfont",hjust=.5),

plot.margin = unit(c(ifelse(i<=3,5,.5),1,ifelse(i>=3,5,.5),1),"lines")

)

print(p,vp=vplayout(ifelse(i<=3,1,2),ifelse(i<=3,i,i-3)))

}

grid.text(label="God"s Perspective",x=.01,y=.98,gp=gpar(col="black",fontsize=35),draw=TRUE,just="left")

grid.text(label="Data Source:DataMofang",x=.02,y=.02,gp=gpar(col="black",fontsize=20),draw=TRUE,just="left")

showtext.end()

dev.off()

---------------------------------------------

使用animation包將361幀地圖合併為GIF動畫

(友情提示:機器性能太弱請不要隨便玩火,容易爆內存~!!!)

saveGIF({

ani.options(interval=.15,convert=shQuote("D:/Program Files/ImageMagick-7.0.5-Q16/convert.exe"))

for(i in 0:360){

p<-ggplot()+

geom_polygon(data=world_map_data,aes(x=long,y=lat,group=group,fill=Address),colour="grey",size=.25)+

coord_map("ortho",orientation=c(0,i,0))+

scale_y_continuous(breaks=(-6:6)*15) +

scale_x_continuous(breaks=(-12:12)*15)+

scale_fill_brewer(name="million($)",palette="Set2")+

theme(

panel.background=element_rect(fill="white",colour=NA),

panel.grid.major = element_line(colour = "grey60",size=.25),

panel.grid.minor = element_line(colour = "grey60",size=.25),

axis.text=element_blank(),

axis.title=element_blank(),

axis.ticks=element_blank()

)

print(p)

}

},movie.name="Movingworld_map.gif",ani.width_=1200,ani.height=1000)

因為原圖有13M,微信公眾平台限制圖片大小為5m,所以大圖能就沒法奉上了,不過又做了一個壓縮版的小圖,效果如下:

draw = function(i){

ggplot()+

geom_polygon(data=world_map_data,aes(x=long,y=lat,group=group,fill=Address),colour="grey",size=.25)+

coord_map("ortho",orientation=c(0,i,0))+

scale_y_continuous(breaks=(-6:6)*15) +

scale_x_continuous(breaks=(-12:12)*15)+

scale_fill_brewer(name="million($)",palette="Set2")+

theme(

panel.background=element_rect(fill="white",colour=NA),

panel.grid.major = element_line(colour = "grey60",size=.25),

panel.grid.minor = element_line(colour = "grey60",size=.25),

axis.text=element_blank(),

axis.title=element_blank(),

axis.ticks=element_blank()

)

}

oopts=ani.options(ffmpeg = "D:/Program Files/ImageMagick-7.0.5-Q16/ffmpeg.exe")

saveVideo({

for(i in 1:36) print(draw(i))

ani.options(interval = 0.6,nmax=230)},

video.name ="world_map_move.gif",other.opts="-b 4000k")

(gif動圖,可以點開看。如果仍然無效果,請訪問網頁上帝視角——給世界一個特寫~)

該案例涉及到的技術面比較廣,需要使用循環、grid圖形版面控制、地圖投影、自編函數、顏色填充等,僅作為探索可視化道路上的一個小台階,也許現在看起來有些高不可攀,但是當你真正深入的了解R語法以及函數編程和ggplot2之後,就沒那麼難理解了!

歡迎關注魔方學院QQ群

EasyCharts團隊出品

帥的人都關注了EasyCharts團隊^..^~

QQ交流群:553270834

微信公眾號:EasyCharts

更多信息敬請查看: easychart.github.io/pos


推薦閱讀:

智聯Python相關職位的數據分析及可視化-Pandas&Matplotlib篇
用R語言高效下載圖片
R語言可視化——圖表嵌套(母子圖)
Python 數據可視化?
R語言之數據可視化

TAG:数据可视化 |