POST
|
As the title says, I am using arcpy.da.UpdateCursor() and I can't get it to update the rows. My code is below. (Yes, I know I am still working with a nested cursor... I haven't decided if a dictionary is the right way to go for my purposes yet. That's for another topic.) fields = ["SOIL", "MAX_SLOPE", "MIN_CDA", "MAX_CDA", "WT_SEP", "WT_RELAX",
"COAST_SEP", "MIN_DEPTH", "DEPTH_RELA", "COAST_MIN_", "BMP", "MOD"]
for row in arcpy.da.SearchCursor(combo_table, ["DARAS", "HSG", "MEDSLOPE", "MEDWT"]):
print("Saving constraint table for DA " + str(row[0]) + " and HSG " + str(row[1]) + "...")
arcpy.Copy_management(compare, BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]))
arcpy.AddField_management(BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]), "MOD", "TEXT", "", "", 25)
with arcpy.da.UpdateCursor(BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]), fields) as cursor:
for r in cursor:
# Compare water table depths
if r[4] + r[7] > row[3]:
if r[5] == 1:
coast_WT = r[6]
else:
coast_WT = r[4]
if r[8] == 1:
coast_depth = r[9]
else:
coast_depth = r[7]
if coast_WT + coast_depth < row[3]:
if r[5] == 1 and r[8] == 1:
r[11] = "Separation and Depth"
print("Modifying " + str(r[11]) + "allows for " + str(r[10]) + "...")
elif r[5] == 1:
r[11] = "WT Separation"
print("Modifying " + str(r[11]) + "allows for " + str(r[10]) + "...")
elif r[8] == 1:
r[11] = "Practice Depth"
print("Modifying " + str(r[11]) + "allows for " + str(r[10]) + "...")
cursor.updateRow(r)
if coast_WT + coast_depth > row[3]:
print("Removing " + str(r[10]) + " from DA " + str(row[0]) +
" HSG " + str(row[1]) +" based on water table proximity...")
cursor.deleteRow() As the title states, I am not getting any errors when I run this code. When I open my file, the "MOD" field is blank for all rows still. My print statements are not printing before or after the r[11] = "TEXT" line even when they are modified to exclude calling r[11]. They worked at one point while I was getting errors with cursor.updateRow() but now there's nothing. My last print statement works, "Removing ..." though.
... View more
04-22-2015
10:15 AM
|
0
|
4
|
2755
|
POST
|
Ah! I see. I got it to work with this code. Thank you! # Create output table for each drainage area
for row in arcpy.da.SearchCursor(combo_table, ["DARAS", "HSG", "MEDSLOPE", "MEDWT"]):
print("Saving constraint table for DA " + str(row[0]) + " and HSG " + str(row[1]) + "...")
arcpy.Copy_management(compare, BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]))
# DAmask = arcpy.sa.SetNull(DAras, DAras, "VALUE <> " + str(row[0]))
# arcpy.env.mask = DAmask
# arcpy.env.snapRaster = DAmask
arcpy.AddField_management(BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]), "MOD", "TEXT", "", "", 14)
# Check constraints against the site values and remove infeasible stormwater practices
with arcpy.da.UpdateCursor(BMPFold + "\\" + "da" + str(row[0]) + "hsg" + str(row[1]), fields) as cursor:
for r in cursor:
print("Checking for incompatible soil types...")
if row[1] not in r[0]:
print("Removing " + str(r[10]) + " based on soil type...")
cursor.deleteRow() So, I just now noticed the second part of your reply: "That also raises the question about the comparison logic. If you do not query the table for any specific records, than I would expect many records to not match your row values, and the row would virtually always be deleted. A dictionary would help with this, since doing a if not row[0] in dict: compares to all the of dictionary keys you previously loaded from the entire table at once, not to just one row at a time in the comparison table." Before I move on to trying to construct a dictionary, I want to be sure it's going to do what I want it to do. It sounds like you're saying that constructing a dictionary will compare all the rows in the constraint table to the combo_table dictionary all at once and remove rows from the constraint table in a group rather than row-by-row. Right? For each row in my Combo_Table, I have a separate constraint file that I want to be edited. Each constraint table should be checked against the values in just one row of the combo table, not all of them at once.
... View more
04-21-2015
08:53 AM
|
0
|
0
|
1403
|
POST
|
I added "break" to my code and now it loops through all the expected combinations of drainage zone and soil type and copies the constraint table for each! But, I found that it didn't delete the rows in the table. row[1] = "HSG" from combo_table r[0] = "SOIL" from table DA1HSGD # Create output table for each drainage area
for row in arcpy.da.SearchCursor(combo_table, ["DARAS", "HSG", "MEDSLOPE", "MEDWT"]):
print("Saving constraint table for DA " + str(row[0]) + " and HSG " + str(row[1]) + "...")
arcpy.Copy_management(compare, BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]))
# DAmask = arcpy.sa.SetNull(DAras, DAras, "VALUE <> " + str(row[0]))
# arcpy.env.mask = DAmask
# arcpy.env.snapRaster = DAmask
arcpy.AddField_management(BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]), "MOD", "TEXT", "", "", 14)
# Check constraints against the site values and remove infeasible stormwater practices
for r in arcpy.da.UpdateCursor(BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]), fields):
print("Removing incompatible soil types...")
if row[1] not in r[0]:
del(row)
break It saves the tables as all lowercase and I am calling an uppercase version. Could that be the problem? How do I convert row[1] into lowercase for the purpose of calling the correct table? Here are my tables in case it helps to see them:
... View more
04-21-2015
08:13 AM
|
0
|
2
|
1403
|
POST
|
The last part, the nested cursor, is throwing the error. I always use "row" in my code for cursors (except in this nested cursor case). Is that a bad thing? for r in arcpy.da.UpdateCursor(BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]), fields):
if row[1] not in r[0]:
del(row) I thought it might be inefficient but I didn't have a better way to do it. I'll check out your blog post and see what I can do with a dictionary instead. Thank you. I will probably have some questions later on since I've never used a dictionary before.
... View more
04-21-2015
07:37 AM
|
0
|
4
|
1403
|
POST
|
Yes, thank you, I actually started correcting that before you even posted! It loses the indents when I copy it over and I always forget. I am trying to correct it but the last few indents don't want to stick for some reason.
... View more
04-21-2015
06:57 AM
|
1
|
0
|
1403
|
POST
|
I am finding it hard to articulate what I am trying to do, so here's what I have and here's where I'm going. I have: 4 raster datasets. One is a set of drainage zones, one is the soil type, one is slope, and one is depth below surface. I also have a large table of stormwater practices and their associated physical constraints. Desired outcome: For each drainage zone, I want a list of stormwater practices that can go on the site. What I've done: For each drainage zone, I have found the median slope and median depth below surface using Zonal Statistics. I have combined the median slope, median depth, drainage zone, and soil type into a single raster dataset using the Combine function. I have used the Build Raster Attribute Table to have all of those values available to me in a single table without converting it back to a shapefile. I have a Cursor set up to duplicate the constraint table for each unique combination of drainage zone and soil type. What I want to do: I want to compare the Combination table to the table of constraints and delete rows from the constraint table when certain conditions are met. For example, some stormwater practices only work on soil types A and B, so if the soil type in the constraint table is not found in the row for the combination table, I want the row in the constraint table to be deleted. Here is the code I have come up with to help you understand my goal.
# Combine rasters to give unique combinations
combo = arcpy.sa.Combine([DAras, EffHSG, med_WT, med_slope])
combo.save(WorkPath + r"\combo")
combo_table = arcpy.BuildRasterAttributeTable_management(combo)
# Convert integer HSG code to string type
arcpy.AddField_management(combo_table, "HSG", "TEXT", "", "", 6)
with arcpy.da.UpdateCursor(combo_table, ["EFFECTIVEHSG", "HSG"]) as cursor:
for row in cursor:
if row[0] == 1:
row[1] = "A"
if row[0] == 2:
row[1] = "B"
if row[0] == 3:
row[1] = "C"
if row[0] == 4:
row[1] = "D"
cursor.updateRow(row)
### _____________COMPARE CRITERIA_____________________ ###
print("Creating BMP output folder...")
# Define location of constraint database and establish new output location
CRIT = TabPath + "constraints.xlsx"
BMPFold = ProjFolder + r"\BMP__Tables"
if not os.path.exists(BMPFold):
os.makedirs(BMPFold)
print("Loading constraint database...")
# Convert Excel constraint file to GIS table
compare = arcpy.ExcelToTable_conversion(CRIT, ProjFolder + r"\constraints")
fields = ["SOIL", "MAX_SLOPE", "MIN_CDA", "MAX_CDA", "WT_SEP", "WT_RELAX",
"COAST_SEP", "MIN_DEPTH", "DEPTH_RELA", "COAST_MIN_"]
# Create output table for each drainage area
for row in arcpy.da.SearchCursor(combo_table, ["DARAS", "HSG", "MEDSLOPE", "MEDWT"]):
arcpy.Copy_management(compare, BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]))
DAmask = arcpy.sa.SetNull(DAras, DAras, "VALUE <> " + str(row[0]))
arcpy.env.mask = DAmask
arcpy.env.snapRaster = DAmask
arcpy.AddField_management(BMPFold + "\\" + "DA" + str(row[0]), "MOD", "TEXT", "", "", 14)
for r in arcpy.da.UpdateCursor(BMPFold + "\\" + "DA" + str(row[0]) + "HSG" + str(row[1]), fields):
if row[1] not in r[0]:
del(row) The problem: I get an error saying that "NameError: name 'row' is not defined" for line 41, "if row[1] not in r[0]:". Once the code enters the nested cursor, "row" gets wiped out and is no longer a valid parameter. What is a workaround for this? EDIT: The python syntax converter works very poorly on my computer for some reason. Sorry. I tried to update it so the indentations are in the right place. If they do not appear in the correct spot, I promise they are correct in my actual code and that is not the problem.
... View more
04-21-2015
06:29 AM
|
0
|
8
|
4774
|
POST
|
Nevermind, I'm just going to delete this post...! I was running the wrong code....
... View more
04-16-2015
09:37 AM
|
0
|
0
|
1132
|
POST
|
Oh, it's write in PyCharm but it copied wrong. I'll edit my main post accordingly. It still isn't printing the "Time to delete", is giving me no errors, and is not deleting.
... View more
04-16-2015
09:35 AM
|
0
|
0
|
1132
|
POST
|
In case you're interested: I got the first part of my program to run and give good outputs! Yay! Thanks for all your help, everyone. It took me a while to write these basic lines of code but I learned a lot in the process and I am eager to apply what I learned to the hard part of my program next. But first... My problem: I want to script a code that will delete all the working directories created by my program. I've got this code: # This script is meant to be used to clear the working directories for a particular
# map file. The user selects the map file they are trying to use the program with
# and this program deletes the working folders bearing the name of the .MXD file.
# This is a tool meant to clean the slate in case write errors are encountered during
# tool operation.
#### _______________IMPORT MODULES_________________###
import os
import shutil
### ________________SET ENVIRONMENTS__________________###
# Set Map Document
MapLoc = r"C:\Users\Rachael Johnson\Documents\GradWork\GIS\LakeRidge\LRpythontest.mxd"
# Establish paths
WorkPath = MapLoc[:-4]
path, filename = os.path.split(MapLoc)
GDBpath = MapLoc[:-4] + ".gdb"
TabPath = r"C:\outputtable" "\\"
ProjFolder = TabPath + filename[:-4]
### __________________DELETE PATHS ASSOCIATED WITH MXD___________ ###
print("Time to delete")
if os.path.exists(WorkPath):
print("deleting...")
try:
shutil.rmtree(WorkPath)
except:
raise
else:
print("No such path:" + WorkPath)
print("Deleted working and scratch folders in the MXD location:" + path)
shutil.rmtree(ProjFolder)
print("Deleted the project table output folder in" + TabPath)
shutil.rmtree(GDBpath)
print("Deleted the project geodatabase in the MXD location:" + path) I've also tried this code without the if statement--just shutil.rmtree(path)-- and I have the same problem. I even tried "ignore_errors=True". Same thing. I have two more directories I'd like to remove but I guess I should get just one working first. I run this code and don't get any errors but the folder deletion doesn't happen either. I added the if statement and print statements to see where the hang-up was and it doesn't even print "Time to delete", which tells me it isn't even reading the code for some reason?? I'm at a loss for what to do. EDIT: I am running Windows 8.1. My code is in Python 2.7 or whatever version is currently used for ArcGIS 10.3. I am running my code from PyCharm Professional v 4.0.6
... View more
04-16-2015
08:43 AM
|
0
|
3
|
3533
|
POST
|
Whoo it worked! And I can use SearchCursor to pull out the values so I can use them in my program. Awesome. Thanks a ton!
... View more
04-14-2015
09:32 AM
|
0
|
0
|
1096
|
POST
|
Ohmygod. I have been racking my brain trying to figure out how to loop this thing and there's a built in function that does it for me?? I was toying with converting to raster and using combine/zonal stats if all else failed. It should have occurred to me to check for a similar shapefile function. Thank you! I'll see if this gives the output I desire.
... View more
04-14-2015
09:09 AM
|
0
|
0
|
1096
|
POST
|
This is less of a python question and more of a general logic question, I suppose. I have a shapefile that represents the intersection of soil types and drainage boundaries. I want to sum the total area of each soil type within each drainage boundary. There are 4 soil types. There are a potentially unlimited number of drainage areas. Soil type (HSG) field: "GRIDCODE" Drainage area field: "DA" Area: "Area" I have a code that extracts unique values from the drainage area field. My problem is that I am not sure how to implement a loop sequence that iterates through each unique drainage value to find the instances of the soil types and sum the Area without manually coding each one. Earlier, I summed the areas of all the soil types with the following code: with arcpy.da.SearchCursor(SiteHSG, ["gridcode", "Area"]) as cursor:
# Initialize variables
SiteArea_A = 0.000
SiteArea_B = 0.000
SiteArea_C = 0.000
SiteArea_D = 0.000
# Calculate area for each HSG
for row in cursor:
if row[0] == 1:
SiteArea_A = SiteArea_A + row[1]
if row[0] == 2:
SiteArea_B = SiteArea_B + row[1]
if row[0] == 3:
SiteArea_C = SiteArea_C + row[1]
if row[0] == 4:
SiteArea_D = SiteArea_D + row[1] I have no idea if there was a better way to calculate those areas or not and I have no problem using a similar code over and over, basically, but I do not know how to tell the computer that for each unique DA value, find soil type, and sum those soil types, then move on and search for the next unique DA value and iterate through the grid codes and sum the area. I am kind of thinking a "while" loop may be able to accomplish what I need, but then I am not really sure how to implement a while loop in this context. I am kind of thinking of something like this so far: DAvalues = [row[0] for row in arcpy.da.SearchCursor(DAHSG, DAID)]
DAunique = set(DAvalues)
print(DAunique)
with arcpy.da.SearchCursor(DAHSG, ["DA", "gridcode", "Area"]) as cursor:
for row[0] == DAunique[0]
if row[1] == 1:
SiteArea_A = SiteArea_A + row[3]
if row[1] == 2:
SiteArea_B = SiteArea_B + row[3]
if row[1] == 3:
SiteArea_C = SiteArea_C + row[3]
if row[1] == 4:
SiteArea_D = SiteArea_D + row[3]
for row[0] == DAunique[1]
if row[1] == 1:
SiteArea_A = SiteArea_A + row[3]
if row[1] == 2:
SiteArea_B = SiteArea_B + row[3]
if row[1] == 3:
SiteArea_C = SiteArea_C + row[3]
if row[1] == 4:
SiteArea_D = SiteArea_D + row[3] Etc. I know there's a better way to do this than making a bunch of different for loops, especially because the number of unique values are unlimited. It's impractical for me to code it this way but I'm not sure where to go.
... View more
04-14-2015
09:00 AM
|
0
|
4
|
3491
|
POST
|
Actually, now that I'm running things out of PyCharm instead of the GIS Python window, I see now how the results aren't being added and how it doesn't make layers for it. It's much faster to run my program from PyCharm than from the GIS Python window, too! So I see that removing the results/layers is eventually going to be superfluous. I can add any layers to the map when my code is all complete, I assume. Thank you for taking the time to help me! I learn so much every time I post on here. I hope one day I know enough about Python to help with other people's problems!
... View more
04-13-2015
11:43 AM
|
0
|
1
|
1596
|
POST
|
It helped because now I know about Results vs Layers! Sure enough, my SoilUnclass is a Result data type. I am not sure how you managed to get it to add the OutLocation layer, however. Is it because it is in the memory and it adds the layer automatically in that case?
... View more
04-13-2015
11:19 AM
|
0
|
1
|
1596
|
POST
|
If I save and redefine my mxd, then it works. Should that be necessary?
... View more
04-13-2015
10:34 AM
|
0
|
5
|
1596
|
Title | Kudos | Posted |
---|---|---|
1 | 06-09-2017 09:27 AM | |
1 | 06-10-2015 09:02 AM | |
1 | 04-21-2015 06:57 AM | |
2 | 08-19-2015 08:14 AM | |
2 | 06-09-2015 11:35 AM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:23 AM
|