4 votos

Sustituir las características nulas por características de otro campo

Tengo un shapefile poligonal con dos campos X e Y. Me gustaría crear un nuevo campo Z que informe de la característica/valor de X cuando falte Y, y de la característica de Y en caso contrario. La función en QGIS Field Calculator sería if(Y IS NULL, X, Y) . Me gustaría encontrar una manera de escribirlo en un código PyQGIS.

En PyQGIS lo he intentado:

my_layer = QgsVectorLayer(my_dir, "my_layer", "ogr")

my_layer.dataProvider().addAttributes([QgsField("Z", QVariant.String)])
my_layer.updateFields()

with edit(my_layer):
    for f in my_layer.getFeatures():
        if f["Y"] == NULL:
            my_layer.changeAttributeValue(f.id(), my_layer.fields().lookupField("Z"), f["X"])
            my_layer.updateFeature(f)
        else:
            my_layer.changeAttributeValue(f.id(), my_layer.fields().lookupField("Z"), f["Y"])
            my_layer.updateFeature(f)

pero no funciona. ¿Alguna idea sobre cómo proceder?

0 votos

¿Y si faltan los dos o ninguno?

0 votos

¿Es obligatorio PYQGIS?

1 votos

¿Has probado f["Y"] is None en lugar de f["Y"] == NULL ?

6voto

BWW Puntos 302

Puedes intentar utilizar la expresión que ya utilizas a través de la GUI pero con PyQGIS

my_layer = QgsVectorLayer(my_dir, "my_layer", "ogr")
#my_layer = iface.activeLayer()

# Add if not existing
if my_layer.fields().indexFromName('Z') == -1:
    my_layer.dataProvider().addAttributes([QgsField("Z", QVariant.String)])
    my_layer.updateFields()

expression = QgsExpression('coalesce(Y, X)')
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(my_layer))

with edit(my_layer):
    for f in my_layer.getFeatures():
        context.setFeature(f)
        f['Z'] = expression.evaluate(context)
        my_layer.updateFeature(f)

5voto

Anton8000 Puntos 165

Prueba esto:

lyr = QgsProject.instance().mapLayersByName('New scratch layer')[0]
zindex = lyr.fields().indexFromName('Z')
attrMap = {}

for f in lyr.getFeatures():
    vals = [f['X'],f['Y']]
    if None in vals: #If there are no Nones, dont set a value for Z.
        z = [v for v in vals if v][0] #"if v", is True for values that are not None or empty strings
        attrMap[f.id()] = {zindex:z}
#attrMap
#{1: {2: 'abc'}, 2: {2: '123'}}

lyr.dataProvider().changeAttributeValues(attrMap)

enter image description here

0 votos

Esto no resuelve bien la cuestión. "Si no hay Nones, no pongas un valor para Z." --> No, la pregunta dice que Z debe estar siempre establecido. Por lo tanto, incluso si X e Y no son Ninguno, Z debe obtener el valor de Y. Además, si el par [X,Y] es [0, Ninguno], debe elegir 0, pero z = [v for v in vals if v][0] no lo hará.

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