欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

数模技巧不用for循环且使用ggplot2实现地图上连线

程序员文章站 2022-03-12 22:29:16
目录1. 前文回顾背景图像2. 利用ggplot2连接多个点1) 现有数据2) 数据预处理3) 绘图4) 结果展示最近由于自己的时间关系,很久没有发一些干货了。这次想谈谈之前我们在进行数学建模时,如何...

最近由于自己的时间关系,很久没有发一些干货了。这次想谈谈之前我们在进行数学建模时,如何将设计好的最优路径,利用ggplot2在地图上进行绘制与展示。

最简单的方法是使用plot绘图,然后再使用lines函数一条一条地将线加上去,但是一条一条加上去的过程中,需要使用for循环不说,而且绘制出来的图相对也没那么美腻。

下面我们讲一讲使用ggplot2且不使用for循环,如何快速便捷地完成这样的操作。

1. 前文回顾

首先可以回顾一下,在没有*的前提下,我们是如何利用ggplot2绘制一个较为好看的中国地图:利用r绘制漂亮的中国地图(无需通过google获取)。

下面我们基于前面绘制的中国地图,根据计算(最小生成树算法,之后有时间在说说这个,不过目前网上说的很详细了,而且也有很多代码)得到的相应连线贴到我们的图上。

背景图像

数模技巧不用for循环且使用ggplot2实现地图上连线

2. 利用ggplot2连接多个点

我们需要选定其中几个点,并将其进行连线。下面是我们最终想要达到的效果(之前的图使用mac画的,下面这个是windows,可能质感有些不一样,望大家理解):

数模技巧不用for循环且使用ggplot2实现地图上连线

为了达到这样的效果,我们主要是需要将数据集整理成可以能够舒适绘制的方式。利用ggplot2绘图,整理数据集要占80%以上的工作。

1) 现有数据

我们的最终目的是连33条线,所以先将需要连的线均一组一组地罗列而出(每个city都对应着一组经纬度,相应地是地图上的一个点)。

(前面的最终效果图是前11组城市连线)

下面的数据我们命名为:city_pair

      city1     city2
1  北京&天津      上海
2       上海 广州&深圳
3  广州&深圳      重庆
4       重庆      成都
5       重庆      西安
6  北京&天津    哈尔滨
7  北京&天津      武汉
8       武汉      郑州
9       重庆      昆明
10 北京&天津  乌鲁木齐
11 北京&天津      拉萨
12      郑州      西安
13      武汉      重庆
14 北京&天津      郑州
15 北京&天津      西安
16      郑州      重庆
17 北京&天津      重庆
18      武汉 广州&深圳
19      上海      武汉
20      上海      郑州
21 北京&天津 广州&深圳
22      上海      重庆
23      昆明 广州&深圳
24      武汉      成都
25      郑州      成都
26      西安      成都
27 北京&天津      成都
28      成都      昆明
29      西安      武汉
30      成都 广州&深圳
31      上海      成都
32    哈尔滨      重庆
33    哈尔滨 广州&深圳

所以我们还需要对应城市经纬度及人口信息,这里的对象为mat.cities,它长这样:(这部分的数据生成也在我们前面的博客中有提及)

       names      lat      long population
1  北京&天津 39.90420 116.40740    32.5506
2       上海 31.23039 121.47370    23.0191
3       郑州 34.74725 113.62493     8.6265
4   乌鲁木齐 43.82660  87.61684     3.1103
5     哈尔滨 45.80218 126.53582    10.6360
6       西安 34.34126 108.93982     8.4678
7       武汉 30.59276 114.30524     9.7854
8       成都 30.57022 104.06477    14.0476
9       拉萨 29.64411  91.11445     0.5594
10      重庆 29.56470 106.55071    28.8462
11      昆明 24.87966 102.83321     6.4320
12 广州&深圳 23.02067 113.75178    23.0587

有了这样两份原始数据,我们就可以开始进行绘图了。

首先是需要将数据整理成能够进行绘图的,为了方便操作,我们直接对原本的33组城市对进行操作。下面是数据预处理的过程。(由于当时数模时间有限,而数据量也不是很大,所以下面采用了大量的for循环,希望大家在用r时还是尽可能多用向量化操作,少用for循环)

2) 数据预处理

预处理代码如下:

dat_plot = matrix(nrow = 66, ncol = 4)
k = 0
for (i in 1:33) {
  for (j in 1:2) {
    k = k + 1
    my.row = mat.cities[city_pair[i, j] == mat.cities$names, ]
    dat_plot[k, 1] = unlist(my.row[1])
    dat_plot[k, 2] = unlist(my.row[2])
    dat_plot[k, 3] = unlist(my.row[3])
    dat_plot[k, 4] = i
  }
}
colnames(dat_plot) = c('地区', 'lat', 'long', 'group')
dat_plot = as.data.frame(dat_plot)
dat_plot$lat = as.numeric(as.character(dat_plot$lat))   
dat_plot$long = as.numeric(as.character(dat_plot$long))

这里我们的主要思路是:将配对的一组城市变为拆分成两组,然后再在最后添加一个group变量,主要是用于连线(两个城市如果在一个相同的group中,使用ggplot绘图中的参数group即可将两个点连接起来)。

在生成完想要的数据集后,记得将经纬度调整为数值型,group直接为factor即可。

最后我们得到的数据dat_plot长下面这样:

        地区      lat      long group
1  北京&天津 39.90420 116.40740     1
2       上海 31.23039 121.47370     1
3       上海 31.23039 121.47370     2
4  广州&深圳 23.02067 113.75178     2
5  广州&深圳 23.02067 113.75178     3
6       重庆 29.56470 106.55071     3
7       重庆 29.56470 106.55071     4
8       成都 30.57022 104.06477     4
9       重庆 29.56470 106.55071     5
10      西安 34.34126 108.93982     5
11 北京&天津 39.90420 116.40740     6
12    哈尔滨 45.80218 126.53582     6
13 北京&天津 39.90420 116.40740     7
14      武汉 30.59276 114.30524     7
15      武汉 30.59276 114.30524     8
16      郑州 34.74725 113.62493     8
17      重庆 29.56470 106.55071     9
18      昆明 24.87966 102.83321     9
19 北京&天津 39.90420 116.40740    10
20  乌鲁木齐 43.82660  87.61684    10
21 北京&天津 39.90420 116.40740    11
22      拉萨 29.64411  91.11445    11
23      郑州 34.74725 113.62493    12
24      西安 34.34126 108.93982    12
25      武汉 30.59276 114.30524    13
26      重庆 29.56470 106.55071    13
27 北京&天津 39.90420 116.40740    14
28      郑州 34.74725 113.62493    14
29 北京&天津 39.90420 116.40740    15
30      西安 34.34126 108.93982    15
31      郑州 34.74725 113.62493    16
32      重庆 29.56470 106.55071    16
33 北京&天津 39.90420 116.40740    17
34      重庆 29.56470 106.55071    17
35      武汉 30.59276 114.30524    18
36 广州&深圳 23.02067 113.75178    18
37      上海 31.23039 121.47370    19
38      武汉 30.59276 114.30524    19
39      上海 31.23039 121.47370    20
40      郑州 34.74725 113.62493    20
41 北京&天津 39.90420 116.40740    21
42 广州&深圳 23.02067 113.75178    21
43      上海 31.23039 121.47370    22
44      重庆 29.56470 106.55071    22
45      昆明 24.87966 102.83321    23
46 广州&深圳 23.02067 113.75178    23
47      武汉 30.59276 114.30524    24
48      成都 30.57022 104.06477    24
49      郑州 34.74725 113.62493    25
50      成都 30.57022 104.06477    25
51      西安 34.34126 108.93982    26
52      成都 30.57022 104.06477    26
53 北京&天津 39.90420 116.40740    27
54      成都 30.57022 104.06477    27
55      成都 30.57022 104.06477    28
56      昆明 24.87966 102.83321    28
57      西安 34.34126 108.93982    29
58      武汉 30.59276 114.30524    29
59      成都 30.57022 104.06477    30
60 广州&深圳 23.02067 113.75178    30
61      上海 31.23039 121.47370    31
62      成都 30.57022 104.06477    31
63    哈尔滨 45.80218 126.53582    32
64      重庆 29.56470 106.55071    32
65    哈尔滨 45.80218 126.53582    33
66 广州&深圳 23.02067 113.75178    33

3) 绘图

下面我们的核心绘图代码如下,想要连接不同的线,我们只是变了数据中选取的行,如:dat_plot[1:22, ]

## 11线
ggplot() + 
  geom_path(data = china, aes(long, lat, group = group), color = '#fd9fa4', show.legend = f) +
  geom_point(data = mat.cities, aes(x = long, y = lat, size = population), alpha = 0.8, color = '#8bb6d6') +
  geom_line(data = dat_plot[1:22, ], aes(long, lat, group = group), size = 1, alpha = 0.8, color = '#8bb6d6') +
  geom_text_repel(data = mat.cities, aes(x = long, y = lat, label = names), family = "stheiti") +
  labs(x = '经度', y = '纬度', title = '十一条连线', size = '人口(百万)') + 
  theme_bw() +
  theme(panel.border = element_blank(),
        text = element_text(family = "stheiti"),
        plot.title = element_text(hjust = 0.5))

## 16线
ggplot() + 
  geom_path(data = china, aes(long, lat, group = group), color = '#fd9fa4', show.legend = f) +
  geom_point(data = mat.cities, aes(x = long, y = lat, size = population), alpha = 0.8, color = '#8bb6d6') +
  geom_line(data = dat_plot[1:32, ], aes(long, lat, group = group), size = 1, alpha = 0.8, color = '#8bb6d6') +
  geom_text_repel(data = mat.cities, aes(x = long, y = lat, label = names), family = "stheiti") +
  labs(x = '经度', y = '纬度', title = '十六条连线', size = '人口(百万)') + 
  theme_bw() +
  theme(panel.border = element_blank(),
        text = element_text(family = "stheiti"),
        plot.title = element_text(hjust = 0.5))

## 33线
ggplot() + 
  geom_path(data = china, aes(long, lat, group = group), color = '#fd9fa4', show.legend = f) +
  geom_point(data = mat.cities, aes(x = long, y = lat, size = population), alpha = 0.8, color = '#8bb6d6') +
  geom_line(data = dat_plot[1:66, ], aes(long, lat, group = group), size = 1, alpha = 0.8, color = '#8bb6d6') +
  geom_text_repel(data = mat.cities, aes(x = long, y = lat, label = names), family = "stheiti") +
  labs(x = '经度', y = '纬度', title = '三十三条连线', size = '人口(百万)') + 
  theme_bw() +
  theme(panel.border = element_blank(),
        text = element_text(family = "stheiti"),
        plot.title = element_text(hjust = 0.5))

绘图过程没有什么好说的了,里面使用的函数与方法都在前面的博客中提及过:

r语言学习ggplot2绘制统计图形包全面详解

唯一添加的连线所使用的函数:geom_line,里面只需注意多了一个参数group,记得添加即可。

4) 结果展示

最后的16条连线与33条连线的效果图分别如下所示:

16条连线:

数模技巧不用for循环且使用ggplot2实现地图上连线

33条连线:

数模技巧不用for循环且使用ggplot2实现地图上连线

以上就是数模技巧ggplot2不用for循环实现地图上连线的详细内容,更多关于ggplot2在地图上连线数模技巧的资料请关注其它相关文章!