Mengganti karakter non-Inggris dalam tabel atribut menggunakan ArcPy dan Python?

9

Saya memiliki beberapa shapefile di mana beberapa atribut berisi karakter non-Inggris ÅÄÖ. Karena beberapa kueri tidak berfungsi dengan karakter ini (khususnya ChangeDetector ), saya mencoba mengubahnya terlebih dahulu dengan skrip sederhana dan menambahkan string baru ke bidang lain.

Namun, perubahan karakter berfungsi dengan baik tetapi tidak memperbarui bidang dengan arcpy.UpdateCursor.

Apa cara yang tepat untuk menyelesaikan ini?

Saya juga mencoba melakukan ini melalui Field Calculator sambil memposting "kode" ke kode kunci, dengan kesalahan yang sama.

Pesan kesalahan:
Runtime error Traceback (panggilan terakhir terakhir): File "", line 1, dalam File "c: /gis/python/teststring.py", baris 28, dalam val = kode (str (prow.Typkod)) UnicodeEncodeError: 'ascii' codec tidak dapat menyandikan karakter u '\ xc4' di posisi 3: ordinal tidak dalam jangkauan (128)

Kode:

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

Nilai-nilai Typkod adalah dari jenis: [D, D, S, DDRÄ, TRÄ] dll.

Saya menggunakan ArcMap Basic (10.1) pada Windows 7.


Pesan Kesalahan Baru:
Kesalahan runtime Traceback (panggilan terakhir terakhir): File "", baris 1, dalam File "c: /gis/python/teststring.py", baris 29, dalam val = kode (unicode (str (baris. Typkod), "utf-8")) UnicodeEncodeError: codec 'ascii' tidak dapat menyandikan karakter u '\ xc4' di posisi 3: ordinal tidak dalam jangkauan (128)

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


Tampaknya seolah-olah output dari fungsi tersebut salah. Ketika ada ÅÄÖ yang terlibat, ia kembali data = u'DDR\xc4'dan tidak (seperti niat saya) data = 'DDRAE'. Ada saran tentang apa yang menyebabkan ini?

Martin
sumber

Jawaban:

7

Saya terlalu sering berurusan dengan karakter khusus seperti yang Anda miliki di Swedia (ä, ö, å), tetapi juga beberapa yang lain menyajikan dalam bahasa lain seperti Portugis dan Spanyol (é, í, ú, ú, ó dll.). Misalnya, saya memiliki data di mana nama kota ditulis dalam bahasa Latin sederhana dengan semua aksen dihapus, sehingga "Göteborg" menjadi "Goteborg" dan "Åre" adalah "Are". Untuk melakukan penggabungan dan mencocokkan data saya harus mengganti aksen ke karakter berbasis bahasa Inggris Latin.

Saya dulu melakukan ini seperti yang Anda tunjukkan dalam jawaban Anda sendiri terlebih dahulu, tetapi logika ini segera menjadi agak rumit untuk dipertahankan. Sekarang saya menggunakan modul unicodedata yang sudah tersedia dengan instalasi Python dan arcpy untuk iterasi fitur-fiturnya.

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)

Lihat tautan untuk informasi lebih lanjut tentang penggunaan modul unicodedata di Apa cara terbaik untuk menghilangkan aksen dalam string unicode python?

Alex Tereshenkov
sumber
Saya melihat bagaimana ini bisa berguna, tetapi bagaimana jika kita perlu mempertahankan karakter apa adanya? Bisakah kita melakukan sihir untuk mempertahankan karakter khusus itu?
Bogdan Mircea Stanciu
6

Ternyata iterasi lebih dari ÅÄÖ tidak mudah. Ini disebut sebagai string unicode, dan ketika memeriksa pernyataan if yang harus digunakan alih-alih ÅÄÖ literal. Setelah saya mengetahuinya, sisanya adalah sepotong kue :)

Kode yang dihasilkan:

# -*- 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
sumber
1

Lihat apakah yang berikut ini berfungsi:

val = code(unicode(str(prow.Typkod), "utf-8")
mapoholic
sumber
Terima kasih! Itu memang membantu untuk penugasan val, tetapi tidak untuk menulisnya ke baris saat ini (baris berikut). [Memperbarui pertanyaan dengan modifikasi ini.]
Martin
Maksud Anda baris ini sekarang gagal: prow.Typkod_U = val? Dengan kesalahan yang sama? Jadi, apa nilai val setelah konversi?
mapoholic
Saya menambahkan beberapa informasi baru, termasuk pesan kesalahan baru.
Martin