Tuesday 2 April 2019

Arcpy to append results of pivot table



I have a script that does some processing but the main part are two things



  1. run a multiple ring buffer using arcpy.MultipleRingBuffer_analysis and four rings

  2. do some zonal statistics using arcpy.sa.ZonalStatisticsAsTable on the four rings


I do this repetitively (through a loop) so I want to dump the results to a table called Final Results. It makes sense to me to have the results organized in five columns (PatientID, Distance1, Distance2, Distance3, Distance4). I making my loop off a search cursor and keeping the PatientID.


I thought to create a pivot table using arcpy.PivotTable_management where the result becomes one row and five columns (the pivot variable and four buffers) and then push that to Final Results. However, it appears I would still need to create a search cursor for my pivot table, grab the first (and only) row, then create an insert cursor to put the data into my Final Resultstable.


Alternatively, I suppose I could just go to the table from #2 above, create a search cursor, and assign four variables (D1, D2, D3, D4) to the zonal stats results with some sort of switch-case statement, then create an insert cursor that concatenates D1, D2, D3, D4 and uses insert row.


Both seem rather inefficient.


Is there a smarter way to just push my results from zonal analysis into a table that I use?




Answer



You cannot use multiple rings because it produces overlapping circles, no good for zonal statistics. Try this one:


import arcpy, traceback, os, sys
import itertools as it
from arcpy import env
env.overwriteoutput=True
env.workspace=r'in_memory'

points = r'D:\Scratch\points.shp'
pFields=['Shape@',"DISTANCE1","DISTANCE2","DISTANCE3","DISTANCE4"]

distances=[5,10,15,20]
raster=r'D:\Scratch\dem_ext'
victRaster=r'in_memory\rtem'

try:
def showPyMessage():
arcpy.AddMessage(str(time.ctime()) + " - " + message)
pgon=arcpy.Geometry()
with arcpy.da.UpdateCursor(points,pFields) as cursor:
m=0

for row in cursor:
point=row[0]
for i in range(4):
buf=point.buffer(distances[i])
anExtent=buf.extent
envelope='%f %f %f %f' %(anExtent.XMin, anExtent.YMin, anExtent.XMax, anExtent.YMax,)
arcpy.Clip_management(raster,envelope,victRaster,buf,"-3.402823e+038","ClippingGeometry")
extract = arcpy.RasterToNumPyArray(victRaster,"","","",-9999)
chain = it.chain.from_iterable(extract)
reduced=filter(lambda x: x not in [-9999],chain)

mean=sum(reduced)/float(len(reduced))
row[1+i]=mean
m+=1
cursor.updateRow(row)
arcpy.AddMessage(m)
except:
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
message = "Python Error Info: " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()


it took 2.5 minutes to process 1000 points. Results stored in parent table, you have to modify inputs, e.g. points, fields, raster. Script assumes that fields exist.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...