arcpy CalculateField - combine field values and derived value

866
4
Jump to solution
04-27-2020 09:46 AM
LeeO_Brien
New Contributor II

Newbie here. I've been trying to solve this for weeks and have searched and tried many suggestions from this site and still can't get this to work correctly.  I'm trying to use a derived value (max) from the Value field of a raster and use it in a calculation on each row of that field, and put the results in a new field (then use that field as a lookup to create a new integer raster). I can do this easily in desktop ArcGIS, but have several hundred rasters to process, so am trying to use an arcpy for loop.

It seems, if I specify the calculation expression outside of the For loop, I can get it to run a calculation on each row in the field, but can't get the derived value, using all the values in the field, into the calculation. If I define the expression inside the for loop (as below), it uses the constant value (max), but then won't iterate through each row in the Value field.  (This way the output rasters have only two values: 0 and 10.  The other way, they have the original raster values multiplied by whatever I set the maxValue variable to initially).

Can someone tell me what I'm doing wrong?

 

import arcpy
import os
from arcpy import env
from arcpy.sa import *
arcpy.CheckOutExtension("Spatial")

# Set environment settings
env.workspace = "...path/SpeciesR07_1"

# Set local variables
fieldName = "Frag"

# Processes: AddField, CalculateField, LookUp
for inRaster in arcpy.ListFiles("*.tif"):
     inRastName = os.path.splitext(inRaster)[0]
     outRastName = inRastName + "f.tif"
     maxValue = 0
     values = [row[0] for row in arcpy.da.SearchCursor(inRaster, "Value")]
     maxValue = max(values)
     expression = "(!Value! / {}".format(maxValue) + ") *10"
     arcpy.AddField_management(inRaster, fieldName, "SHORT")
     arcpy.CalculateField_management(inRaster, fieldName, expression, "PYTHON")
     lookupRast = Lookup(inRaster, fieldName)
     lookupRast.save("...path/SpeciesR07_Frag1/" + outRastName)

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
LeeO_Brien
New Contributor II

I figured out how to get the results I wanted. After trying several different ways to format the Value field in the expression, I abandoned this approach and used map algebra instead, on someone's advice. This doesn't require adding and calculating a field, or using Lookup. The final code that seems to be working is:

for inRaster in arcpy.ListFiles("*.tif"):
     inRastName = os.path.splitext(inRaster)[0]
     outRastName = inRastName + "f.tif"
     raster1 = arcpy.Raster(inRaster)
     rasterMax = raster1.maximum
     outRaster = Int(((raster1 / rasterMax) *10) +0.5)
     outRaster.save("...path/SpeciesR07_Frag1/" + outRastName)

A couple of tips I learned in doing this: use int for values and Int for rasters (capitalization matters!) and... adding 0.5 to the raster rounds the float values to integers, instead of just lopping off the decimals.

View solution in original post

0 Kudos
4 Replies
JoeBorgione
MVP Emeritus
expression = "(!Value! / {}".format(maxValue) + ") *10"

What are you trying to evaluate with this line?  I don't understand what 

+''

does for you.

That should just about do it....
0 Kudos
LeeO_Brien
New Contributor II

Trying to build the expression string: ( !Value! / num ) * 10

0 Kudos
LeeO_Brien
New Contributor II

where num = the max value in the !Value! field.

0 Kudos
LeeO_Brien
New Contributor II

I figured out how to get the results I wanted. After trying several different ways to format the Value field in the expression, I abandoned this approach and used map algebra instead, on someone's advice. This doesn't require adding and calculating a field, or using Lookup. The final code that seems to be working is:

for inRaster in arcpy.ListFiles("*.tif"):
     inRastName = os.path.splitext(inRaster)[0]
     outRastName = inRastName + "f.tif"
     raster1 = arcpy.Raster(inRaster)
     rasterMax = raster1.maximum
     outRaster = Int(((raster1 / rasterMax) *10) +0.5)
     outRaster.save("...path/SpeciesR07_Frag1/" + outRastName)

A couple of tips I learned in doing this: use int for values and Int for rasters (capitalization matters!) and... adding 0.5 to the raster rounds the float values to integers, instead of just lopping off the decimals.

0 Kudos