Remplacer les caractères non anglais dans les tables d'attributs à l'aide d'ArcPy et de Python?

9

J'ai quelques fichiers de formes où certains des attributs contiennent les caractères non anglais ÅÄÖ. Étant donné que certaines requêtes ne fonctionnent pas avec ces caractères (en particulier ChangeDetector ), j'ai essayé de les modifier à l'avance avec un script simple et d'ajouter les nouvelles chaînes à un autre champ.

Cependant, la modification des caractères fonctionne correctement mais ne met pas à jour le champ avec arcpy.UpdateCursor.

Quelle est la manière appropriée de résoudre ce problème?

J'ai également essayé de le faire via la calculatrice de champ lors de la publication de "code" sur le bloc de code, avec la même erreur.

Message d'erreur:
Erreur d'exécution Traceback (dernier appel le plus récent): Fichier "", ligne 1, dans Fichier "c: /gis/python/teststring.py", ligne 28, dans val = code (str (prow.Typkod)) UnicodeEncodeError: le codec 'ascii' ne peut pas coder le caractère u '\ xc4' en position 3: l'ordinal n'est pas dans la plage (128)

Code:

# -*- 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)

Les valeurs de Typkod sont du type: [D, D, S, DDRÄ, TRÄ] etc.

J'utilise ArcMap Basic (10.1) sur Windows 7.


Nouveau message d'erreur:
Erreur d'exécution Traceback (dernier appel le plus récent): Fichier "", ligne 1, dans Fichier "c: /gis/python/teststring.py", ligne 29, dans val = code (unicode (str (ligne. Typkod), "utf-8")) UnicodeEncodeError: le codec 'ascii' ne peut pas coder le caractère u '\ xc4' en position 3: ordinal pas dans la plage (128)

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


Il semble que la sortie de la fonction soit incorrecte d'une manière ou d'une autre. Quand ÅÄÖ est impliqué, il revient data = u'DDR\xc4'et non (comme c'était mon intention) data = 'DDRAE'. Des suggestions sur ce qui pourrait provoquer cela?

Martin
la source

Réponses:

7

Je m'occupe trop souvent de caractères spéciaux comme vous en avez en suédois (ä, ö, å), mais aussi de quelques autres présentant dans d'autres langues comme le portugais et l'espagnol (é, í, ú, ó etc.). Par exemple, j'ai des données où le nom de la ville est écrit en latin simple avec tous les accents supprimés, donc le "Göteborg" devient "Goteborg" et "Åre" est "Are". Afin d'effectuer les jointures et de faire correspondre les données, je dois remplacer les accents du caractère basé sur le latin anglais.

J'avais l'habitude de faire cela comme vous l'avez montré dans votre propre réponse en premier, mais cette logique est rapidement devenue assez lourde à maintenir. Maintenant, j'utilise le module unicodedata qui est déjà disponible avec l'installation de Python et arcpy pour itérer les fonctionnalités.

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)

Voir le lien pour plus d'informations sur l'utilisation du module unicodedata à Quelle est la meilleure façon de supprimer les accents dans une chaîne unicode python?

Alex Tereshenkov
la source
Je vois comment cela pourrait être utile, mais que faire si nous devons conserver les personnages tels quels? pourrions-nous faire de la magie pour conserver ces caractères spéciaux?
Bogdan Mircea Stanciu
6

Il s'avère que l'itération de ÅÄÖ n'a pas été aussi simple. Il est appelé chaîne unicode et lors de l'archivage des instructions if qui doivent être utilisées à la place du littéral ÅÄÖ. Après avoir compris cela, le reste était un morceau de gâteau :)

Code résultant:

# -*- 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)
Martin
la source
1

Voyez si les éléments suivants fonctionnent:

val = code(unicode(str(prow.Typkod), "utf-8")
mapoholic
la source
Merci! Cela a aidé pour l'attribution de val, mais pas pour l'écrire dans la ligne actuelle (la ligne suivante). [Mise à jour de la question avec cette modification.]
Martin
Vous voulez dire que cette ligne échoue maintenant: prow.Typkod_U = val? Avec la même erreur? Alors, quelle est la valeur de val après la conversion?
mapoholic
J'ai ajouté de nouvelles informations, y compris le nouveau message d'erreur.
Martin