Hi folks. I'm new to both GIS and programming and am attempting to combine the two. I need a python script that will read down a particular column of the attribute table of a particular layer, then check it against a column in the attribute table of another layer. Both of these columns will contain strings. If the two match, then the script should input "YES" into another field in the first layer.
I honestly have no idea how to even start this. I've read through esri's help section and have a very basic grasp of python but I'm unsure of how to get the script to actually access the attribute tables. Any help would be very greatly appreciated.
Thanks in advance! If there's a better place to post this, please let me know.
Solved! Go to Solution.
If you want to know which parcel the well point is on, why not do a spatial join first, that way you only need to iterate over 1 attribute table, after you do the spatial join.
ArcGIS Help (10.2, 10.2.1, and 10.2.2)
You will need to add another field to your points, so you can put "YES" it in.
This way you should only need 1 search cursor, which will need the the field names for the well owner, parcel owner, and field name that will contain the "Yes".
so after doing a spatial join and adding your new field it would look something like this.
import arcpy wells = "path here" wellowner = "Owner" #or whatever your field name is parcelowner = "Owner1" #or whatever your field name is with arcpy.da.UpdateCursor(wells, [wellowner, parcelowner, "Nameofyournewfieldhere"]) as cursor: for row in cursor: if row[0] == row[1]: row[2] = "YES" cursor.updateRow(row) else: continue
You did pretty well with your code, cursors can take a little while to get use to.
A little critique of your code:
import arcpy #perfect! wells = "path here" #good parcels = "path here" # good owner = ["Owner"] #no brackets needed, you want a string not a list(though it turns out okay in this case) powner = ["Owner1"] #see above cursor = arcpy.da.UpdateCursor(wells, ["Public"]) #correct syntax for making a cursor, kudos for using the data access cursor wellowner = arcpy.da.SearchCursor(wells, owner) #again correct syntax parcelowner = arcpy.da.SearchCursor(parcels, powner)#ditto if ( wellowner == parcelowner ) : #here would be the problem, you are comparing two cursor objects and not their values for row in cursor: #correct syntax for accessing your update cursor object row = YES #would be row[indexvalueofyourfield] See my example else row = cursor.next()
A good attempt for a first time, I would recommend trying some of their sample code first to get use to the syntax and outputs.
Have you read the sections and seen the code examples in the "cursors" sections of the help file? There are search cursors update cursors. Other sections on fields, queries etc. and their code examples will get you off to a good start. Also examining code snippets produced by other individuals, if you can find them on this site, will also serve you well.
Just about to read up on cursors, I'm sure that will help. Thanks for the advice.
If I may ask another question, is there a way to write a script that will spatially check the location of a point in one layer, to see if it's in a polygon in another layer and then check two fields in each of their attribute tables to see if they match? For example, I have two layers, one with a point where a water well was drilled, and one with county parcel data. I would want the script to see which parcel the well point is on, and then see if the name of the well owner and the name of the parcel owner match. Is this significantly more or less difficult than my original script?
Thanks so much for your help!
If you want to know which parcel the well point is on, why not do a spatial join first, that way you only need to iterate over 1 attribute table, after you do the spatial join.
ArcGIS Help (10.2, 10.2.1, and 10.2.2)
You will need to add another field to your points, so you can put "YES" it in.
This way you should only need 1 search cursor, which will need the the field names for the well owner, parcel owner, and field name that will contain the "Yes".
so after doing a spatial join and adding your new field it would look something like this.
import arcpy wells = "path here" wellowner = "Owner" #or whatever your field name is parcelowner = "Owner1" #or whatever your field name is with arcpy.da.UpdateCursor(wells, [wellowner, parcelowner, "Nameofyournewfieldhere"]) as cursor: for row in cursor: if row[0] == row[1]: row[2] = "YES" cursor.updateRow(row) else: continue
You did pretty well with your code, cursors can take a little while to get use to.
A little critique of your code:
import arcpy #perfect! wells = "path here" #good parcels = "path here" # good owner = ["Owner"] #no brackets needed, you want a string not a list(though it turns out okay in this case) powner = ["Owner1"] #see above cursor = arcpy.da.UpdateCursor(wells, ["Public"]) #correct syntax for making a cursor, kudos for using the data access cursor wellowner = arcpy.da.SearchCursor(wells, owner) #again correct syntax parcelowner = arcpy.da.SearchCursor(parcels, powner)#ditto if ( wellowner == parcelowner ) : #here would be the problem, you are comparing two cursor objects and not their values for row in cursor: #correct syntax for accessing your update cursor object row = YES #would be row[indexvalueofyourfield] See my example else row = cursor.next()
A good attempt for a first time, I would recommend trying some of their sample code first to get use to the syntax and outputs.
Thanks so much for taking the time to critique my code! Your help is greatly appreciated. I'm going to try to correct my code later today, although your method of doing the spatial join seems much easier, so I'm trying that route right now. When I run the code, though, I get a runtime error- it says that
file "<string>", line 9, in <module>
runtimeerror: workspace or data source is read only
I think part of my problem might be that I've had trouble setting the path properly. All the examples on the arcgis help have a .gdb file in the path, like so:
fc = "c:/data/base.gdb/roads"
this is the path I'm trying to use:
"P:/sections/Residential Sanitation/EHS-net Private Well Project/GIS - Work/Individual County Maps/Tom/WellParcelLoc.shp"
is it because I'm trying to access the shapefile and not a .gdb (I don't even know what that is, nor do I see that file anywhere near my shapefile) that I'm getting this read-only error?
Thanks!
Hi,
My first bed would be to change the file location to a place without special signs in it (like " ","-"). Some geoprocessing tools do not like these.
If the shapefile is viewed in any ESRI application like ArcMap or ArcCatalog it could be locked - this could result in a similar error. ESRI Applications are not good in deleting these locks after you are finished with the file - I had to close every ESRI app to get rid of the lock sometimes.
Upon closer inspection, when I view the shapefile and other files when Arcmap opens, it also creates (for as long as arcmap is open) a "LOCK" file. I assume this means that I need to run the script without arcmap open, but how can I do that? Could I use the command prompt in windows?
If you import arcpy you could run it from cmd.exe (commandline) or idle the integrated python ide.
You also could run the code via python window from arcCatalog but you should not have the catalogs cursor on the file than.
Hope it helps
Python is already on your computer, since you have ArcGIS it comes with Python 2.7 (or 2.6). You can just copy and paste the code I used into any text editor and save it as a .py file extension, and your computer should be able to run it by double clicking on it.
The lock file exists when you open ArcMap to prevent edits being made if the file is being accessed more than once(you have multiple maps open with that data, multipler users are using the same data, etc.). The code should work in the ArcMap python window, but might not if the map is open and the program is being run outside of ArcMap, since it is updating values, not just reading them.
I realized that part of the data that I used to make the join was data that I technically was not able to write. I copied it to a place where I could write and re-did the join, now the code works perfectly! Thank you so much. Unfortunately the names, I realize, are not in the same format or even capitalized the same way so now I'm trying to use the field calculator to split the names with a space as a delimiter, for whatever reason it gets the first names no problem but won't separate out the last names.
For the "OwnerFirst" and "OwnerLast" fields, I used..
OwnerFirst = !Owner!.split(" ")[0]
OwnerLast is the same but with a [1]. It got ~100 of the 2k last names out, but skipped some and I can't quite figure out why.