Calculate summary statistics in Python - return result NOT a table

6471
9
Jump to solution
08-05-2013 05:28 AM
MikeTree
New Contributor III
I want to use python to calculate the area of a number of different fields (using where clauses to filter results) and then output results to my own text file.

The summary statistics tool lets you output a separate table but I don't want an external table: http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/Summary_Statistics/00080000001z000000/

I just want to return the results within python, eg:
- create selection
- return sum area for a field within that selection
- do something with the returned result

How can I do this without creating separate tables in dbf? It must be really simple to do.

Thank you
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
T__WayneWhitley
Frequent Contributor
Python and arcpy offers you a lot of flexibility.  On the face of things, sounds like you may want to perhaps use a cursor with a query to filter the return, then you can within a loop gain access to area and tally it up, see this:

SearchCursor (arcpy.da)
Desktop » Geoprocessing » ArcPy » Data Access module
http://resources.arcgis.com/en/help/main/10.1/index.html#//018w00000011000000

Notice access to geometry properties with a token, as in your case for area:  SHAPE@AREA


As for your other question about not returning separate tables, but maybe you want some output in-memory, see the below link particularly the section about Using in_memory in Python (if all you want is area as in the above example, you don't need an output workspace).

Using in-memory workspace
Desktop » Geoprocessing » ModelBuilder
http://resources.arcgis.com/en/help/main/10.1/index.html#//002w0000005s000000


...that should at least get you started - you can follow-up with more specific questions.

Enjoy,
Wayne


The SearchCursor example 3, quickly modified to sum area (untested):
import arcpy  fc = "c:/data/base.gdb/well" areaTotal = 0.0  # For each row print the Object ID field, and use the SHAPE@AREA #  token to access geometry properties # with arcpy.da.SearchCursor(fc, ("OID@", "SHAPE@AREA")) as cursor:     for row in cursor:         print("Feature {0} has an area of {1}".format(row[0], row[1]))          areaTotal += row[1]  print("Features have a total area of {0}".format(areaTotal))


Refer to one of the other examples to add an expression to the cursor in order to tally area on a feature subset.

View solution in original post

0 Kudos
9 Replies
T__WayneWhitley
Frequent Contributor
Python and arcpy offers you a lot of flexibility.  On the face of things, sounds like you may want to perhaps use a cursor with a query to filter the return, then you can within a loop gain access to area and tally it up, see this:

SearchCursor (arcpy.da)
Desktop » Geoprocessing » ArcPy » Data Access module
http://resources.arcgis.com/en/help/main/10.1/index.html#//018w00000011000000

Notice access to geometry properties with a token, as in your case for area:  SHAPE@AREA


As for your other question about not returning separate tables, but maybe you want some output in-memory, see the below link particularly the section about Using in_memory in Python (if all you want is area as in the above example, you don't need an output workspace).

Using in-memory workspace
Desktop » Geoprocessing » ModelBuilder
http://resources.arcgis.com/en/help/main/10.1/index.html#//002w0000005s000000


...that should at least get you started - you can follow-up with more specific questions.

Enjoy,
Wayne


The SearchCursor example 3, quickly modified to sum area (untested):
import arcpy  fc = "c:/data/base.gdb/well" areaTotal = 0.0  # For each row print the Object ID field, and use the SHAPE@AREA #  token to access geometry properties # with arcpy.da.SearchCursor(fc, ("OID@", "SHAPE@AREA")) as cursor:     for row in cursor:         print("Feature {0} has an area of {1}".format(row[0], row[1]))          areaTotal += row[1]  print("Features have a total area of {0}".format(areaTotal))


Refer to one of the other examples to add an expression to the cursor in order to tally area on a feature subset.
0 Kudos
JamesCrandall
MVP Frequent Contributor
I use the Pandas Package for getting summary stuff.  The DataFrame (not an ArcGIS "DataFrame" concept) is really powerful for building and shaping data to meet your needs --- I incorporate it into matplotlib Package for generating hydrographs, but there is just a ton of functionality.

https://pypi.python.org/pypi/pandas

Example below shows a normal array/list that was populated with some data and getting min/max values from the date field:

#set the pandas dataframe to the array
dbhydDF = DataFrame(datArray, columns=['site', 'value', 'dateread'])

#get min/max date values    
dmax = dbhydDF.dateread.max()
dmin = dbhydDF.dateread.min()

#not tested, but I think you just issue .sum to get a sum value from the appropriate field
dsum = dbhydDF.value.sum()
0 Kudos
MikeTree
New Contributor III
Thanks folks. I couldn't find a way to do what I needed, so I just ended up creating a table (in a GDB) using the arcpy.Statistics_analysis tool, extracting the value from the table using a searchcursor, and then overwriting the table each time. A bit of a go-around, but it works.

If anyone can think of a better way then I'd be keen to hear. Thanks
0 Kudos
JamesCrandall
MVP Frequent Contributor
Thanks folks. I couldn't find a way to do what I needed, so I just ended up creating a table (in a GDB) using the arcpy.Statistics_analysis tool, extracting the value from the table using a searchcursor, and then overwriting the table each time. A bit of a go-around, but it works.

If anyone can think of a better way then I'd be keen to hear. Thanks


I didn't think of it at the time, but yes there is a much better solution -- especially if you are not wanting to write to disk....

FeatureClassToNumPyArray
http://resources.arcgis.com/en/help/main/10.1/index.html#//018w00000015000000

The example even has your requirement to sum a field!

Good luck,
james
0 Kudos
RhettZufelt
MVP Frequent Contributor
I just want to return the results within python, eg:
- create selection
- return sum area for a field within that selection
- do something with the returned result



Not sure why Waynes answer didn't work for you?
I use this code all the time (in my case, I switch the scale of a map depending on how large my areas are).  This will "return sum area for a field within that selection" for the selected features (or, features that match def query in mxd). Which is now just a number that you can "do something with".

Just need to make sure that the selection or def query (however you are limiting your results) is put on the layer before you searchcursor the area.

          warea = 0
          with arcpy.da.SearchCursor(lyr1, "SHAPE@AREA") as cursor:
             for row in cursor:
                warea += row[0]
          del cursor


R_
0 Kudos
MikeTree
New Contributor III
Thanks for the tips - I'm using 10.0 so don't have access to arcpy.da, but am keen to use it before too long!
0 Kudos
T__WayneWhitley
Frequent Contributor
Oh, well in that case, you can still do something like this:
>>> import arcpy
>>> arcpy.env.workspace = r'C:\YOUR GDB.gdb'
>>> fc = 'YOUR FC'
>>> rows = arcpy.SearchCursor(fc)
>>> area = 0.0
>>> for row in rows:
               area += row.Shape.area
 
               
>>> print area
471790363.853
>>>  
0 Kudos
MikeTree
New Contributor III
Precisely, many thanks. That method works, and note I used the following line to filter out WHERE clause queries that resulted in empty records being returned:

if arcpy.SearchCursor(activelayer).next() == None:


However this is quite a slow way to essentially do a non-spatial database operation, which spawned me to ask this question over at another site, http://gis.stackexchange.com/questions/68205/non-spatial-database-analysis-in-arcgis-need-alternativ...

If anyone has any tips on how best to trawl through my data I'd be very grateful.

Many thanks
0 Kudos
T__WayneWhitley
Frequent Contributor
....if I am understanding correctly the entire situation, you may optionally apply what I call a 'query filter' to the cursor as the following which was applied to the same dataset I used in my last post:
>>> where_clause = arcpy.AddFieldDelimiters(fc, 'UNIT') + ' IS NOT NULL'
>>> print where_clause
"UNIT" IS NOT NULL
 
>>> rows = arcpy.SearchCursor(fc, where_clause, '', 'Shape; UNIT')
 
>>> area = 0.0
>>> for row in rows:
               area += row.Shape.area
 
               
>>> print area
17385325.4074
>>>
0 Kudos