用R在地图上绘制网络图的三种方法

news2024/11/15 7:17:43

地理网络图与传统的网络图不同,当引用地理位置进行节点网络可视化时,需要将这些节点放置在地图上,然后绘制他们之间的连结。Markus konrad的帖子(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       Algeria
 2    54.00000  24.00000           UAE
 3   139.75309  35.68536         Japan
 4    45.00000  25.00000 'Saudi Arabia'
 5     9.00000  34.00000       Tunisia
 6     5.75000  52.50000   Netherlands
 7   103.80000   1.36667     Singapore
 8   124.10000  -8.36667         Korea
 9    -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)中国家边界外,我们还需要三个几何对象:

  1. geom_point:绘制节点;

  2. geom_text:添加节点的标签名字;

  3. geom_curve:绘制节点间的连线(edge)。

此外我们需要定义aesthetic来规定数据如何可视化地映射在地图上

  1. 对于节点(nodes):将各个地理坐标映射到画板的x、y位置,并且节点的大小取决于权重大小;

  2. 对于连线(edges):使用edges_for_plot数据集,xendyend指定连线的起始和重点,按照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 widths
  geom_point(aes(x=lon,y=lat,size=weight),  # draw nodes
             shape=21,fill="white",color="black",stroke=0.5)+
  scale_size_continuous(guide = FALSE, range = c(1,6))+ # scale for node size
  geom_text(aes(x=lon,y=lat,label=name), # draw text labels
            hjust=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)

图片

下面创建第一个需要覆盖在地图上的图层——各节点之间的连线(edges)。

(p_edges <- ggplot(edges_for_plot)+
  geom_curve(aes(x=x,y=y,xend=xend,yend=yend,color=category,size=weight), # draw edges as arcs
             curvature = 0.33,alpha=0.33)+
  scale_size_continuous(guide = FALSE, range = c(0.5, 2)) + # scale for edge widths
  mapcoords + maptheme + theme_transp_overlay +
  theme(legend.position = c(0.5, -0.1),
        legend.direction = "horizontal"))

图片

然后是绘制第二个需要叠加的图层——节点(nodes)

(p_nodes <- ggplot(nodes) +
  geom_point(aes(x = lon, y = lat, size = weight),
             shape = 21, fill = "white", color = "black",   # draw nodes
             stroke = 0.5) +
  scale_size_continuous(guide = FALSE, range = c(1, 6)) +   # scale for node size
  geom_text(aes(x = lon, y = lat, label = name),            # draw text labels
            hjust = 0, nudge_x = 1, nudge_y = 4,
            size = 3, color = "white", fontface = "bold") +
  mapcoords + maptheme + theme_transp_overlay)

图片

最后需要用annotation_custom(ggplotGrob)p_edgesp_nodes添加到p_base上,三个图形就叠加在一起了。之后还需要手动多次调整p_edgesp_nodes在垂直方向上的位置。

p <- p_base+
  annotation_custom(ggplotGrob(p_edges), ymin = -74)+
  annotation_custom(ggplotGrob(p_nodes), ymin = -74)
print(p)

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1907144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

绝地求生PUBG兰博基尼怎么兑换 兰博基尼怎么获得

绝地求生采用虚幻4引擎制作&#xff0c;玩家们会在一个偏远的岛屿上出生&#xff0c;然后展开一场赢家通吃的生存竞赛&#xff0c;最后只会有1个人存活。当然&#xff0c;和其他生存游戏一样&#xff0c;玩家需要在广袤复杂的地图中收集武器、车辆、物资&#xff0c;而且也会有…

数字化设计与分析助力建造印度最大污水处理厂

利用 STAAD 开展结构分析和设计&#xff0c;为不稳定土体上的复杂水池系统开发稳定的基础 治理河流 新德里不仅是印度的首都&#xff0c;一个多世纪以来也一直是印度最重要的城市之一。这座城市于 1911 年作为新的政府所在地&#xff0c;历经 20 年时间建成了许多宏伟建筑&…

tomcat的优化和tomcat和nginx实现动静分离:

tomcat的优化 tomcat自身的优化 tomcat的并发处理能力不强。大项目不使用tomcat做为转发动态的中间件&#xff08;k8s集群&#xff0c;python&#xff0c;rubby&#xff09;&#xff0c;小项目会使用&#xff08;内部使用&#xff09;&#xff0c;动静分离。 优化tomcat的启动…

什么是离散化?

离散化 题目 你会这个题 吗&#xff1f; 题目 假定有一个无限长的数轴&#xff0c;数轴上每个坐标上的数都是 0 0 0。 现在&#xff0c;我们首先进行 n n n 次操作&#xff0c;每次操作将某一位置 x x x 上的数加 c c c。 接下来&#xff0c;进行 m m m 次询问&#x…

方圆资源网,方圆资源官网

在当今这个信息化高速发展的时代&#xff0c;方圆资源网络已成为推动社会进步、促进经济发展的重要力量。方圆资源网不仅汇聚了海量的信息资源&#xff0c;更为我们提供了一个高效、便捷的信息交流平台。本文旨在详细介绍资源网的概念、特点、功能以及其在现代社会中的重要意义…

基于Java的数码论坛系统设计与实现

你好&#xff0c;我是计算机领域的研究者。如果你对数码论坛系统开发感兴趣或有相关需求&#xff0c;欢迎联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; Java技术、MySQL数据库、B/S架构、SpringBoot框架 工具&#xff1a; Eclipse、MySQ…

Django文档简化版——Django快速入门——创建一个基本的投票应用程序

Django快速入门——创建一个基本的投票应用程序 准备工作1、创建虚拟环境2、安装django 1、请求和响应&#xff08;1&#xff09;创建项目&#xff08;2&#xff09;用于开发的简易服务器&#xff08;3&#xff09;创建投票应用&#xff08;4&#xff09;编写第一个视图1、编写…

数据库基础复习

数据库简介 关系型数据库&#xff1a;Mysql 、Oracle 、SqlServer.... DB2 达梦 非关系型数据库&#xff1a;Redis 、MongoDB... MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管…

【45 Pandas+Pyecharts | 去哪儿海南旅游攻略数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 日期处理&#xff0c;提取年份、月份2.4 经费处理2.5 天数处理 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 出发日期_…

mysql在linux系统下重置root密码

mysql在linux系统下重置root密码 登录服务器时候mysql密码忘记了&#xff0c;没办法只能重置&#xff0c;找了一圈&#xff0c;把行之有效的方法介绍在这里。 错误展示&#xff1a; 我还以为yes就可以了呢&#xff0c;这是不行的意思。 关掉mysql服务 sudo systemctl stop …

基于大数据的电商产品评论数据分析与可视化--Python

基于大数据的电商产品评论数据分析与可视化 1绪论 1.1研究背景与意义阐述 随着电子商务领域的迅猛扩张,电商平台累积了海量的用户评价信息。这些建议不只是包含了消费者对产品的评价和经验分享,更重要的是,它们包含了丰富且价值巨大的信息。深度分析在线用户反馈不仅揭示…

【java web 01】3小时快速学习前端知识(收藏备用)

3小时快速学习前端知识【全栈专用】 一、教程简介1.1 Java 开发为何学Web技术1.2 课程设计1.3 课前准备 二、HTML2.1 Html简介2.1.1 HTML、CSS、JS分别有什么作用2.1.2 什么是HTML2.1.3 什么是标记语言 2.2 Hello&#xff0c;Html2.2.1 HTML基础结构2.2.2 专业词汇2.2.3 语法细…

SpringBoot后端验证码-防止密码爆破功能

一、简介 为了防止网站的用户被通过密码典爆破。引入验证码的功能是十分有必要的。而前端的验证码又仅仅是只防君子不防小人。通过burpsuit等工具很容易就会被绕过。所以后端实现的验证码才是对用户信息安全的一大重要保障。 实现思路&#xff1a; 1.引入图形生成的依赖 2.生成…

一文揭秘:中小企业选择做软文营销推广的优势有哪些?

在当今这个信息泛滥、注意力稀缺的时代&#xff0c;中小企业作为经济活力的重要组成部分&#xff0c;面临着前所未有的机遇与挑战。而相比于硬广告的直接灌输&#xff0c;软文营销推广以其独特的魅力&#xff0c;成为了中小企业提升品牌形象、吸引目标客户的重要手段。今天投媒…

关于腾讯的那些事(1月新闻纪要)

腾讯AI Lab与Robotics X 2023年度回顾 这份文件是腾讯AI Lab与Robotics X 2023年度回顾&#xff0c;主要回顾了腾讯在人工智能和机器人领域的研究进展、技术创新及成果应用。以下是文件的核心内容总结&#xff1a; 生成式AI的崛起与影响&#xff1a; 生成式AI的崛起彻底革新了…

【分布式系统】注册中心Zookeeper

目录 一.Zookkeeper 概述 1.Zookkeeper 定义 2.Zookkeeper 工作机制 3.Zookkeeper 特点 4.Zookkeeper 数据结构 5.Zookkeeper 应用场景 统一命名服务 统一配置管理 统一集群管理 服务器动态上下线 软负载均衡 6.Zookkeeper 选举机制 第一次启动选举机制 非第一次…

paddleocr运行报错?谈谈解决思路。

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

使用Keil 点亮LED灯 F103ZET6

1.新建项目 不截图了 2.startup_stm32f10x_hd.s Keil\Packs\Keil\STM32F1xx_DFP\2.2.0\Device\Source\ARM 搜索startup_stm32f10x_hd.s 复制到项目路径&#xff0c;双击Source Group 1 3.项目文件夹新建stm32f10x.h&#xff0c; 新建文件main.c #include "stm32f10x…

储能电源性能测试方案:纳米软件电源测试系统自动化测试服务

储能电源是什么&#xff1f;   储能电源主要由电池组、充电控制器、逆变器、车规级电芯、外壳等组成&#xff0c;是一种能够将电能储存起来并在需要时释放的设备&#xff0c;能够提供稳定、可靠的电力供应。因便携、轻便、环保等特点&#xff0c;储能电源在家用电子设备、车载…

30 华三华为STP

一 为什么要用到STP协议 在开启STP协议后 计算机之间互通 关闭生成树协议后 不能实现互通 为啥 逻辑环路 开通了STP 全部互通 PC>ping 192.168.1.3Ping 192.168.1.3: 32 data bytes, Press Ctrl_C to break From 192.168.1.3: bytes32 seq1 ttl128 time47 ms From 192.168.…