6 votos

¿Aplicar un renderizador graduado a un polígono usando PyQGIS 3?

Estoy tratando de simbolizar una capa de polígono utilizando una rampa de color graduada, sin éxito.

En el campo de atributos de mi capa tengo una columna: 'PatCNT' con valores enteros de 2 a 6 para cada fila.

He estado tratando de adaptar el código de QGIS v2.x de ¿Aplicar el renderizador graduado en PyQGIS? o de Libro de cocina de programación en python de QGIS (también para QGIS 2.x) Estoy tratando de utilizar los ejemplos de la Libro de cocina de PyQGIS que describe cómo utilizar el renderizador de símbolos graduados . He copiado más o menos el código del ejemplo del libro de cocina de abajo y he intentado adaptarlo a mi caso.

from qgis.PyQt import QtGui
from qgis.core import *

uri = '/Users/ep9k/Desktop/SandraMonson/TestZips.shp'

myVectorLayer = QgsVectorLayer(uri, 'testZipCodes', 'ogr')
myTargetField = 'PatCNT'
myRangeList = []
myOpacity = 1

#Make our first symbol and range
myMin = 2.0
myMax = 4.0
myLabel = 'Group 1'
myColor = QtGui.QColor(Qt.red)
mySymbol1 = QgsSymbol.defaultSymbol(myVectorLayer.geometryType())
mySymbol1.setColor(myColor)
mySymbol1.setOpacity(myOpacity)
myRange1 = QgsRendererRange(myMin, myMax, mySymbol1, 
myVectorLayer.geometryType())
myRangeList.append(myRange1)

#now make another symbol and range
myMin = 4.1
myMax = 6.0
myLabel = 'Group 2'
myColor = QtGui.QColor(Qt.blue)
mySymbol2 = QgsSymbol.defaultSymbol(myVectorLayer.geometryType())
mySymbol2.setColor(myColor)
mysymbol2.setOpacity(myOpacity)
myRange2 = QgsRendererRange(myMin, myMax, mySymbol2, myLabel)
myRangeList.append(myRange2)

myRenderer = QgsGraduatedSymbolRenderer('', myRangeList)
myRenderer.setMode(QgsGraduatedSymbolRenderer.EqualInterval)
myRenderer.setClassAttribute(myTargetField)
myVectorLayer.setRenderer(myRenderer)
QgsProject.instance().addMapLayer(myVectorLayer)

Por ahora sólo intento que el "grupo 1" esté en rojo y el "grupo 2" en azul. Luego puedo personalizarlo más en el futuro si quiero.

Dependiendo de lo que cambie, recibo uno de los muchos mensajes de error...

8voto

Erich Purpur Puntos 26

Voy a responder a mi propia pregunta de dos maneras.

En primer lugar, utilizaré el ejemplo del Libro de recetas para desarrolladores de PyQGIS . Al principio tuve problemas con este ejemplo, pero al final conseguí que funcionara, así que aquí hay un ejemplo simplificado con algunas anotaciones y comentarios adicionales. Yo codifiqué algunos valores que usted puede querer adaptar.

Aquí está el código completo como ejemplo:

uri = '/Users/ep9k/Desktop/SandraMonson/TestZips.shp'
join_layer = iface.addVectorLayer(uri, 'Patients by Zip Code', 'ogr')
target_field = 'PatCNT'

myRangeList = []

symbol = QgsSymbol.defaultSymbol(join_layer.geometryType())
symbol.setColor(QColor("#f5c9c9"))
myRange = QgsRendererRange(0, 1, symbol, 'Group 1')
myRangeList.append(myRange)

symbol = QgsSymbol.defaultSymbol(join_layer.geometryType())
symbol.setColor(QColor("#f97a7a"))
myRange = QgsRendererRange(1.1, 2, symbol, 'Group 2')
myRangeList.append(myRange)

myRenderer = QgsGraduatedSymbolRenderer(target_field, myRangeList)
myRenderer.setMode(QgsGraduatedSymbolRenderer.Custom)

join_layer.setRenderer(myRenderer)

Vamos a desglosar este ejemplo y empezaré por las tres primeras líneas.

uri = '/Users/ep9k/Desktop/SandraMonson/TestZips.shp'
join_layer = iface.addVectorLayer(uri, 'Patients by Zip Code', 'ogr')
target_field = 'PatCNT'

La uri es la ruta de acceso a su capa. 'Pacientes por código postal' es el nombre dado en el panel de capas de QGIS. 'ogr' se utiliza normalmente con archivos shapefiles. iface.addVectorLayer añade la capa dada por la uri en su mapa. Se puede sustituir esta función por QgsVectorLayer() para trabajar con una capa ya existente en el mapa. El campo_destino es el campo que se quiere simbolizar en la tabla de atributos de su shapefile.

myRangeList = []

symbol = QgsSymbol.defaultSymbol(join_layer.geometryType())
symbol.setColor(QColor("#f5c9c9"))
myRange = QgsRendererRange(0, 1, symbol, 'Group 1')
myRangeList.append(myRange)

myRangeList almacenará valores de simbología para cada grupo de datos. symbol es una variable que almacena el tipo de geometría de la capa, que en mi caso es un polígono. El tuyo puede ser una línea o un punto (marcador). Inserte una declaración de impresión aquí si quiere determinar cuál es la suya. A continuación, establezco el color para este tipo de geometría. Aquí utilicé una cadena hexadecimal ("#f5c9c9") que es un color rosado.

A continuación, crea miRango. Esto crea un QgsRendererRange que toma los siguientes argumentos: (valor mínimo, valor máximo, color, etiqueta). Puedes ver que aquí he codificado el valor mínimo, máximo y la etiqueta. El color ya lo definí y almacené en el símbolo. Usted puede hacer algo más avanzado aquí para calcular el mínimo y el máximo. Por último, añado esto a myRangeList.

Note que hice esto una segunda vez en mi ejemplo. myRangeList ahora contiene dos objetos, el primero es para los valores 0-1, el segundo es para los valores 1.1-2. Usted puede hacer tantas rupturas en su conjunto de datos como quiera aquí. Este es un ejemplo personalizado (más abajo), pero también podría utilizar Natural Breaks, Jenks, etc.

myRenderer = QgsGraduatedSymbolRenderer(target_field, myRangeList)
myRenderer.setMode(QgsGraduatedSymbolRenderer.Custom)

join_layer.setRenderer(myRenderer)

Ahora vamos a implementar lo que hemos hecho. myRenderer crea un objeto que almacena el objeto QgsGraduatedSymbolRenderer con el nombre del campo (target_field) y myRangeList (que almacena los valores de QgsRendererRange para cada ruptura) como argumentos. A continuación, definimos el modo como "custom". Como se ha dicho antes, se pueden utilizar modos preexistentes como Jenks, Natural Breaks, etc.

Por último, necesitas renderizar tu capa y aplicar la simbología graduada. join_layer.setRenderer(myRenderer) hace esto.

\~~~~~~~~

Segundo, He encontrado en este hilo, que es para QGIS 2.x y anteriores que he adaptado a la 3.x, pero que sirve como un ejemplo personalizado muy bonito con funciones extra para validar los tipos de geometría, etc.

from PyQt5.QtGui import *

target_field = 'PatCNT'
layer = QgsVectorLayer('/Users/ep9k/Desktop/SandraMonson/TestZips.shp', 
'Fixed Divisions', 'ogr')

def validatedDefaultSymbol(geometryType):
    symbol = QgsSymbol.defaultSymbol(geometryType)
    if symbol is None:
        if geometryType == Qgis.Point:
            symbol = QgsMarkerSymbol()
        elif geometryType == Qgis.Line:
            symbol = QgsLineSymbol()
        elif geometryType == Qgis.Polygon:
            symbol = QgsFillSymbol()
    return symbol

def makeSymbologyForRange(layer, min, max, title, color):
    symbol = validatedDefaultSymbol(layer.geometryType())
    symbol.setColor(color)
    range = QgsRendererRange(min, max, symbol, title)
    return range

def applySymbologyFixedDivisions(layer, field):
    rangeList = []
    rangeList.append( makeSymbologyForRange(layer, 2, 4, '2-4', 
QColor("Green") ) )
    rangeList.append( makeSymbologyForRange(layer, 4.1, 6, '4-6',  
QColor("Purple") ) )
    renderer = QgsGraduatedSymbolRenderer(field, rangeList)
    renderer.setMode(QgsGraduatedSymbolRenderer.Custom)
    layer.setRenderer(renderer)

if layer.isValid():
    applySymbologyFixedDivisions(layer, target_field)
    QgsProject.instance().addMapLayer(layer)

La falta de ejemplos de QGIS 3.x me resultó difícil de navegar, así que espero que esto te sirva. No soy un experto, así que por favor edite esta respuesta y comente lo que sea necesario.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X