资料表连接 (PyQGIS)

本教学示范如何在 QGIS 中利用 Python 脚本 (PyQGIS) 操作资料表连接,并为输出的图层进行渐层样式设定。我们要重复一次在 资料表连接 中进行的步骤,但这一次会只使用 python 脚本来操作。

内容说明

请参考 资料表连接 的教学说明。

你还会学到这些

  • 利用 Python 载入压缩的图层到 QGIS 中

  • 使用 QgsGraduatedSymbolRendererV2 为向量图层设定渐层样式

取得资料

请下载以下资料至电脑中:

tl_2013_06_tract.zip

ca_tracts_pop.csv

ca_tracts_pop.csvt

资料来源 [TIGER] [USCENSUS]

操作流程

你可以在 Python 主控台 或是 QGIS 内建的 编辑器 中输入以下指令。

  1. 第一步是载入 shapefile,我们要的档案包含在档名含有 tract.zip 的压缩档中。虽然我们可以解压缩然后载入 shapefile,不过 OGR 提供元(provider,这里就是 QGIS)也可以经由虚拟的档案系统直接载入 shapefile。只要在路径最前端加上 /vsizip/ 之后,就能够载入 zip 格式的 shapefile。

注解

zip_uri 在 Linux 和 Mac 系统上的前缀是 /vsizip//(注意多出来的 /)

zip_uri = '/vsizip/C:/Users/Ujaval/Downloads/tl_2013_06_tract.zip'
shp =  QgsVectorLayer(zip_uri, 'tl_2013_06_tract', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(shp)
../_images/1178.png
  1. 接下来载入 CSV 档。由于 CSV 档不包含任何空间资讯,我们要使用 delimitedtext 做为资料提供元,载入成表格。

csv_uri = 'file:///C:/Users/Ujaval/Downloads/ca_tracts_pop.csv?delimiter=,'
csv = QgsVectorLayer(csv_uri, 'ca_tracts_pop', 'delimitedtext')
QgsMapLayerRegistry.instance().addMapLayer(csv)
../_images/2136.png
  1. 开始进行资料表连接。在 QGIS 中此操作要使用 QgsVectorJoinInfo 物件,而且我们需要指定 CSV 图层中的 GEO.id2 作为 连结栏位,以及 shapefile 图层中的 GEOID 作为 目标栏位。执行下列程式码后,shapefile 的图层就会多出一个从 CSV 图层连结过来的属性。

注解

当使用 QgsVectorJoinInfo 时,务必要确认两个图层都已载入至 QgsMapLayerRegistry,否则是不会有任何东西被连结的。

shpField='GEOID'
csvField='GEO.id2'
joinObject = QgsVectorJoinInfo()
joinObject.joinLayerId = csv.id()
joinObject.joinFieldName = csvField
joinObject.targetFieldName = shpField
joinObject.memoryCache = True
shp.addJoin(joinObject)
../_images/375.png
  1. 另一个较简单,而且也较为推荐的方法是使用「处理框架」。你可以呼叫 qgis:joinattributestable 演算法来创造连接完毕的图层。

注解

我们这边使用的是 processing.runandload() 方法,而不是较常见的 processing.runalg() 来执行演算法,这是因为我们想要把执行的结果图层也加到 QGIS 中,使用 processing.runandload() 是较方便的选择。

import processing
shpField='GEOID'
csvField='GEO.id2'
result = processing.runandload('qgis:joinattributestable', shp, csv, shpField, csvField, None)
../_images/453.png
  1. 在本教学剩馀的部分中,我们会继续使用第一种利用 QgsVectorJoinInfo 的方法。接下来我们要来为连接后的图层设定渐层样式。在连接后的图层中,人口的栏位是 ca_tracts_pop_D001,我们要使用 QgsGraduatedSymbolRendererV2,在 分位数 模式下设定渐层样式,相关的颜色和数值范围设定请参考 资料表连接

from PyQt4 import QtGui

myColumn = 'ca_tracts_pop_D001 '
myRangeList = []
myOpacity = 1

ranges = []

myMin1 = 0.0
myMax1 = 3157.2
myLabel1 = 'Group 1'
myColor1 = QtGui.QColor('#f7fbff')
ranges.append((myMin1, myMax1, myLabel1, myColor1))

myMin2 = 3157.2
myMax2 = 4019.0
myLabel2 = 'Group 2'
myColor2 = QtGui.QColor('#c7dcef')
ranges.append((myMin2, myMax2, myLabel2, myColor2))

myMin3 = 4019.0
myMax3 = 4865.8
myLabel3 = 'Group 3'
myColor3 = QtGui.QColor('#72b2d7')
ranges.append((myMin3, myMax3, myLabel3, myColor3))

myMin4 = 4865.8
myMax4 = 5996.4
myLabel4 = 'Group 4'
myColor4 = QtGui.QColor('#2878b8')
ranges.append((myMin4, myMax4, myLabel4, myColor4))

myMin5 = 5996.4
myMax5 = 37452.0
myLabel5 = 'Group 5'
myColor5 = QtGui.QColor('#08306b')
ranges.append((myMin5, myMax5, myLabel5, myColor5))

for myMin, myMax, myLabel, myColor in ranges:
  mySymbol = QgsSymbolV2.defaultSymbol(shp.geometryType())
  mySymbol.setColor(myColor)
  mySymbol.setAlpha(myOpacity)
  myRange = QgsRendererRangeV2(myMin, myMax, mySymbol, myLabel)
  myRangeList.append(myRange)

myRenderer = QgsGraduatedSymbolRendererV2('', myRangeList)
myRenderer.setMode(QgsGraduatedSymbolRendererV2.Quantile)
myRenderer.setClassAttribute(myColumn)

shp.setRendererV2(myRenderer)
../_images/554.png
  1. 在 Python 主控台中直接输入程式码,对于执行小型的工作非常方便,不过对于以上的程式片段,使用内建的 编辑器 会容易得多。你可以复制整段程式码然后贴上到 编辑器 中,然后按下 执行,当脚本执行完毕后,资料表连接和样式设定就完成了,不需要多馀的手动操作。

../_images/652.png

以下放上完整的 join_attributes.py 档做为参考。

from PyQt4 import QtGui
zip_uri = '/vsizip/C:/Users/Ujaval/Downloads/tl_2013_06_tract.zip/tl_2013_06_tract.shp'
shp =  QgsVectorLayer(zip_uri, 'tl_2013_06_tract', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(shp)

csv_uri = "file:///C:/Users/Ujaval/Downloads/ca_tracts_pop.csv?delimiter=,"
csv = QgsVectorLayer(csv_uri, "ca_tracts_pop", "delimitedtext")
QgsMapLayerRegistry.instance().addMapLayer(csv)

shpField='GEOID'
csvField='GEO.id2'
joinObject = QgsVectorJoinInfo()
joinObject.joinLayerId = csv.id()
joinObject.joinFieldName = csvField
joinObject.targetFieldName = shpField
joinObject.memoryCache = True
shp.addJoin(joinObject)

myColumn = 'ca_tracts_pop_D001 '
myRangeList = []
myOpacity = 1

ranges = []

myMin1 = 0.0
myMax1 = 3157.2
myLabel1 = 'Group 1'
myColor1 = QtGui.QColor('#f7fbff')
ranges.append((myMin1, myMax1, myLabel1, myColor1))

myMin2 = 3157.2
myMax2 = 4019.0
myLabel2 = 'Group 2'
myColor2 = QtGui.QColor('#c7dcef')
ranges.append((myMin2, myMax2, myLabel2, myColor2))

myMin3 = 4019.0
myMax3 = 4865.8
myLabel3 = 'Group 3'
myColor3 = QtGui.QColor('#72b2d7')
ranges.append((myMin3, myMax3, myLabel3, myColor3))

myMin4 = 4865.8
myMax4 = 5996.4
myLabel4 = 'Group 4'
myColor4 = QtGui.QColor('#2878b8')
ranges.append((myMin4, myMax4, myLabel4, myColor4))

myMin5 = 5996.4
myMax5 = 37452.0
myLabel5 = 'Group 5'
myColor5 = QtGui.QColor('#08306b')
ranges.append((myMin5, myMax5, myLabel5, myColor5))

for myMin, myMax, myLabel, myColor in ranges:
    mySymbol = QgsSymbolV2.defaultSymbol(shp.geometryType())
    mySymbol.setColor(myColor)
    mySymbol.setAlpha(myOpacity)
    myRange = QgsRendererRangeV2(myMin, myMax, mySymbol, myLabel)
    myRangeList.append(myRange)

myRenderer = QgsGraduatedSymbolRendererV2('', myRangeList)
myRenderer.setMode(QgsGraduatedSymbolRendererV2.Quantile)
myRenderer.setClassAttribute(myColumn)

shp.setRendererV2(myRenderer)