Замена неанглийских символов в таблицах атрибутов с использованием ArcPy и Python?

9

У меня есть несколько шейп-файлов, где некоторые атрибуты содержат неанглийские символы ÅÄÖ. Поскольку некоторые запросы не работают с этими символами (в частности, ChangeDetector ), я попытался заранее изменить их с помощью простого сценария и добавить новые строки в другое поле.

Однако изменение символов работает нормально, но не обновляет поле с помощью arcpy.UpdateCursor.

Как правильно решить эту проблему?

Я также попытался сделать это с помощью Калькулятора полей, отправляя «код» в кодовый блок, с той же ошибкой.

Сообщение об ошибке:
Ошибка во время выполнения (последний вызов был последним): файл "", строка 1, в файле "c: /gis/python/teststring.py", строка 28, в val = code (str (prow.Typkod)) UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xc4' в позиции 3: порядковый номер не в диапазоне (128)

Код:

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

Значения Typkod имеют тип: [D, D, S, DDRÄ, TRÄ] и т. Д.

Я использую ArcMap Basic (10.1) в Windows 7.


Новое сообщение об ошибке: Ошибка
времени выполнения Traceback (последний вызов был последним): файл "", строка 1, в файле "c: /gis/python/teststring.py", строка 29, в val = код (unicode (str (строка. Типкод), "utf-8")) UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xc4' в позиции 3: порядковый номер не в диапазоне (128)

>>> val 'DDRÄ'
>>> type(val) тип 'str'


Похоже, что выход из функции как-то не так. Когда вовлечено ÅÄÖ, оно возвращается, data = u'DDR\xc4'а не (как было в моем намерении) data = 'DDRAE'. Любые предложения о том, что может вызвать это?

Мартин
источник

Ответы:

7

Я слишком часто имею дело со специальными символами, такими как у вас на шведском (ä, ö, å), но также с некоторыми другими, присутствующими на других языках, таких как португальский и испанский (é, í, ú, ó и т. Д.). Например, у меня есть данные, где название города написано простым латинским языком со всеми удаленными акцентами, поэтому «Гетеборг» становится «Гетеборгом», а «Оре» - «Аре». Чтобы выполнить объединения и сопоставить данные, я должен заменить акценты на английский латинский символ.

Раньше я делал это, как вы сначала показали в своем ответе, но вскоре эта логика стала довольно громоздкой для поддержки. Теперь я использую модуль unicodedata, который уже доступен с установкой Python и arcpy для итерации функций.

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)

См. Ссылку для получения дополнительной информации об использовании модуля unicodedata в Каков лучший способ удалить акценты в строке Unicode Python?

Алекс Терешенков
источник
Я понимаю, как это может быть полезно, но что, если нам нужно сохранить персонажей как есть? мы могли бы сделать немного магии, чтобы сохранить эти специальные символы?
Богдан Мирча Станчу
6

Оказывается, перебирая ÅÄÖ, было не так просто. Он называется строкой Юникода и при проверке в операторах if, которые должны использоваться вместо литерала ÅÄÖ. После того, как я понял это, остальное было просто пирогом :)

Результирующий код:

# -*- 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)
Мартин
источник
1

Посмотрите, работает ли следующее:

val = code(unicode(str(prow.Typkod), "utf-8")
mapoholic
источник
Спасибо! Это помогло назначить val, но не записать его в текущую строку (следующая строка). [Обновление вопроса с помощью этой модификации.]
Мартин
Вы имеете в виду, что эта строка теперь не работает: prow.Typkod_U = val? С той же ошибкой? Итак, каково значение val после конвертации?
Мапоголик
Я добавил новую информацию, в том числе новое сообщение об ошибке.
Мартин