|
POST
|
flds = ['Field1','Field']
search_feats = {f[0]:f[1:] for f in arcpy.da.SearchCursor(fc1, flds)} In this bit of your code, 'Field1' id becoming the dictionary key f[0]. A dictionary key cannot be blank. Field1 should be unique, something like an object id ('OID@' for example)
... View more
10-09-2020
12:00 PM
|
1
|
1
|
3149
|
|
POST
|
Try using split: fc = 'feature'
fields = ['USPS_ADDRE','Unit']
values = ['APT', 'UNIT', 'STE']
with arcpy.da.UpdateCursor(fc, fields) as cursor:
for row in cursor:
for v in values:
if v in row[0].upper():
# row[1] = v
row[1] = "{} {}".format(v,row[0].split(v)[1].split(' ')[1])
cursor.updateRow(row)
If you are doing some serious address parsing, look into the usaddress module. import usaddress
adr = usaddress.parse("515 S WEBER RD APT 108 LOCKPORT, IL 60441")
print(adr)
# [(u'515', 'AddressNumber'), (u'S', 'StreetNamePreDirectional'), (u'WEBER', 'StreetName'), (u'RD', 'StreetNamePostType'), (u'APT', 'OccupancyType'), (u'108', 'OccupancyIdentifier'), (u'LOCKPORT,', 'PlaceName'), (u'IL', 'StateName'), (u'60441', 'ZipCode')]
... View more
10-09-2020
10:29 AM
|
2
|
2
|
3579
|
|
POST
|
You might try this, and note case sensitivity: fc = r'C:\Users\jpilbeam\Downloads\AddPts_AptUnitSte.gdb\Default.gdb\AddPts_AptUnitSte'
field = 'USPS_ADDRE'
values = ['APT', 'UNIT', 'STE']
addresses = [row[0] for row in arcpy.da.SearchCursor(fc, field)]
types = [v for v in values for address in addresses if v in address.upper()]
print(types) I'd like to update the value to a new filed called 'UnitType'. I'm not sure if list comprehension, at least in this form, will get you closer to your goal. I would use either the field calculator or an update cursor. fc = r'C:\Users\jpilbeam\Downloads\AddPts_AptUnitSte.gdb\Default.gdb\AddPts_AptUnitSte'
fields = ['USPS_ADDRE','UnitType']
values = ['APT', 'UNIT', 'STE']
with arcpy.da.UpdateCursor(fc, fields) as cursor:
for row in cursor:
for v in values:
if v in row[0].upper():
row[1] = v
cursor.updateRow(row)
... View more
10-08-2020
03:42 PM
|
1
|
1
|
3579
|
|
POST
|
As an alternative to field mapping (and for future reference), look at Xander Bakker's code near the bottom of this thread: FieldMap and FieldMappings arrgh.... But since you are learning field mappings (as am I) here's some code that may assist in that process: # field mapping test
import arcpy
def tempMap(fm): # function takes a field map and returns it as a string
tfms = arcpy.FieldMappings() # temporary field mappings object
tfms.addFieldMap(fm) # add the field map
return tfms.exportToString() # reurn string version
# what is in a field map:
# name "aliasName" editable isNullable required length type scale precision ,mergeRule,"joinDelimiter",inputTableName,inputFieldName,startTextPosition,endTextPosition;
# create a test feature
arcpy.CreateFeatureclass_management(out_path = 'in_memory', out_name = 'test_feature', geometry_type = "POINT",
template = "#", has_m = "DISABLED", has_z = "DISABLED",
spatial_reference = arcpy.SpatialReference("WGS 1984 Web Mercator (auxiliary sphere)"))
# add some fields
arcpy.AddField_management(in_table = r'in_memory\test_feature', field_name = 'stringField',
field_type = "STRING", field_precision = "#", field_scale = "#",
field_length = 20, field_alias = "String Alias", field_is_nullable = "NULLABLE",
field_is_required = "NON_REQUIRED", field_domain = "#")
arcpy.AddField_management(in_table = r'in_memory\test_feature', field_name = 'doubleField',
field_type = "Double", field_precision = "#", field_scale = "#",
field_length = 0, field_alias = "Double Alias", field_is_nullable = "NULLABLE",
field_is_required = "NON_REQUIRED", field_domain = "#")
# create a field mapping object and display as text
fms = arcpy.FieldMappings()
fms.addTable(r'in_memory\test_feature')
print(fms.exportToString().replace(';',';\n'))
'''
stringField "String Alias" true true false 20 Text 0 0 ,First,#,in_memory\test_feature,stringField,-1,-1;
doubleField "Double Alias" true true false 0 Double 0 0 ,First,#,in_memory\test_feature,doubleField,-1,-1
'''
# examine stringField using a field map object
fm = fms.getFieldMap(fms.findFieldMapIndex('stringField'))
print(fm.outputField.name, fm.outputField.aliasName, fm.outputField.length, fm.outputField.type)
# (u'stringField', u'String Alias', 20, u'String')
print(tempMap(fm))
# stringField "String Alias" true true false 20 Text 0 0 ,First,#,in_memory\test_feature,stringField,-1,-1
# change some things
outfield = fm.outputField
outfield.name = 'hello'
outfield.aliasName = 'welcome'
outfield.length = '10'
fm.outputField = outfield
# see what we get
print(tempMap(fm))
# hello "welcome" true true false 10 Text 0 0 ,First,#,in_memory\test_feature,stringField,-1,-1
print("Toggle editable, is nullable, and required")
outfield.editable = not outfield.editable
fm.outputField = outfield
print(tempMap(fm))
outfield.isNullable = not outfield.isNullable
fm.outputField = outfield
print(tempMap(fm))
outfield.required = not outfield.required
fm.outputField = outfield
print(tempMap(fm))
'''
Toggle editable, is nullable, and required
hello "welcome" false true false 10 Text 0 0 ,First,#,in_memory\test_feature,stringField,-1,-1
hello "welcome" false false false 10 Text 0 0 ,First,#,in_memory\test_feature,stringField,-1,-1
hello "welcome" false false true 10 Text 0 0 ,First,#,in_memory\test_feature,stringField,-1,-1
'''
# change scale and precision for numeric field
# since this is just an experiment, ignore the fact that it is using a text field
outfield.scale = 5
outfield.precision = 6
fm.outputField = outfield
print(tempMap(fm))
# hello "welcome" false false true 10 Text 5 6 ,First,#,in_memory\test_feature,stringField,-1,-1
# examine merge rule and join delimiter
print(fm.mergeRule, fm.joinDelimiter)
# (u'First', u'')
# change merge and delimiter, check results
fm.mergeRule = 'Join'
fm.joinDelimiter = ';'
print(tempMap(fm))
# hello "welcome" false false true 10 Text 5 6 ,Join,";",in_memory\test_feature,stringField,-1,-1
print(fm.getStartTextPosition(0), fm.getEndTextPosition(0)) # only one item in fm, so index is 0
# (-1, -1)
fm.setStartTextPosition(0,1) # index, position
fm.setEndTextPosition(0,8)
# check changes
print(tempMap(fm))
# hello "welcome" false false true 10 Text 5 6 ,Join,";",in_memory\test_feature,stringField,1,8
# input table and field
print(fm.getInputTableName(0), fm.getInputFieldName(0)) # index
# (u'in_memory\\test_feature', u'stringField')
fms.replaceFieldMap(0, fm) # index, field map
print(fms.exportToString())
'''
hello "welcome" false false true 10 Text 5 6 ,Join,";",in_memory\test_feature,stringField,1,8;
doubleField "Double Alias" true true false 0 Double 0 0 ,First,#,in_memory\test_feature,doubleField,-1,-1
'''
# delete test feature from memory
arcpy.Delete_management(r'in_memory\test_feature') Code was developed using desktop 10.5's Python window. It shows how to access and modify some parts of the fieldmappings object. The Python window will provide some clues as to the properties and methods being used. Also, check the appropriate documentation.
... View more
10-05-2020
03:06 PM
|
1
|
0
|
4452
|
|
POST
|
RuntimeError: FieldMap: Error in adding input field to field map I suspect that the error is because the "append_layer" does not have a field named 'PropertyAddress' (the value of field_map[1]). It appears that the "addInputField" method is doing some sort of checking. Since you are fieldmapping for the append tool, I would suggest that you use the target layer's mapping and use 'removeInputField' and replace its input fields with the appropriate input fields from the append layer. My suggested code (tested in desktop 10.5's Python window) is: # function used for printing debug info
def tempMap(fm): # function takes a field map and returns it as a string
tfms = arcpy.FieldMappings() # temporary field mappings object
tfms.addFieldMap(fm) # add the field map
return tfms.exportToString() # reurn string version
appendFC = 'fm_append'
targetFC = 'fm_target'
fmsAppend = arcpy.FieldMappings()
fmsAppend.addTable(appendFC)
fmsTarget = arcpy.FieldMappings()
fmsTarget.addTable(targetFC)
match = { 'PropertyAddress' : 'Addy_Concat',
'PropertyCity' : 'CMUNITY',
'PropertyZip' : 'ZipCode' }
for x in range(0, fmsTarget.fieldCount):
fmTarget = fmsTarget.getFieldMap(x)
# print(tempMap(fmTarget))
if fmTarget.outputField.name in match.keys():
# look for the paired name
matchField = match[fmTarget.outputField.name]
else:
# look for a matching name
matchField = fmTarget.outputField.name
# try:
fmAppend = fmsAppend.getFieldMap(fmsAppend.findFieldMapIndex(matchField))
# print(tempMap(fmAppend))
# code does not check if field types match; add here if required
if fmAppend.outputField.type == fmTarget.outputField.type:
print("OK: Append field {} matches target field's type.".format(matchField))
else:
print("ERROR: Append field {} does not match target field's type.".format(matchField))
# abort code goes here
sys.exit(1)
# update input field
fmTarget.removeInputField(0)
fmTarget.addInputField(appendFC,matchField)
if fmAppend.outputField.length > fmTarget.outputField.length:
print('WARNING: Append field {} is too long; making adjustments.'.format(matchField))
fmTarget.setStartTextPosition(0,0)
fmTarget.setEndTextPosition(0,fmTarget.outputField.length-1)
# print(tempMap(fmTarget))
# replace updated field map
fmsTarget.replaceFieldMap(x, fmTarget)
# except:
# no matching field code - perhaps to remove field from mappings
# print('\n')
# print(fmsTarget.exportToString())
print("Appending.")
arcpy.Append_management(inputs=appendFC, # feature data to be added
target=targetFC, # feature where data will go
schema_type="NO_TEST",
field_mapping=fmsTarget, subtype="")
print("Done.") I've commented out some print statements that were used for debugging. I assumed that the number of fields would match; but the situation may actually require a try/except block to remove unmatched fields. Hope this helps.
... View more
10-05-2020
02:58 PM
|
0
|
0
|
4452
|
|
POST
|
See this support article: How To: Access offline edits from Collector for ArcGIS directly from an Android or iOS device
... View more
10-02-2020
10:34 AM
|
0
|
0
|
595
|
|
POST
|
Try changing lines 9 and 10 in my Sept 27 response. # From:
parcelFlds = ['WellID', 'W_DEPTH', 'Geothermal', 'GeoWaterUs', 'TEMP', 'TEMP_DATE']
pointFlds = ['WellID', 'W_DEPTH', 'Geothermal', 'GeoWaterUs', 'TEMP', 'TEMP_DATE', 'SHAPE@']
# To something like (just match fields by position in lists):
parcelFlds = ['field_A', 'field_1', 'field_B', 'field_2', 'field_C', 'field_3']
pointFlds = ['fieldA', 'field1', 'fieldB', 'field2', 'fieldC', 'field3', 'SHAPE@']
... View more
10-01-2020
04:26 PM
|
0
|
0
|
332
|
|
POST
|
Here's the approach I was experimenting with that uses a spatial join (and field mapping). # inside ArcMap with layers in a map
points = "GeoWellTemp"
parcels = "WellTaxlots"
# outside ArcMap, use full path to feature layer or shapefile
# points = r'C:\Path\to\GeoWellTemp.shp'
# parcels = r'C:\Path\to\WellTaxlots.shp'
# fields needed for join (assumes field names exist)
pointsFlds = ['OBJECTID'] # alternatively use the FID field
parcelFlds = ['WellID', 'W_DEPTH', 'Geothermal', 'GeoWaterUs', 'TEMP', 'TEMP_DATE']
# set-up the field mappings
fieldmappings = arcpy.FieldMappings()
# fields in target (points) layer are done first
for f in pointsFlds: # field mapping for points layer
fm = arcpy.FieldMap()
fm.addInputField(points, f)
fieldmappings.addFieldMap(fm)
# field mapping for points layer with same field names as parcels
# these fields will be renamed to avoid confusion
for f in parcelFlds:
try:
fm = arcpy.FieldMap() # reset field map
fm.addInputField(points, f) # checking points for matching field
outname = fm.outputField
outname.name = outname.name + "_99" # append _99 to end
outname.aliasName = outname.aliasName + "_99"
fm.outputField = outname
fieldmappings.addFieldMap(fm)
except:
pass
# then do fields in join (parcels) layer
for f in parcelFlds: # field mapping for parcels layer
fm = arcpy.FieldMap()
fm.addInputField(parcels, f)
fieldmappings.addFieldMap(fm)
# now the spatial join
join = 'in_memory\sj_test' # location/name of join
if arcpy.Exists(join): # delete any old joins
arcpy.Delete_management(join)
# join one to many will create a JOIN_FID which with the TARGET_FID could be used in checking the linking of the features
arcpy.SpatialJoin_analysis(target_features = points, join_features = parcels, out_feature_class = join,
join_operation="JOIN_ONE_TO_MANY", join_type="KEEP_ALL", field_mapping = fieldmappings,
match_option="INTERSECT", search_radius="", distance_field_name="")
joinFlds = pointsFlds + parcelFlds # points fields has the objectid or fid field
valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(join, joinFlds)}
# update the points feature
with arcpy.da.UpdateCursor(points, joinFlds) as updateRows:
for updateRow in updateRows:
keyValue = updateRow[0]
if keyValue in valueDict:
for n in range (1,len(joinFlds)):
updateRow[n] = valueDict[keyValue][n-1]
updateRows.updateRow(updateRow)
# clean up
if arcpy.Exists(join):
arcpy.Delete_management(join)
del valueDict The field mappings took some experimenting. I first tried a spatial join and examined the code the tool creates (copy as python snippet). This provided a way to examine the default field map the tool generates. The points and parcels layers had a number of fields that used the same name. Normally, the target feature (points, in this case) would use the original field name, and the join feature (parcels) would append an underscore with a number to rename any fields sharing a name in the target feature. As I wanted the original field names for the join feature, I renamed the target feature's fields when setting up the field mapping. I think the identical names caused some issues for the spatial join tool, as it would use the values of the target feature when I selected only the fields from the join feature. I ended up performing three steps to assemble the field map. First, I selected the object id field from the target feature to be used for linking to the points feature. The second step was to select and rename any fields in the target feature that had identical names in the join feature that were to be used. The final step was to select the fields in the join feature that were used to update the points feature. I used an in_memory location for the spatial join; it needed to be a temporary join anyway. I used a 'one to many' join to have access to the JOIN_FID field that is created which would assist in linking the two layers together for any debugging necessary. The last steps were to load the join layer's data into a dictionary and to use it in an update cursor. I think this approach is a bit faster than the one in my previous post. But it took much more time to get debugged and working. Hope this helps.
... View more
09-30-2020
06:01 PM
|
2
|
2
|
1485
|
|
POST
|
Since you are wanting the user to type a name for the file, you may want set the data type as 'String' for the Name (not 'File'). That way the tool will not help the user locate a file, such as Default.gdb.
... View more
09-28-2020
12:12 PM
|
0
|
0
|
906
|
|
POST
|
I did some testing with the data you provided using Desktop 10.5. I did notice that the field names didn't match with what you were trying in your scripts, so that may be something to watch out for. Here's a script for you to try, It uses your shape files, so you may need to make adjustments if you are using a file/server geodatabase. It is basically the approach in my earlier post. import arcpy
points = "GeoWellTemp" # layers in map
parcels = "WellTaxlots"
# if outside ArcMap (or inside ArcMap with an empty document), add these extra steps
ptsPath = r'C:\Path\to\GeoWellTemp.shp'
parPath = r'C:\Path\to\WellTaxlots.shp'
arcpy.MakeFeatureLayer_management(ptsPath, points)
arcpy.MakeFeatureLayer_management(parPath, parcels)
# end extra steps
# parcel and point fields are paired; geometry is added at end for points
parcelFlds = ['WellID', 'W_DEPTH', 'Geothermal', 'GeoWaterUs', 'TEMP', 'TEMP_DATE']
pointFlds = ['WellID', 'W_DEPTH', 'Geothermal', 'GeoWaterUs', 'TEMP', 'TEMP_DATE', 'SHAPE@']
# clear any selected features
arcpy.SelectLayerByAttribute_management(points, "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management(parcels, "CLEAR_SELECTION")
where_clause = 'WellID IS NULL OR WellID = 0' # where clause if needed
with arcpy.da.UpdateCursor(points, pointFlds, where_clause) as cursor:
for row in cursor:
# row[6] is the point's geometry - SHAPE@
arcpy.management.SelectLayerByLocation(parcels, "INTERSECT", row[6], "", "NEW_SELECTION")
with arcpy.da.SearchCursor(parcels, parcelFlds) as parcelsCursor:
for parcelRow in parcelsCursor:
# print parcelRow
row[0] = parcelRow[0] # WellID
row[1] = parcelRow[1] # W_DEPTH
row[2] = parcelRow[2] # Geothermal
row[3] = parcelRow[3] # GeoWaterUS
row[4] = parcelRow[4] # TEMP
row[5] = parcelRow[5] # TEMP_DATE
cursor.updateRow(row) # update row
# last parcel selected can be cleared
arcpy.SelectLayerByAttribute_management(parcels, "CLEAR_SELECTION") I'm not sure how fast this approach will be if you have lots of points to update. I did some testing with a spatial join and field mapping. I can share that approach, if you're interested.
... View more
09-27-2020
10:33 PM
|
3
|
4
|
1485
|
|
POST
|
I tested the following code inside Desktop 10.5 with parcels and points layers in the map. It may give you some ideas. I did not use a where clause for the update cursor, but one could be used to limit the rows to ones where the Well ID is null or '' (zero length). points = "WellPoints"
parcels = "WellParcels"
parcelFlds = ['WellID', 'dept', 'type', 'Geothermal', 'GeoWaterUs', 'Temp', 'TempDate']
pointFlds = ['W_ID', 'dept', 'type', 'Geothermal', 'GeoWaterUs', 'Temp', 'TempDate', 'SHAPE@']
with arcpy.da.UpdateCursor(points, pointFlds) as cursor:
for row in cursor:
arcpy.management.SelectLayerByLocation(parcels, "INTERSECT", row[7], "", "NEW_SELECTION")
with arcpy.da.SearchCursor(parcels, parcelFlds) as parcelsCursor:
for parcelRow in parcelsCursor:
# print parcelRow
row[0] = parcelRow[0]
row[1] = parcelRow[1]
row[2] = parcelRow[2]
row[3] = parcelRow[3]
row[4] = parcelRow[4]
row[5] = parcelRow[5]
row[6] = parcelRow[6]
cursor.updateRow(row) # update row I also noticed a few typos in your code - perhaps copy/paste errors. A missing comma and an extra space: >>> fldList = ['WellID', 'dept', 'type', ' Geothermal' 'GeoWaterUs', 'Temp', 'TempDate']
>>> fldList
['WellID', 'dept', 'type', ' GeothermalGeoWaterUs', 'Temp', 'TempDate']
>>> Hope this helps.
... View more
09-25-2020
10:33 AM
|
0
|
0
|
1485
|
|
POST
|
To assist in understanding your project, the goal is to update attributes in the well points layer with data from the parcels layer feature the well is located in, correct? Does each parcel contain only one well or can it contain several wells? Do you need to only update a few wells where the data is missing, or do you want to update all wells? Could you share some sample data?
... View more
09-24-2020
01:45 PM
|
0
|
1
|
1485
|
|
POST
|
You can use something like DictWriter to create a csv file. However, I usually do something a bit more basic, usually using tab delimited files: # before your loop, open a new file
fw = open("outputfile.txt", "w") # can be .csv
for item in some_loop:
# do things ...
path = "Account22"
filename = "Account22_20200921_photo1.jpg"
# write a line - \t = tab character and \n = new line
fw.writelines("{}\t{}\n".format(path, filename))
# after the loop, close the file
fw.close() Your code would be a bit easier to read with formatting. See: Code Formatting... the basics++
... View more
09-21-2020
03:36 PM
|
2
|
0
|
4016
|
|
POST
|
Try replacing the None in Joshua Bixby's line of code with 0.
... View more
09-21-2020
10:54 AM
|
2
|
1
|
1601
|
|
POST
|
The first issue is lines 64, 73 and 82 of the second script which sets the various parameter's name to the same value, "geo3", which is the name for params3 in line 55. This will cause parameters 3 through 6 to have the same value; when any one of these gets changed, the others in the group will also change. You have a similar problem in your first script as the name "veg3" is also used multiple times. Additional thoughts: The updateParameters section is a bit awkward, but in a quick test it does work. You could combine these six parameters into one that is "multiple values". This may also apply to vegetation class as well. Regarding the vegetation class, all the numbers appear to be integers, but you are using a type of float (double). This could be an issue. You may also wish to use a filter type of "Range": param0.filter.type = "Range"
param0.filter.list = [0, 76]
... View more
09-20-2020
06:25 PM
|
1
|
1
|
3988
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 10-27-2016 02:23 PM | |
| 1 | 09-09-2017 08:27 PM | |
| 2 | 08-20-2020 06:15 PM | |
| 1 | 10-21-2021 09:15 PM | |
| 1 | 07-19-2018 12:33 PM |
| Online Status |
Offline
|
| Date Last Visited |
09-15-2025
02:54 PM
|