Graded Renderer in PyQGIS anwenden? [geschlossen]

9

Versuchen Sie einfach, den folgenden Code auszuführen, der bereits im pyqgis-Kochbuch enthalten ist, um eine Symbologie für abgestufte Farben zu erstellen (wie im Beispiel mit 2 Klassen).

Ich definiere die Quellinformationen für das Shapefile, aber wenn ich den Code in meinem Test-Plugin ausführe, wird nur die Ebene hinzugefügt, ohne sie zu klassifizieren. Fügt wie gewohnt hinzu, alle Polylinien erscheinen gleich.

Irgendeine Lösung oder Arbeitscode / Methode?

Link zum Code im Kochbuch http://www.qgis.org/pyqgis-cookbook/vector.html#graduated-symbol-renderer

from qgis.core import  (QgsVectorLayer, QgsMapLayerRegistry, QgsGraduatedSymbolRendererV2, QgsSymbolV2,QgsRendererRangeV2)

myVectorLayer = QgsVectorLayer('C:/my_test_shape_file.shp', 'test_shp_file', 'ogr')

myTargetField = 'target_field'
myRangeList = []
myOpacity = 1

# Make our first symbol and range...
myMin = 0.0
myMax = 50.0
myLabel = 'Group 1'
myColour = QtGui.QColor('#ffee00')
mySymbol1 = QgsSymbolV2.defaultSymbol(myVectorLayer.geometryType())
mySymbol1.setColor(myColour)
mySymbol1.setAlpha(myOpacity)
myRange1 = QgsRendererRangeV2(myMin, myMax, mySymbol1, myLabel)
myRangeList.append(myRange1)

#now make another symbol and range...
myMin = 50.1
myMax = 100
myLabel = 'Group 2'
myColour = QtGui.QColor('#00eeff')
mySymbol2 = QgsSymbolV2.defaultSymbol(myVectorLayer.geometryType())
mySymbol2.setColor(myColour)
mySymbol2.setAlpha(myOpacity)
myRange2 = QgsRendererRangeV2( myMin, myMax, mySymbol2, myLabel)
myRangeList.append(myRange2)

myRenderer = QgsGraduatedSymbolRendererV2('', myRangeList)
myRenderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval)
myRenderer.setClassAttribute(myTargetField)
myVectorLayer.setRendererV2(myRenderer)
QgsMapLayerRegistry.instance().addMapLayer(myVectorLayer) 

@ Kellys Code funktioniert perfekt.

Ich habe jedoch festgestellt, dass sowohl der Code (einer, den ich in meiner ersten Nachricht eingegeben habe, als auch Ihr Code in der zweiten Nachricht) NICHT in QGIS v1.7.3 funktioniert, sondern in QGIS v1.8.0 funktioniert. Ich denke, dies war ein Fehler (?), Der bereits in Version 1.8.0 behoben wurde

Und noch eine Frage;

Haben Sie einen Beispielcode für die (natürliche Unterbrechungen, Jenks) Klassifizierung des "numeric_attribute_field" basierend auf der angegebenen Anzahl von Klassen (dh die Anzahl der Klassen wird eine Variable im Code sein, sagen Sie "n", und ich werde das von der übergeben Plugin GUI dh n = spinBox.value ())

cempro
quelle
1
Bitte lesen Sie die Hilfe zum Formatieren des Codes für diese Site. Diesmal habe ich es für dich behoben.
Nathan W

Antworten:

19

Welche Art von Ebene verwenden Sie?

Ich fand heraus, dass ich mit der Punktebene die folgende zurückgegebene Zeile verwendete None

mySymbol1 = QgsSymbolV2.defaultSymbol(myVectorLayer.geometryType())

Dies könnte jedoch behoben werden, indem es durch einen Aufruf der validatedDefaultSymbolMethode aus dem folgenden Code ersetzt wird. Die Grundvoraussetzung ist, anzurufen QgsSymbolV2.defaultSymbol()und dann zu validieren und bei Bedarf Korrekturen vorzunehmen.

Bearbeiten: Änderungen, um die Kompatibilität mit QGIS 1.8 und dem aktuellen Master sicherzustellen (27.01.13); erweitert auf eine Reihe von Beispielen mit größerem Umfang.

Die folgenden Snippets sind so formatiert, dass sie in die Python-Konsole eingefügt und auf Natural Earth Data 1: 10m besiedelte Orte angewendet werden können, die hier verfügbar sind . Beachten Sie, dass die späteren Snippets von Definitionen und Importen aus dem ersten abhängig sind.

1) Dies ist ein Beispiel für das Anwenden von benutzerdefinierten, aber fest codierten Kategorien auf eine bestimmte Ebene.

from PyQt4.QtGui import *

def validatedDefaultSymbol( geometryType ):
    symbol = QgsSymbolV2.defaultSymbol( geometryType )
    if symbol is None:
        if geometryType == QGis.Point:
            symbol = QgsMarkerSymbolV2()
        elif geometryType == QGis.Line:
            symbol =  QgsLineSymbolV2 ()
        elif geometryType == QGis.Polygon:
            symbol = QgsFillSymbolV2 ()
    return symbol

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

def applySymbologyFixedDivisions( layer, field ):
    rangeList = []
    rangeList.append( makeSymbologyForRange( layer, -99, 999999.9, '<1 Million', QColor("Green") ) )
    rangeList.append( makeSymbologyForRange( layer, 1000000, 10000000, '1-10 Million',  QColor("Purple") ) )
    rangeList.append( makeSymbologyForRange( layer, 10000000.1, 100000000, '>10 Million', QColor("Orange") ) )
    renderer = QgsGraduatedSymbolRendererV2( field, rangeList )
    renderer.setMode( QgsGraduatedSymbolRendererV2.Custom )
    layer.setRendererV2( renderer )

targetField = 'POP_OTHER'
layer = QgsVectorLayer( 'C:/data/ne_10m_populated_places.shp', 'Fixed Divisions', 'ogr' )
if layer.isValid():
    applySymbologyFixedDivisions( layer, targetField )
    QgsMapLayerRegistry.instance().addMapLayers( [layer] )

2) Dieses Beispiel gilt wiederum für jeden der von QgsGraduatedSymbolRendererV2 unterstützten Standardmodi. Der Klassenwert wird als Hinweis und nicht als Regel behandelt, wie dies für jeden bestimmten Modus erforderlich ist. Die setSizeScaleField-Zeile kann bei Bedarf nicht kommentiert werden. Die Werte der LABELRANK-Spalte sind jedoch zu groß, um bei Standardzoomstufen gut auszusehen.

def applyGraduatedSymbologyStandardMode( layer, field, classes, mode):
    symbol = validatedDefaultSymbol( layer.geometryType() )
    colorRamp = QgsVectorGradientColorRampV2.create({'color1':'255,0,0,255', 'color2':'0,0,255,255','stops':'0.25;255,255,0,255:0.50;0,255,0,255:0.75;0,255,255,255'})
    renderer = QgsGraduatedSymbolRendererV2.createRenderer( layer, field, classes, mode, symbol, colorRamp )
    #renderer.setSizeScaleField("LABELRANK")
    layer.setRendererV2( renderer )

modes = { QgsGraduatedSymbolRendererV2.EqualInterval : "Equal Interval",
          QgsGraduatedSymbolRendererV2.Quantile      : "Quantile",
          QgsGraduatedSymbolRendererV2.Jenks         : "Natural Breaks (Jenks)",
          QgsGraduatedSymbolRendererV2.StdDev        : "Standard Deviation",
          QgsGraduatedSymbolRendererV2.Pretty        : "Pretty Breaks"
        }

targetField = 'POP_OTHER'
classes = 6
for mode in modes.keys():
    layer = QgsVectorLayer('C:/data/ne_10m_populated_places.shp', modes[mode] , 'ogr')
    if layer.isValid():
        applyGraduatedSymbologyStandardMode( layer, targetField, classes, mode)
        QgsMapLayerRegistry.instance().addMapLayers( [layer] ) 

3) Dieses Beispiel zeigt das Anwenden dynamischer benutzerdefinierter Unterteilungen. In diesem Fall werden die Features nach Wert sortiert und dann in Gruppen aufgeteilt, sodass die Summe der Werte in jeder Kategorie gleich ist. dh die Weltbevölkerung in Drittel aufteilen, die an Orten der kleinsten / mittleren / größten Bevölkerung leben.

def getSortedFloatsFromAttributeTable( layer, fieldName ):
    provider = layer.dataProvider()
    fieldIndex = provider.fieldNameIndex(fieldName)
    provider.select( [fieldIndex] )
    values = []
    feature = QgsFeature()
    while provider.nextFeature( feature ):
        values.append( feature.attributeMap()[fieldIndex].toFloat()[0] )
    values.sort()
    return values

def arbitaryColor( amount, max ):
    color = QColor()
    color.setHsv( 240 * amount / float( max - 1 ), 255, 255 )
    return color

def makeGraduatedRendererFromDivisionsList( layer, fieldName, divisions ):
    classes = len( divisions ) - 1
    rangeList = []
    for i in range( classes ):
        label = str( divisions[i] ) + " < X < " + str( divisions[i+1] )
        rangeList.append( makeSymbologyForRange( layer, divisions[i] , divisions[i+1], label, arbitaryColor( i, classes ) ) )
    renderer = QgsGraduatedSymbolRendererV2( fieldName, rangeList )
    renderer.setMode( QgsGraduatedSymbolRendererV2.Custom )
    return renderer

def applySymbologyEqualTotalValue( layer, classes, fieldName):
    values = getSortedFloatsFromAttributeTable( layer, fieldName )
    total = sum( values )
    step = total / float( classes )
    nextStep = step
    divisions = [ values[0] ]
    runningTotal = 0
    for value in values:
        runningTotal += value
        if runningTotal >= nextStep:
            divisions.append( value )
            nextStep += step
    if divisions[-1] != values[-1]:
        divisions.append(values[-1])
    renderer = makeGraduatedRendererFromDivisionsList( layer, fieldName, divisions )
    layer.setRendererV2( renderer )

targetField = 'POP_OTHER'
classes = 3
layer = QgsVectorLayer( 'C:/data/ne_10m_populated_places.shp', 'Equal Total Value', 'ogr')
if layer.isValid():
    applySymbologyEqualTotalValue(layer, classes, targetField)
    QgsMapLayerRegistry.instance().addMapLayers( [layer] ) 
Kelly Thomas
quelle
Ich möchte ein paar Dinge sagen. Wenn Sie versuchen, die obige Antwort von @Kelly neu zu erstellen, müssen Sie zunächst die Datei "Bestückte Orte herunterladen" aus Kellys Link auswählen. Wenn Sie eine aktualisierte Version dieses Codes für PyQGIS 3 / QGIS 3.x sehen möchten, lesen Sie diesen Thread: gis.stackexchange.com/questions/303990/… Ich verwende ein anderes Shapefile. Aber der Code ist sehr ähnlich und Sie sollten in der Lage sein, ihm zu folgen. Einige Methoden und Dinge haben sich für QGIS 3 geändert.
Erich Purpur