Substituindo caracteres não ingleses nas tabelas de atributos usando ArcPy e Python?

9

Eu tenho alguns shapefiles nos quais alguns dos atributos contêm os caracteres não ingleses ÅÄÖ. Como algumas consultas não funcionam com esses caracteres (especificamente ChangeDetector ), tentei alterá-los antecipadamente com um script simples e adicionar as novas strings a outro campo.

No entanto, a alteração de caracteres funciona bem, mas não atualiza o campo com arcpy.UpdateCursor.

Qual é a maneira apropriada de resolver isso?

Eu também tentei fazer isso através da calculadora de campo ao postar "código" no código de bloqueio, com o mesmo erro.

Mensagem de erro:
Erro de tempo de execução Traceback (última chamada mais recente): Arquivo "", linha 1, no arquivo "c: /gis/python/teststring.py", linha 28, em val = code (str (prow.Typkod)) UnicodeEncodeError: o codec 'ascii' não pode codificar o caractere u '\ xc4' na posição 3: ordinal fora do intervalo (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)

Os valores do Typkod são do tipo: [D, D, S, DDRÄ, TRÄ] etc.

Eu uso o ArcMap Basic (10.1) no Windows 7.


Nova mensagem de erro:
Erro de tempo de execução Traceback (última chamada mais recente): Arquivo "", linha 1, no arquivo "c: /gis/python/teststring.py", linha 29, em val = code (unicode (str (row. Typkod), "utf-8")) UnicodeEncodeError: o codec 'ascii' não pode codificar o caractere u '\ xc4' na posição 3: ordinal fora do intervalo (128)

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


Parece que a saída da função está errada de alguma forma. Quando há ÅÄÖ envolvido, ele retorna data = u'DDR\xc4'e não (como era minha intenção) data = 'DDRAE'. Alguma sugestão sobre o que pode causar isso?

Martin
fonte

Respostas:

7

Frequentemente lido com caracteres especiais como os que você possui em sueco (ä, ö, å), mas também com outros que se apresentam em outros idiomas, como português e espanhol (é, í, ú, ó etc.). Por exemplo, tenho dados em que o nome da cidade está escrito em latim sem todos os sotaques removidos, de modo que o "Gotemburgo" se torna "Goteborg" e "Åre" é "Are". Para executar as junções e combinar os dados, tenho que substituir os acentos pelo caractere em inglês da América Latina.

Eu costumava fazer isso como você mostrou em sua própria resposta primeiro, mas essa lógica logo se tornou bastante difícil de manter. Agora eu uso o módulo unicodedata, que já está disponível com a instalação do Python e o arcpy para iterar os recursos.

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 o link para obter mais informações sobre o uso do módulo unicodedata em Qual é a melhor maneira de remover acentos em uma string unicode python?

Alex Tereshenkov
fonte
Vejo como isso pode ser útil, mas e se precisarmos manter os personagens como estão? poderíamos fazer alguma mágica para manter esses personagens especiais?
Bogdan Mircea Stanciu
6

Acontece que iterar sobre ÅÄÖ não foi tão fácil. É referido como uma cadeia unicode e, ao fazer o check-in das instruções if que devem ser usadas no lugar do literal ÅÄÖ. Depois que eu descobri isso, o resto foi um pedaço de bolo :)

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)
Martin
fonte
1

Veja se o seguinte funciona:

val = code(unicode(str(prow.Typkod), "utf-8")
mapoholic
fonte
Obrigado! Isso ajudou na atribuição val, mas não na gravação na linha atual (a linha a seguir). [Atualizando a pergunta com esta modificação.]
Martin
Você quer dizer que esta linha agora falha: prow.Typkod_U = val? Com o mesmo erro? Então, qual é o valor val após a conversão?
amigos estão dizendo sobre mapoholic
Eu adicionei algumas informações novas, incluindo a nova mensagem de erro.
Martin Martin