¿Reemplazar caracteres que no están en inglés en tablas de atributos usando ArcPy y Python?

9

Tengo algunos shapefiles donde algunos de los atributos contienen los caracteres no ingleses ÅÄÖ. Dado que algunas consultas no funcionan con estos caracteres (específicamente ChangeDetector ), intenté cambiarlos por adelantado con un script simple y agregar las nuevas cadenas a otro campo.

Sin embargo, el cambio de caracteres funciona bien pero no actualiza el campo con arcpy.UpdateCursor.

¿Cuál es una forma apropiada de resolver esto?

También intenté hacer esto a través de la Calculadora de campo mientras publicaba "código" en el bloque de código, con el mismo error.

Mensaje de error:
Runtime error Traceback (última llamada reciente): Archivo "", línea 1, en el Archivo "c: /gis/python/teststring.py", línea 28, en val = code (str (prow.Typkod)) UnicodeEncodeError: el códec 'ascii' no puede codificar el carácter u '\ xc4' en la posición 3: el ordinal no está en el rango (128)

Código:

# -*- coding: cp1252 -*-
def code(infield):
    data = ''
    for i in infield:
##        print i
        if i == 'Ä':
            data = data + 'AE'
        elif i == 'ä':
            data = data + 'ae'
        elif i == 'Å':
            data = data + 'AA'
        elif i == 'å':
            data = data + 'aa'
        elif i == 'Ö':
            data = data + 'OE'
        elif i == 'ö':
            data = data + 'oe'
        else:
            data = data + i
    return data


shp = r'O:\XXX\250000\DB\ArcView\shape.shp'

prows = arcpy.UpdateCursor(shp)

for prow in prows:
    val = code(unicode(str(prow.Typkod), "utf-8"))
    prow.Typkod_U = val
    print val
    prows.updateRow(prow)

Los valores de Typkod son del tipo: [D, D, S, DDRÄ, TRÄ] etc.

Yo uso ArcMap Basic (10.1) en Windows 7.


Nuevo mensaje de error:
Runtime error Traceback (última llamada más reciente): Archivo "", línea 1, en el Archivo "c: /gis/python/teststring.py", línea 29, en val = code (unicode (str (fila. Typkod), "utf-8")) UnicodeEncodeError: el códec 'ascii' no puede codificar el carácter u '\ xc4' en la posición 3: el ordinal no está en el rango (128)

>>> val 'DDRÄ'
>>> type(val) tipo 'str'


Parece que la salida de la función es incorrecta de alguna manera. Cuando hay ÅÄÖ involucrado, regresa data = u'DDR\xc4'y no (como era mi intención) data = 'DDRAE'. ¿Alguna sugerencia sobre lo que podría causar esto?

Martín
fuente

Respuestas:

7

Con demasiada frecuencia trato con caracteres especiales como el que tiene en sueco (ä, ö, å), pero también algunos que se presentan en otros idiomas como el portugués y el español (é, í, ú, ó, etc.). Por ejemplo, tengo datos en los que el nombre de la ciudad está escrito en latín simple con todos los acentos eliminados, por lo que "Gotemburgo" se convierte en "Goteborg" y "Åre" es "Are". Para realizar las uniones y unir los datos, tengo que reemplazar los acentos al carácter en inglés latino.

Solía ​​hacer esto como has mostrado en tu propia respuesta primero, pero esta lógica pronto se volvió bastante engorrosa de mantener. Ahora uso el módulo unicodedata que ya está disponible con la instalación de Python y arcpy para iterar las características.

import unicodedata
import arcpy
import os

def strip_accents(s):
   return ''.join(c for c in unicodedata.normalize('NFD', s)
                  if unicodedata.category(c) != 'Mn')

arcpy.env.workspace = r"C:\TempData_processed.gdb"
workspace = arcpy.env.workspace

in_fc = os.path.join(workspace,"FC")
fields = ["Adm_name","Adm_Latin"]
with arcpy.da.UpdateCursor(in_fc,fields) as upd_cursor:
    for row in upd_cursor:
        row[1] = strip_accents(u"{0}".format(row[0]))
        upd_cursor.updateRow(row)

Consulte el enlace para obtener más información sobre el uso del módulo unicodedata en ¿Cuál es la mejor manera de eliminar acentos en una cadena unicode de Python?

Alex Tereshenkov
fuente
Veo cómo esto podría ser útil, pero ¿qué pasa si necesitamos mantener los personajes como están? ¿podríamos hacer algo de magia para mantener esos personajes especiales?
Bogdan Mircea Stanciu
6

Resulta que iterar sobre ÅÄÖ no fue tan fácil. Se le conoce como una cadena Unicode, y cuando se registran las sentencias if que deben usarse en lugar del literal ÅÄÖ. Después de descubrirlo, el resto fue pan comido :)

Código resultante:

# -*- coding: cp1252 -*-
def code(infield):
    data = ''
    for i in infield:
##        print i
        if i == u'\xc4': 
            data = data + 'AE'
        elif i == u'\xe4': 
            data = data + 'ae'
        elif i == u'\xc5': 
            data = data + 'AA'
        elif i == u'\xe5': 
            data = data + 'aa'
        elif i == u'\xd6': 
            data = data + 'OE'
        elif i == u'\xf6': 
            data = data + 'oe'
        else:
            data = data + i
    return data


shp = arcpy.GetParameterAsText(0)
field = arcpy.GetParameterAsText(1)
newfield = field + '_U'
arcpy.AddField_management(shp, newfield, 'TEXT')

prows = arcpy.UpdateCursor(shp)

for row in prows:
    row.newfield = code(row.field)
    prows.updateRow(row)
Martín
fuente
1

Vea si lo siguiente funciona:

val = code(unicode(str(prow.Typkod), "utf-8")
mapoholic
fuente
¡Gracias! Eso ayudó para la asignación de val, pero no para escribirlo en la fila actual (la siguiente línea). [Actualizando la pregunta con esta modificación.]
Martin
Quiere decir que esta línea ahora falla: prow.Typkod_U = val? ¿Con el mismo error? Entonces, ¿cuál es el valor val después de la conversión?
mapoholic
Agregué información nueva, incluido el nuevo mensaje de error.
Martin