I am new to Jupyter notebooks in AGOL. I am trying to develop a script which updates a field in a hosted feature layer based on what has been entered in other fields. I am getting an error (code 400) pointing to the "for row in cursor:" line. This script works perfectly on my desktop machine. Any ideas as to what might be wrong? Here is what I am seeing in Notebook.
For one thing, ArcPy is only available in the advanced notebooks (the ones that cost you credits to run), so I'd make sure your notebook runtime is correct.
If you're working with hosted layers and AGOL, you're much better off using the ArcGIS Python API and spatially enabled dataframes. Here's a sample of how you might use it:
from arcgis import GIS # Log in to portal; for AGOL notebooks, you can also use gis = GIS("home") gis = GIS('portal-url', 'user', 'password') # Get your hosted layer you want updated fc = gis.content.get('itemID').layers # Query out all features to a dataframe df = fc.query(out_fields=['the', 'fields', 'you', 'need'], return_geometry=False, as_df=True) # Subset rows for those where 'field_a', etc., is greater than 0, add 1 to 'target_field' df.loc[df['field_a'] > 0, 'target_field'] = df['target_field'] + 1 df.loc[df['field_b'] > 0, 'target_field'] = df['target_field'] + 1 # And so on # Submit updated dataframe back to hosted layer as updates fc.edit_features(updates=df.spatial.to_featureset())
It's quite different from using cursors, but once you get the hang of using dataframes (see the pandas docs for more info), it will become much, much easier. And more versatile, as pandas is widely used with other python modules, and can import/export a wide variety of file formats.
Rather than using a bunch of if statements, the pandas loc indexer is grabbing a selection of rows and columns from the dataframe and operating on them separately. Within loc[x, y], x represents the rows. Here we supply "df['field_a'] > 0", so we're getting back all the rows that meet the condition. y represents the columns, and specifying a single column by its label, 'target_field', gives us only those values we wish to update.
Setting that selection equal to the 'target_field' value + 1, the dataframe only grabs the value at the same index, so you don't have to specify a subset for that operation.
Thanks for the interesting response.
I am indeed using an advanced notebook.
I will take a look at the dataframes, but would also really like to solve the problem with the UpdateCursor.
arcpy and arcpy.da are imported somewhere else in the notebook?
the error stems from the input featureclass name or location or the specified fields.
check both to make sure they "exist" in your code
Thanks a lot. Yes arcpy and arcpy.da are imported at the top of the notebook.
I found a small error in the fields list which I think was breaking it, so the error is now gone. However, now it doesn't seem to be resolving any of the if statements,. In fact it doesn't even appear to be stepping into the UpdateCursor. I tested this by putting a print statement directly after "for row in cursor:'. It runs with no error but isn't doing anyone of the assessments and incrementing the counter.
that row (row???? will only get updated in the last if statement
print the value prior to updating the row, I can't tell what is going on because flipping back and forth to the image is difficult. Try code formatting to make it easier to view code samples
Sorry about the problems with image of the code.
Here is the code:
from arcgis.gis import GIS gis = GIS("home") import arcpy, arcpy.da, requests, json inputFC = ''https://services8.arcgis.com/eDOP1zOdWfMRGgMh/arcgis/rest/services/?????/FeatureServer/0'' TableFields_VehicleAvailability = ['MajorPumpActualNum','MediumPumpActualNum','FireEnginesActualNum','WaterTankersActualNum','UrbanPumpersActualNum','FoamTendersActualNum','VeldFireVehActualNum','AerialFireActualNum','CommUnitsActualNum','RapidUnitsActualNum','FuelTendersActualNum','CrewBusesActualNum','FireBoatsActualNum','VehReplacePolicy','VehAvailMainScore']#,'VehAvailBonusScore','VehAvailCombScore'] VehAvailMain_Score = 0 VehAvailBonus_Score = 0 #calculate classification score for Vehicle Availability with arcpy.da.UpdateCursor(inputFC, TableFields_VehicleAvailability) as cursor: for row in cursor: VehAvailMain_Score = 0 VehAvailBonus_Score = 0 if (row > 0 or row > 0): #Major and Medium Pumps VehAvailMain_Score = VehAvailMain_Score + 1 print(row) if row > 0: #Fire Engines VehAvailMain_Score = VehAvailMain_Score + 1 if row > 0: #Water Tankers VehAvailMain_Score = VehAvailMain_Score + 1 if row > 0: #Veld Fire Vehicles VehAvailMain_Score = VehAvailMain_Score + 1 if (row == 'Yes' or row == 'No'): #vehicle replacement policy because always either Yes or No row = VehAvailMain_Score #VehAvailMainScore print(VehAvailMain_Score) cursor.updateRow(row) del cursor
'' .... ''
two single quotes surround your inputFC path. You said you found some issue with your field names. Are you still getting the same error message?
also all those
VehAvailMain_Score = VehAvailMain_Score + 1 #---- current VehAvailMain_Score += 1 # ---- suggested
lines can be written as suggested
for row in cursor: VehAvailMain_Score = 0 # ---- redundant VehAvailBonus_Score = 0 # ---- redundant
are defined outside the with statement and again within it. Do you want it redefined there as well?
two single quotes - sorry that is an error that crept in when I copied the code into the reply. The actual code I am testing has the inputFC in one set of single quotes.
I sorted out the issue with the field names and am no longer getting the error message, but the problem now is that the code doesn't seem to be getting into the UpdateCursor. None of the operations within the UpdateCursor are being fired. I placed some print statements within the UpdateCursor to test this and none of them print.
If it isn't getting to the cursor, then print statement outside are needed.
You indicate that it is supposed to be a featureclass. If so, then you should be able to print some of its properties. If that fails, then it isn't a featureclass, it doesn't exist or something else.