用R在地图上绘制网络图的三种方法
作者:嚴濤浙江大學作物遺傳育種在讀研究生(生物信息學方向)偽碼農,R語言愛好者,愛開源
又到了親愛的嚴濤老師時間:
諾獎文章里面的動圖布局教程來了!!
R包ggseqlogo |置換序列分析圖
ggplot2高效實用指南(可視化腳本,工具,套路,配色)
ComplexHeatmap |理解繪圖邏輯布局熱圖
R語言可視化學習筆記之ggridges包
? ggplot2學習筆記之圖形排列
網絡地理圖產品與傳統的網絡圖產品不同,引用當地理位置進行節點網絡可視化時,需要將這些節點放置在地圖上,然后繪制他們之間的連結。馬庫斯康拉德的帖子(https://datascience.blog。 wzb.eu/2018/05/31/three-ways-of-visualizing-a-graph-on-a-map/),非常贊。其中他的部分思路對于我們學習可視化很有幫助。
首先準備需要的R包,當需要一次性加載多個R包時,我們可以利用pacman,它整合了library包中的一些相關函數,利用pacman包中的p_load函數可以自動加載需要的R包,如果沒有找到替代自動安裝缺失的R包。這樣我們就不用寫很多行library命令了,從而使代碼變得簡單些。
library(pacman) p_load(assertthat,tidyverse,ggraph,igraph,ggmap)為了方便大家練習,僅挑出部分國家地理位置,如下:
country_coords_txt <- "1 3.00000 28.00000 Algeria2 54.00000 24.00000 UAE3 139.75309 35.68536 Japan4 45.00000 25.00000 'Saudi Arabia'5 9.00000 34.00000 Tunisia6 5.75000 52.50000 Netherlands7 103.80000 1.36667 Singapore8 124.10000 -8.36667 Korea9 -2.69531 54.75844 UK 10 34.91155 39.05901 Turkey 11 -113.64258 60.10867 Canada 12 77.00000 20.00000 India 13 25.00000 46.00000 Romania 14 135.00000 -25.00000 Australia 15 10.00000 62.00000 Norway"nodes <- read.table(text = country_coords_txt, header = FALSE, quote = "'",sep = "\t",col.names = c("id","lon","lat","name"))現在我們有了15個國家的地理坐標(LON和LAT)和國家名稱,這些就是之后要在地圖中展現的例程,下面我們需要在這些隊列之間隨機創建一些鏈接,方便之后將不同國家連起來。
# 生成隨機數種子,保證結果的重復性 set.seed(42) min <- 1 max <- 4 n_categories <- 4# edges:建立國家之間的隨機連結 edges <- map_dfr(nodes$id, function(id){n <- floor(runif(1,min,max+1))to <- sample(1:max(nodes$id),n ,replace = FALSE)to <- to[to!=id]categories <- sample(1:n_categories,length(to), replace = TRUE)weight <- runif(length(to))data_frame(from=id, to=to, weight=weight, category=categories) }) edges <- edges%>%mutate(category=as.factor(category))上面我們已經創建好了例程(node)以及連接(edge),并且還生成了連結之間的類別(categories)和權重(weight),下面就進行可視化。
生成圖形結構
下面創建一個預測邊緣的數據框架。
(g <- graph_from_data_frame(edges, directed = FALSE, vertices = nodes))此外,還需要再額外定義四列并入替換的初始位置。
edges_for_plot <- edges%>%inner_join(nodes%>%select(id, lon, lat),by=c("from"="id"))%>%rename(x=lon, y=lat)%>%inner_join(nodes%>%select(id,lon,lat),by=c("to"="id"))%>%rename(xend=lon,yend=lat) assert_that(nrow(edges_for_plot)==nrow(edges))# 給每個節點一個權重(weight)值,在之后的繪圖中將反應在節點的大小上 nodes$weight <- degree(g)再下面定義以下GGPLOT2主題用來繪制地圖。
# 定義主題 maptheme <- theme(panel.grid = element_blank(),axis.text = element_blank(),axis.ticks = element_blank(),axis.title = element_blank(),legend.position = "bottom",panel.background = element_rect(fill="#596673"),plot.margin = unit(c(0,0,0.5,0),"cm") )# 指定`data=map_data("world")`保證每個節點共享同一世界地圖中的坐標系 country_shape <- geom_polygon(aes(x=long, y=lat, group=group),data=map_data("world"),fill="#CECECE", color="#515151",size=0.1)# coord_fixed函數可以改變xy軸的范圍 mapcoords <- coord_fixed(xlim=c(-150,180), ylim=c(-55,80))方法一:ggplot2
除了需要世界地圖(country_shape)中國家邊界外,我們還需要三個幾何對象:
geom_point:重新排序;
geom_text:添加上游的標簽名字;
geom_curve:預測上游間的連線(edge)。
此外我們需要定義aesthetic來規定數據如何可視化地映射在地圖上
對于股東(節點):將各個地理坐標映射到畫板的x,y位置,以及路由器的大小取決于權重大小;
對于連線(邊緣):使用edges_for_plot數據集,xend和yend指定連線的起始和重點,按照category著色,根據weight來指定連線的粗細。
注意:?geoms的順序很重要,因為它定義了先放置該對象,先放置的將被后面的層疊覆蓋。因此我們先行放置了連線(edges),然后重新布局了(nodes),最后重新布局的標簽(labels)。
ggplot(nodes)+country_shape+geom_curve(aes(x=x,y=y,xend=xend,yend=yend,color=category,size=weight),data=edges_for_plot,curvature = 0.33,alpha=0.5)+scale_size_continuous(guide = FALSE,range = c(0.25,2))+ # scale for edge widthsgeom_point(aes(x=lon,y=lat,size=weight), # draw nodesshape=21,fill="white",color="black",stroke=0.5)+scale_size_continuous(guide = FALSE, range = c(1,6))+ # scale for node sizegeom_text(aes(x=lon,y=lat,label=name), # draw text labelshjust=0,nudge_x = 1,nudge_y = 4,size=3,color="white",fontface="bold")+mapcoords+maptheme方法二:ggplot2 + ggraph
ggplot2有一個名叫gggraph的擴展包(點我了解更多的ggplot2擴展包)專門為網絡圖的替換添加了geoms美學,它可以幫助我們對電容器和接線使用單獨的標度(scales)。
nodes_pos <- nodes%>%select(lon,lat)%>%rename(x=lon,y=lat) lay <- create_layout(g,"manual",node.position=nodes_pos) assert_that(nrow(lay)==nrow(nodes))# add node degree for scaling the node sizes lay$weight <- degree(g)# 使用gggraph包中的geom_edge_arc和geom_node_point函數進行繪圖 ggraph(lay)+country_shape+geom_edge_arc(aes(color=category,edge_width=weight,circular=FALSE),data = edges_for_plot,curvature = 0.33,alpha=0.5)+scale_edge_width_continuous(range = c(0.5,2),guide=FALSE)+geom_node_point(aes(size=weight),shape=21,fill="white",color="black",stroke=0.5)+scale_size_continuous(range = c(1,6),guide = FALSE)+# 指定repel = TRUE來分發各個節點的標簽geom_node_text(aes(label=name),repel = TRUE, size=3,color="white",fontface="bold")+mapcoords+maptheme方法三:圖形疊加
圖形疊加需要一個透明背景,可通過下面的命令創建。
theme_transp_overlay <- theme(panel.background = element_rect(fill="transparent",color=NA),plot.background = element_rect(fill="transparent",color=NA) )在透明的背景上添加地圖。
這里介紹一個技巧,我們可以將繪圖代碼放置在()中,運行一句命令即可將圖形顯示在你的RStudio中,而不需要再次運行p_base。
(p_base <- ggplot() + country_shape + mapcoords + maptheme)下面創建第一個需要覆蓋在地圖上的層疊-各節點之間的連線(邊)。
(p_edges <- ggplot(edges_for_plot)+geom_curve(aes(x=x,y=y,xend=xend,yend=yend,color=category,size=weight), # draw edges as arcscurvature = 0.33,alpha=0.33)+scale_size_continuous(guide = FALSE, range = c(0.5, 2)) + # scale for edge widthsmapcoords + maptheme + theme_transp_overlay +theme(legend.position = c(0.5, -0.1),legend.direction = "horizontal"))然后是排除第二個需要重疊的附件-節點(節點)
(p_nodes <- ggplot(nodes) +geom_point(aes(x = lon, y = lat, size = weight),shape = 21, fill = "white", color = "black", # draw nodesstroke = 0.5) +scale_size_continuous(guide = FALSE, range = c(1, 6)) + # scale for node sizegeom_text(aes(x = lon, y = lat, label = name), # draw text labelshjust = 0, nudge_x = 1, nudge_y = 4,size = 3, color = "white", fontface = "bold") +mapcoords + maptheme + theme_transp_overlay)需要求最后用annotation_custom(ggplotGrob)把p_edges狀語從句:p_nodes添加到p_base上,三個圖形就疊加在一起了。還之后需要手動多次調整p_edges狀語從句:p_nodes在垂直方向上的位置。
p <- p_base+annotation_custom(ggplotGrob(p_edges), ymin = -74)+annotation_custom(ggplotGrob(p_nodes), ymin = -74) print(p)[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UXmmXC3W-1572262414923)(https://upload-images.jianshu.io/upload_images/7071112-4cc26891cff059a2?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的用R在地图上绘制网络图的三种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这篇纯数据分析文章被拒8次,发到行业顶刊
- 下一篇: 癌症精准医疗上市公司泛生子基因 - 内推