I'm trying to calculate the percentage of cell counts in new raster and the new raster is created from an old raster based on the Value > 14. In my code, 1st for loop is for original raster and keeping the value and count fields in a dictionary. Then, creating new raster using Value > 14. The 2nd for loop is for the new raster and keeping its value and counts of in a new dictionary and finally calculating the percentage.

However, I am getting an error on the 2nd for loop. The error says:

'Raster' object is not iterable

Does anybody have a suggestion?


import arcpy, os
from arcpy import env
from arcpy.sa import *

#To overwrite output
arcpy.env.overwriteOutput = True

#Set environment settings
env.workspace = "C:/Subhasis/Test/Neshanic_Python"


#checkout ArcGIS spatial analyst extension license

# set local variable
inraster = ["01367620-r-r"]

for i in inraster:
    flds = ("VALUE", "COUNT") 
    dct = {row[0]:row[1] for row in arcpy.da.SearchCursor(i, flds)} 
    sumcnt = sum(dct.values())
    newraster = ExtractByAttributes(str(i), "VALUE>=14")
    for j in newraster:
        flds1 = ("VALUE", "COUNT")
        dct1 = {row[0]:row[1] for row in arcpy.da.SearchCursor(j, flds)}
        sumcnt1 = sum(dct1.values())
        print percentage
  • 1
    Maybe the new raster needs an attribute table built (see Build Raster Attribute Table). Also, the dct1 = ... line needs to end with flds1 not flds.
    – Erica
    Jul 23 '14 at 16:05
  • Actually, I am not sure why you are making the second raster. Can you just calculate the statistics from the dictionary of values?
    – Erica
    Jul 23 '14 at 16:07

I suggest that you do not need to make a second raster to accomplish this. Rather, use Python to sub-set the dictionary to select only the desired values. This should both bypass the problem, and run faster.

# original dictionary from raster
dct = {row[0]:row[1] for row in arcpy.da.SearchCursor(i, flds)}
sumcnt = sum(dct.values())

# new dictionary with only values >= 14
dct1 = {k:v for (k,v) in dct.items() if k >= 14}
sumcnt1 = sum(dct1.values())

percentage = float(sumcnt1) / float(sumcnt)
  • Hi Erica, Thanks for your quick response. I tried your code, The percentage I found is 1, which should be less than 1. I am thinking it is calculating the same counts in the second dictionary.
    – Inception
    Jul 23 '14 at 16:55
  • I had sumcnt1 and sumcnt in the wrong places in percentage, I've reversed that. There's a float/int problem still...
    – Erica
    Jul 23 '14 at 16:57
  • I changed numerator and denominator in percentage and got "0" value. Then tried printing dct and dct 1. In dct1, I got all the value similar to dct except the 1st vale and counts. see the print of both dictionary in the next comment.
    – Inception
    Jul 23 '14 at 17:12
  • 1
    OK, it is filtering on the count instead of the value. Change v >= 14 to k >= 14. Also make sure the two sumcnt variables are explicitly cast as float (otherwise it's rounding the percentage, which will always be an int of 0).
    – Erica
    Jul 23 '14 at 17:17
  • 1
    Sure (although if it's moderately complex, another Question would also work)
    – Erica
    Jul 23 '14 at 18:10

The real issue lies in the line:

for j in newraster:

where you are indeed trying to loop (iterate) through a raster object, which is not "loopable". As Erica points out, this won't work and is not necessary.

I think you are simply trying to figure out what % of the cells have a value >= 14, correct? Erica has a correct answer - althoiugh populating a new dictionary with the values >= 14 is not necessary I think. Another correct answer would look like this:

valueDct = {row[0]:row[1] for row in arcpy.da.SearchCursor(i, flds)}
valSum = sum(valueDict.values())
valFilterSum = sum([valueDct[i] for i in valueDct if i >= 14])
percentage = float(valFilterSum) / valSum
  • I had valFilterSum list comp wrong - now correct!
    – csny490
    Jul 23 '14 at 19:07
  • Thank you for your post. I got the answer using Erica's code.
    – Inception
    Jul 23 '14 at 20:00
  • Hmm. Alright, I would do from next time onwards..
    – Inception
    Jul 23 '14 at 21:36
  • 1
    Indeed, this is a more concise approach. I tend to err on the side of unnecessarily verbose code when introducing programming structure, but a tighter structure is what I would personally use.
    – Erica
    Jul 23 '14 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.