การแทนที่อักขระที่ไม่ใช่ภาษาอังกฤษในตารางแอตทริบิวต์โดยใช้ ArcPy และ Python?


9

ฉันมีรูปแบบไฟล์เล็กน้อยที่คุณสมบัติบางอย่างมีอักขระที่ไม่ใช่ภาษาอังกฤษÅÄÖ เนื่องจากข้อความค้นหาบางข้อไม่สามารถใช้งานได้กับตัวละครเหล่านี้ (โดยเฉพาะChangeDetector ) ฉันพยายามที่จะเปลี่ยนพวกเขาล่วงหน้าด้วยสคริปต์ง่าย ๆ และเพิ่มสตริงใหม่ลงในฟิลด์อื่น

อย่างไรก็ตามการเปลี่ยนแปลงในตัวละครทำงานได้ดี แต่ไม่ได้ปรับปรุงสนามด้วย arcpy.UpdateCursor

อะไรคือวิธีที่เหมาะสมในการแก้ปัญหานี้?

ฉันได้ลองทำเช่นนี้ผ่านเครื่องคิดเลขภาคสนามในขณะที่โพสต์ "รหัส" เพื่อ codeblock มีข้อผิดพลาดเดียวกัน

ข้อความแสดงข้อผิดพลาด:
ข้อผิดพลาดรันไทม์การติดตามย้อนกลับ (การโทรล่าสุดครั้งล่าสุด): ไฟล์ "", บรรทัด 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


ข้อความแสดงข้อผิดพลาดใหม่:
ข้อผิดพลาดรันไทม์การติดตามย้อนกลับ (การโทรล่าสุดครั้งล่าสุด): ไฟล์ "", บรรทัด 1, ในไฟล์ "c: /gis/python/teststring.py", บรรทัด 29, ใน val = code (unicode (str (แถว) Typkod), "utf-8")) UnicodeEncodeError: 'ascii' codec ไม่สามารถเข้ารหัสอักขระ u '\ xc4' ในตำแหน่ง 3: ลำดับไม่อยู่ในช่วง (128)

>>> val 'DDRÄ'
>>> type(val) พิมพ์ 'str'


ดูเหมือนว่าเอาต์พุตจากฟังก์ชันผิดปกติ เมื่อมี AAO ที่เกี่ยวข้องก็จะส่งกลับdata = u'DDR\xc4'และไม่ได้ data = 'DDRAE'(ตามที่เป็นความตั้งใจของฉัน) ข้อเสนอแนะใด ๆ เกี่ยวกับสิ่งที่อาจทำให้เกิดปัญหานี้?

คำตอบ:


7

ฉันมักจะพูดถึงตัวละครพิเศษเช่นคุณเป็นภาษาสวีเดน (ä, ö, å) แต่ก็มีบางคนที่แสดงเป็นภาษาอื่นเช่นโปรตุเกสและสเปน (é, í, ú, ó ฯลฯ ) ตัวอย่างเช่นฉันมีข้อมูลที่เขียนชื่อเมืองเป็นภาษาละตินเรียบง่ายพร้อมการลบเสียงทั้งหมดดังนั้น "Göteborg" จึงกลายเป็น "Goteborg" และ "Åre" คือ "Are" เพื่อทำการเชื่อมต่อและจับคู่ข้อมูลฉันต้องแทนที่สำเนียงให้เป็นอักขระภาษาอังกฤษละติน

ฉันเคยทำสิ่งนี้ตามที่คุณแสดงในคำตอบของคุณเองก่อน แต่ในไม่ช้าตรรกะนี้ค่อนข้างยุ่งยากในการรักษา ตอนนี้ฉันใช้โมดูล 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 ที่วิธีที่ดีที่สุดในการลบเครื่องหมายเน้นเสียงในสตริง python unicode คืออะไร?


ฉันเห็นว่ามันจะมีประโยชน์ แต่ถ้าเราจำเป็นต้องรักษาตัวละครตามที่เป็นอยู่ เราสามารถใช้เวทมนตร์เพื่อรักษาตัวละครพิเศษเหล่านั้นได้หรือไม่?
Bogdan Mircea Stanciu

6

ปรากฎว่าซ้ำÅÄÖไม่ใช่เรื่องง่าย มันถูกอ้างถึงเป็นสตริง Unicode และเมื่อตรวจสอบในคำสั่ง 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")

ขอบคุณ! นั่นช่วยในการกำหนดvalแต่ไม่ใช่สำหรับการเขียนลงในแถวปัจจุบัน (บรรทัดต่อไปนี้) [อัปเดตคำถามด้วยการดัดแปลงนี้]
Martin

คุณหมายถึงบรรทัดนี้ล้มเหลวแล้ว: prow.Typkod_U = val? ด้วยข้อผิดพลาดเดียวกัน? แล้วค่าวาลหลังการแปลงคืออะไร?
mapoholic

ฉันเพิ่มข้อมูลใหม่รวมถึงข้อความแสดงข้อผิดพลาดใหม่
มาร์ติน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.