背景

前几天有个朋友在微信群里面问,如何画一个这样的图:

其实这种图还是很简单的,我记得我之前在做美赛的时候,就用python的basemap画过。当时也没公众号,代码也丢了,现在basemap也基本上过时了,都是使用cartopy画图。

这种图其实我也不知道叫什么名字,描述一下就是:map add 3d bar

⚠️:代码在文末

相似的图介绍

把这个描述在谷歌里面搜索,其实可以找到很多类似的图:

  1. 比如excel可以画:

  1. origin可以画:

  1. powerBI可以画:

  1. tableau可以画:

  1. 高德地图、一些地图提供商也可以画:

  1. 很多别的网站也提供服务,可以画出这样的:

上面的若干截图只是为了展示图像样式!!!!

但是

  1. 很少有看到使用python画的(其实并不少)
  2. 也很少能看到画中国的

那么本文,将介绍,如何使用python来画,基于中国地图做一些创作。

代码部分

导入包

# 导入包
from shapely.geometry import Polygon, MultiPolygon
from matplotlib import cm
import matplotlib
from getchinamap.getchinamap import DownloadChmap
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import platform
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import geopandas as gpd
import cartopy.feature
from cartopy.mpl.patch import geos_to_pathimport itertoolsfrom mpl_toolkits.mplot3d import Axes3D
# import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection,PolyCollection# matplotlib 显示中文的问题
if platform.system() == 'Darwin':plt.rcParams["font.family"] = 'Arial Unicode MS'
elif platform.system() == 'Windows':plt.rcParams["font.family"] = 'SimHei'
else:pass

获得中国地图数据

chinamapdata = gpd.read_file("https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000_full")
chinamapdata.head(3)
  1. 数据来源是阿里云,这种其实只是为了画个轮廓,足够了。
  2. 展示前3条,大概了解一下数据情况

样本数据

sampledata = pd.DataFrame({'lon':chinamapdata.centroid.x, 'lat':chinamapdata.centroid.y, 'name':chinamapdata['name']})
sampledata['value'] = np.random.randint(0, 1000, sampledata.shape[0])
sampledata.head(4)
  1. 这里基于地图随机生成一系列样本数据,如果你有特定的数据,那么数据中要包括三列。
  2. 三列分别为 lonlatvalue,分别是经纬度和对于的值,一般这个值都是正数。
  3. 至于name 其实要不要无所谓,你想展示就加,不想展示就算了。反正我这里有(主要是想分享如何在3d空间 添加文本)

地图的box

bounds_box = chinamapdata.bounds
minx = bounds_box['minx'].min()
miny = bounds_box['miny'].min()
maxx = bounds_box['maxx'].max()
maxy = bounds_box['maxy'].max()
  1. 计算地图的经纬度的范围而已,为后面画图的时候,限制x、y轴的范围。

数据转换

这个步骤是核心,因为现成的geopands、cartopy、matplotlib组合,是没办法直接画出来这种特定需求的图的。那么就需要对数据做一系列的转换。
主要步骤有:

  1. 提取地图数据的geometry。
  2. 将geometry转换成成对的数据(类似于线条的数据,要求二维的)。
  3. 把数据转换成LineCollection需要的格式。
geoms = chinamapdata.geometry
# target_projection = ccrs.PlateCarree()
# geoms = [target_projection.project_geometry(geom, target_projection)
#          for geom in geoms]paths = list(itertools.chain.from_iterable(geos_to_path(geom) for geom in geoms))# At this point, we start working around mpl3d's slightly broken interfaces.
# So we produce a LineCollection rather than a PathCollection.
segments = []
for path in paths:vertices = [vertex for vertex, _ in path.iter_segments()]vertices = np.asarray(vertices)segments.append(vertices)lc = LineCollection(segments, color='black')

开始画图

  1. 如果你是在jupyter里面写的,那这行代码可以加上,不然就可以不加。
%matplotlib widget
  1. 主要画图部分
# part 1
segments = []
for path in paths:vertices = [vertex for vertex, _ in path.iter_segments()]vertices = np.asarray(vertices)segments.append(vertices)# with plt.style.context('fivethirtyeight'):fig = plt.figure()
ax = Axes3D(fig, xlim=[minx, maxx], ylim=[miny, maxy])
# ax.set_zlim(bottom=0)lc = LineCollection(segments, color='black',linewidths=1)ax.add_collection3d(lc)ax.bar3d(x=sampledata['lon'], y=sampledata['lat'], z=np.zeros_like(sampledata['value']),dx=np.ones_like(sampledata['value']), dy=np.ones_like(sampledata['value']), dz=sampledata['value'],alpha=0.8)for index, iterrow in sampledata.iterrows():ax.text(iterrow['lon'], iterrow['lat'], iterrow['value']+2,iterrow['name'], color='green',size=9)ax.text(80, 30, 1000, '公众号: world of statistics', size=20, color='gray')ax.set_xlabel('经度')
ax.set_ylabel('维度')
# ax.set_xlim([minx, maxx])
# ax.set_ylim([miny, maxy])
ax.set_zlabel('value')# ax.set_title("公众号: world of statistics")plt.show()

效果如下:

地图区域填充

如果你希望可以对区域填充,只需要稍微更改几行代码即可.

# geoms
# part 2fig = plt.figure()
ax = Axes3D(fig, xlim=[minx, maxx], ylim=[miny, maxy])concat = lambda iterable: list(itertools.chain.from_iterable(iterable))
polys = concat(path.to_polygons() for path in paths)lc = PolyCollection(polys, edgecolor='black',facecolor='green', closed=False, alpha=0.4)ax.add_collection3d(lc)ax.bar3d(x=sampledata['lon'], y=sampledata['lat'], z=np.zeros_like(sampledata['value']),dx=np.ones_like(sampledata['value']), dy=np.ones_like(sampledata['value']), dz=sampledata['value'],alpha=0.8)ax.text(80, 30, 1000, '公众号: world of statistics', size=20, color='gray')ax.set_xlabel('经度')
ax.set_ylabel('维度')
# ax.set_xlim([minx, maxx])
# ax.set_ylim([miny, maxy])
ax.set_zlabel('value')# ax.set_title("公众号: world of statistics")plt.show()

效果如下:

整体的感觉是:如果地图填充了颜色,其实还好看一点。

完整代码

本文章的代码全部在GitHub上免费分享

  1. 链接为:https://github.com/yuanzhoulvpi2017/tiny_python/tree/main/map
  2. 文件为01开头的ipynb文件。

地图还可以这么画_3D版相关推荐

  1. 版是什么_雕版研习 | 什么是版画?版是画的母亲,画是版的子女

    一个简单的问题:什么是版画? 版画是名词,有版即可成画."版"是"画"的母亲,"画"是"版"的子女,画家则做了当然的父亲 ...

  2. 还在用Navicat破解版吗?资深DBA推荐的八款SQL工具,免费又简单!

    如今,学习SQL语言的越来越越多,不仅仅有未出校门的高校学生,还有希望取数不求人的职场人士.但是,传统客户端SQL工具在安装.配置等各环节的繁琐流程,还有高昂的价格,让很多学习者望而生畏,那潜台词是- ...

  3. Echart + 百度地图实现区域聚合(Vue版)

    Echart + 百度地图实现区域聚合(Vue版) 百度地图的聚合很简单,但是根据区域聚合怎么实现呢?结合Echart的百度地图怎么实现区域聚合呢? 单独玩过Echart,也单独用过百度地图,但是两个 ...

  4. 我的世界java版tp_我的世界原来还存在边界?Java版边界穿越方法

    原标题:我的世界原来还存在边界?Java版边界穿越方法 大家好,我是小豆. 在我的世界里,有一个神秘的地方.实体过去之后会死亡,包括玩家.没错,这就是边界.今天我们讲一讲我的世界边界的穿越方法. ① ...

  5. 2012年中国移动地图和导航市场研究报告简版

    2019独角兽企业重金招聘Python工程师标准>>> 2012年中国移动地图和导航市场研究报告简版 2012年中国移动地图和导航市场用户规模为2.53亿人,增长率为62.2%.伴随 ...

  6. 【葡萄城报表】还在为画“类Word文档报表”而发愁吗?

    [葡萄城报表]还在为画"类Word文档报表"而发愁吗? ​Word 是非常强大的文档编辑工具,一些行业制式文档都是使用Word来创建的,像教育行业的申请表,履历表,审批表等,像石油 ...

  7. 各系地图坐标互相转换【JS版和Java版】

    各系地图坐标互相转换[JS版和Java版] 坐标说明 1.(地球坐标)美国GPS使用的是WGS84的坐标系统,以经纬度的形式来表示地球平面上的某一个位置. 2.(火星坐标)我国,出于国家安全考虑,国内 ...

  8. 还在动手画棋盘 ?20分钟带你用Java写一个井字棋!

    还在动手画棋盘 ?20分钟带你用Java写一个井字棋! 文章目录 还在动手画棋盘 ?20分钟带你用Java写一个井字棋! 前言 设计过程 1.创建窗体类MyGameWindow 2.创建窗体的构造器 ...

  9. 【码绘】p5.js画Q版自画像

    [码绘]p5.js画Q版自画像 来自互动媒体作业的实验二,这次没有采用processing,而选择了p5.js,原因是用p5.js的在线编辑实时浏览比较方便. 先看一下最后的成果吧 我的实验过程: 手 ...

最新文章

  1. Windows 7的VPC虚拟机自动不与主机时间同步的解决办法
  2. C# 实现多线程的同步方法详解
  3. 算法与数据结构——并查集
  4. 中北大学和陕西科技大学计算机专业,西北地区两所重点大学,中北大学和陕西科技大学...
  5. 李沐老师的《动手学深度学习PyTorch》中的d2lzh_python包的安装
  6. linux tar 命令 详解
  7. as 使用类模拟枚举类
  8. Servlet打印HTML页面乱码问题
  9. ORA-27101: shared memory realm does not exist 错误的处理(ORA-01034 - Oracle not available )
  10. 老人为啥怒砸30辆车
  11. php vendor 删除,composer update删除第三方库的问题
  12. android 模仿今日头条ViewPager+TabLayout
  13. 小心你的Schedule task
  14. InfoPath 教程
  15. P1107 [BJWC2008]雷涛的小猫
  16. 机器人视觉测量与控制
  17. 小程序如何获取用户名和头像?
  18. 高三计算机教学总结,2021年高三信息技术教学工作总结范文.doc
  19. 亲身试验之后,我差点被微博上的兼职广告骗到三和
  20. 如何用ggplot2绘制漂亮的统计图形

热门文章

  1. 消灭星星android,消灭星星安卓版
  2. 蓝桥杯刷题冲刺 | 倒计时14天
  3. IE6下图片的浏览剪裁与上传
  4. 解读手机拍照的各个参数(延时摄影)
  5. 【汇正财经】成交量的三种表达方式
  6. RTX 3080和RTX 2080 Ti哪个好
  7. 贪婪洞窟2 素材解密
  8. 如何为勒索软件攻击做准备?
  9. Android下监听返回键、home键、任务键
  10. 计算机组装评分标准,计算机组装与配置技能竞赛评分标准表.doc