PyQGIS开发-使用 QGIS 创建仪表板样式的地图布局
迪丽瓦拉
2025-05-29 21:00:14
0

前言

创建数据驱动的地图并不难,QGIS 可以轻松帮助您创建它。 QGIS 有很多很棒的功能可以从各种数据源创建好的地图。 您可以将图表、图像、文本作为附加元素与布局中的地图一起添加,以丰富您的地图,使其具有仪表板元素。

1、解决方法

QGIS 支持 python 脚本来扩展其核心功能。 它给了我们很多优势。 Python 易于使用,有支持性的社区,它有数百个不同的库,这些库在节省执行图像处理、数据可视化、机器学习等特定任务的时间方面非常有用。

在我们的例子中,我们将使用 python 库来处理表格数据并创建图表,这些图表是 Pandas 和 Matplotlib 以及 PyQGIS 本身来访问 QGIS 中的核心功能。 Python 需要自动化整个过程,从读取数据源、过滤和操作数据、创建图表、将它们添加到布局,最后导出到 PDF 文件。

我假设您已经熟悉 QGIS 并且具备非常基本的 Python 编程知识,可以按照本教程进行操作。

2、数据

对于本教程,我只需要两个图层:作为主题图层的动态数据和底图图层。

  • earthquakes events from USGS (find the data here : https://earthquake.usgs.gov/earthquakes/search/)

  • basemap voyager from Carto (https://carto.com/blog/new-voyager-basemap/)

当然,你需要 QGIS,以及一些 python 库:Pandas 和 Matplotlib 要安装在你的计算机上。 我们将在 QGIS 环境中运行这些 python 库。 不幸的是,QGIS 本身并不提供这些库,所以你必须手动安装它们。 如果你需要在 QGIS 环境中安装 python 库的指导,你可以阅读这篇文章。

3、实现过程

(1)创建布局模板

这个布局模板很像容器,用于安排信息 如图表、地图、标签值 将被显示。 它的布局组成将帮助我们稍后在编写 python 脚本时定义正确的位置来绘制布局信息。

QGIS 布局模板

(2)准备工作区目录

创建目录以组织本教程的输入和输出文件。

D:\PLAYGROUND\MAP-DASHBOARD
|   create_map.py
|   LICENSE
|   README.md
|   utils.py
|
+---data
|       Carto-Voyager.xml
|       earthquakes_2019.csv
|       earthquakes_2019.csvt
|       style_gempa.qml
|
+---img
|       pyqgis.svg
|       report_template_A4.qpt
|       usgs-logo.jpg
|
\---report

(3)读取数据并将其加载到画布

这部分是关于导入所需的库、定义输入和输出数据、读取数据并加载到画布以及将预定义样式应用于图层。

import pandas as pd
import datetime as dt
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib as mpl
import time
  • 定义输入和输出

path = “D:\playground\map-dashboard”
file_basemap = os.path.join(path,”data\Carto-Voyager.xml”)
file_csv = os.path.join(path,”data\earthquakes_2019.csv”)
style_layer_gempa = os.path.join(path,”data\style_gempa.qml”)
qpt_path = os.path.join(path,”img/report_template_A4.qpt”)
output_pdf = os.path.join(path,”report/report_A4.pdf”)
#CRS definition
wgs84 = QgsCoordinateReferenceSystem(4326)
  • 加载数据到 QGIS 画布

#Add layer to canvas
layer_basemap = iface.addRasterLayer(file_basemap, "", "gdal")
layer_gempa = iface.addVectorLayer(file_csv, "csv", "ogr")
layer_gempa.setCrs(wgs84, True)
#apply style to layer gempa
layer_gempa.loadNamedStyle(style_layer_gempa)
layer_gempa.triggerRepaint()

(4)数据处理和图表生成

#Create Pandas DataFrame for statistics
df = pd.read_csv(file_csv,sep=';')
df['datetime'] = pd.to_datetime(df['time'], format='%Y-%m-%dT%H:%M:%S.%fZ') #convert string as datetime format
df2019 = df[(df['datetime']>dt.date(2019,1,1)) & (df['datetime']

我们需要将 csv 文件转换为 pandas 数据框。 Pandas真的很强大,我们会得到更多pandas特性的优势来处理原始数据表。 它还擅长处理大数据。

该图表将根据 pandas 数据框中的数据生成。

(5)加载模板并打印到布局

###LAYOUT COMPOSING
document = QDomDocument()
project = QgsProject.instance()
composition = QgsPrintLayout(project)layout = QgsLayout(project)
layout.initializeDefaults()
# read template content
# read template content
template_file = open(qpt_path)
#template_content = template_file.read()
#template_file.close()
document.setContent(template_content)
items, ok = layout.loadFromTemplate(document, QgsReadWriteContext(), False)# load layout from template and add to Layout Manager
composition.loadFromTemplate(document, QgsReadWriteContext())
project.layoutManager().addLayout(composition)
layout = project.layoutManager().layoutByName("Report A4")
#add map to layout
map = QgsLayoutItemMap(layout)
map.setRect(20, 20, 20, 20)#get extent from layer gempa
ext = layer_gempa.extent()
map.setExtent(ext)
layout.addLayoutItem(map)
map.setFrameStrokeWidth(QgsLayoutMeasurement(0.2,QgsUnitTypes.LayoutMillimeters))
map.attemptMove(QgsLayoutPoint(9.275, 22, QgsUnitTypes.LayoutMillimeters))
map.attemptResize(QgsLayoutSize(191.118, 88, QgsUnitTypes.LayoutMillimeters))
scale = map.scale()# call functions in utils
sys.path.append(path)
from utils import *# add label max_mag, avg_depth, count_eq
addLabel(layout, str(max_mag), 'Arial', 36, QFont.Bold, False, '#21908d', 0,0, 28.852, 125) #Magnitude  label
addLabel(layout, str(round(avg_depth,2)), 'Arial', 36, QFont.Bold, False, '#21908d', 0,0, 93, 125) #Depth  label
addLabel(layout, str(count_eq), 'Arial', 36, QFont.Bold, False, '#21908d', 0,0, 156, 125) #Magnitude  label# add chart 1
addImage(layout,chart_count_mag,10, 175, 190, 34) #chart1: donut chart dumping point
addImage(layout,chart_avg_depth,10, 237, 190, 34) #chart1: donut chart dumping point# export layout to file 
# creats a QgsLayoutExporter object
exporter = QgsLayoutExporter(layout)
settings = exporter.PdfExportSettings()
settings.rasterizeWholeImage = False
#this exports a pdf of the layout object
exporter.exportToPdf(output_pdf, settings)
exporter.exportToImage('D:/playground/map-dashboard/report/report_A4.png', QgsLayoutExporter.ImageExportSettings())

打开 QGIS 并打开 Python 控制台面板或使用快捷键 (Ctrl + Alt + P)。 单击打开脚本按钮以加载您刚刚创建的 python 脚本,然后运行它,就可以得到上面类似仪表盘的布局。

后续考虑把完整资料放出来:https://github.com/gwisnu/map-dashboard

相关内容