[GIS] Changing single character in attribute table with ArcPy

arcpyattribute-tablestring

I was trying to speed up my data processing, and I was wondering, which would be the python code, that could browse through my shapefiles, and find special single characters (which I define) in attribute table in string fields, and replace them with defined characters.

For example, I have shapefiles, in my "D:\GIS_One" folder. All of the shapefiles have few string(text) fields in their attribute tables. For example, value in some of the fields are "Day&Night", "Mix!" "Über". In this example, I would like to replace "&" with "_" , "!" with "One" and "Ü" with "U". Just the single characters, not the whole words, since I have another code to change the whole words. I am just looking for a code to do a single character replacement.

I already tried with How to iterate fields and remove Null values and spaces but could not manage to work it out. Also, I know how to to it with Field Calculator, and Excel/LibreOffice, but I am looking for a Python solution so I could speed up my work.

EDIT: As Michael asked, I worked on a first two codes, and now I am working on a third provided from a posted link. Here is working code:

>>> import arcpy
    fc = ["D:\GIS_One\Ride.shp", "D:\GIS_One\Unknown.shp" ]
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
    with arcpy.da.UpdateCursor(fc, [fieldList]) as cursor:
        for row in cursor:
            for i in range (len(fieldList)):
                if not row[i]:
                    row[i] == ""
                elif row[i] == "&":
                    row[i] == "_"
                elif row[i] == "!":
                    row[i] == "1"
                elif row[i] == "Ü":
                    row[i] == "U"
            cursor.updateRow(row)
print "Processing complete"

I get this error:

Runtime error
Traceback (most recent call last):
File "", line 3, in
File "c:\program files\arcgis\desktop10.1\arcpy\arcpy__init__.py", line 1075, in ListFields
return gp.listFields(dataset, wild_card, field_type)
File "c:\program files\arcgis\desktop10.1\arcpy\arcpy\geoprocessing_base.py", line 344, in listFields
self._gp.ListFields(*gp_fixargs(args, True)))
IOError: "['D:/GIS_One/Ride.shp', 'D:/GIS_One/Unknown.shp']" does not exist

And if I try with one feature class from database, with this code:

>>> import arcpy
    fc = "D:\GIS_Temp\TEST.gdb\ONE"
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
    with arcpy.da.UpdateCursor(fc, [fieldList]) as cursor:
        for row in cursor:
            for i in range (len(fieldList)):
               if not row[i]:
                    row[i] == ""
                elif row[i] == "&":
                    row[i] == "_"
                elif row[i] == "!":
                    row[i] == "One"
                elif row[i] == "Ü":
                    row[i] == "U"    
            cursor.updateRow(row)
print "Processing complete"

I get this error:

Runtime error
Traceback (most recent call last):
File "", line 5, in
TypeError: 'field_names' must be string or non empty sequence of strings

It would be really helpful if i could manage to make the code to work on shapefiles.

Best Answer

You need to use the str.replace() to replace the characters in your field values.

Also needed to put a for fc in fcs: to loop through your shapefiles, and remove the square brackets from around fieldList in your cursor (this is what is giving you the error 'field_names' must be string or non empty sequence of strings)

And note the u in front of u"Ü" so that you don't get a decode error.

import arcpy
fcs = [r"D:\GIS_One\Ride.shp", r"D:\GIS_One\Unknown.shp" ]

for fc in fcs:
    fieldList = [f.name for f in arcpy.ListFields(fc) if f.type == "String"]
    if fieldList:
        with arcpy.da.UpdateCursor(fc, fieldList) as cursor:
            for row in cursor:
                for i in range (len(fieldList)):
                    newFieldvalue = row[i].replace("&","_").replace("!","1").replace(u"Ü","U")
                    row[i] = newFieldvalue
                cursor.updateRow(row)

print "Processing complete"