Using ArcGIS 10.7 desktop.
I want to reclassify a land use field using Field Calculator. Grasslands are conditionally reclassified using a 'veg_type' field (Avena, or Bromus) and a CWHR land use field (grassland values = Annual Grassland, AGS, Perennial Grassland). All other values in the CWHR field should stay the same.
When I run the Python Parser syntax the Grassland_Reclass field returns "Avena Grassland" (gridcode = 1) for the assigned land use values, but also for grasslands categorized as "Bromus' (gridcode = 0). The default CWHR values are added, but the elif condition (gridcode = 0) is not returned. I've also tried with the veg_type field but I get the same result.
def Reclass(gridcode, CWHR_TYPE):
if gridcode == 1 and CWHR_TYPE == "Annual Grassland" or CWHR_TYPE == "AGS" or CWHR_TYPE == "Perennial Grassland":
return "Avena Grassland"
elif gridcode == 0 and CWHR_TYPE == "Annual Grassland" or CWHR_TYPE == "AGS" or CWHR_TYPE == "Perennial Grassland":
return "Bromus Grassland"
else:
return CWHR_TYPE
Expression: Grassland_Reclass =
Reclass(!gridcode!, !CWHR_TYPE!)
2 Answers 2
Logical operator precedence and order of operators is causing your issue. Try grouping your or
s in parentheses:
e.g.
Wrong:
def Reclass(gridcode, CWHR_TYPE):
if gridcode == 1 and CWHR_TYPE == "Annual Grassland" or CWHR_TYPE == "AGS" or CWHR_TYPE == "Perennial Grassland":
return "Avena Grassland"
elif gridcode == 0 and CWHR_TYPE == "Annual Grassland" or CWHR_TYPE == "AGS" or CWHR_TYPE == "Perennial Grassland":
return "Bromus Grassland"
else:
return CWHR_TYPE
print(Reclass(0,"Annual Grassland"))
print(Reclass(1,"Annual Grassland"))
print(Reclass(0,"Perennial Grassland"))
print(Reclass(1,"Perennial Grassland"))
Output:
Bromus Grassland
Avena Grassland
Avena Grassland
Avena Grassland
Right:
def Reclass(gridcode, CWHR_TYPE):
if gridcode == 1 and (CWHR_TYPE == "Annual Grassland" or CWHR_TYPE == "AGS" or CWHR_TYPE == "Perennial Grassland"):
return "Avena Grassland"
elif gridcode == 0 and (
CWHR_TYPE == "Annual Grassland" or CWHR_TYPE == "AGS" or CWHR_TYPE == "Perennial Grassland"):
return "Bromus Grassland"
else:
return CWHR_TYPE
print(Reclass(0, "Annual Grassland"))
print(Reclass(1, "Annual Grassland"))
print(Reclass(0, "Perennial Grassland"))
print(Reclass(1, "Perennial Grassland"))
Output:
Bromus Grassland
Avena Grassland
Bromus Grassland
Avena Grassland
Even better, use the in
operator (thanks @fatih_dur):
Right:
def Reclass(gridcode, CWHR_TYPE):
if gridcode == 1 and CWHR_TYPE in ("Annual Grassland", "AGS", "Perennial Grassland"):
return "Avena Grassland"
elif gridcode == 0 and CWHR_TYPE in ("Annual Grassland", "AGS", "Perennial Grassland"):
return "Bromus Grassland"
else:
return CWHR_TYPE
-
Placing the parentheses around the CWHR values made the difference - thank you! (The binary grid code covers all CWHR land use features, not just the grasslands, which is why I needed to include the grassland classes to sort out.)kent– kent2020年08月01日 18:52:46 +00:00Commented Aug 1, 2020 at 18:52
-
1Left to right evaluation isn't relevant here. The problem is due to the precedence of
and
andor
.user2357112– user23571122020年08月02日 08:43:01 +00:00Commented Aug 2, 2020 at 8:43
What you are seeing is due to the fact that and
takes precedence over or
. a and b or c
is the same as (a and b) or c
and not a and (b or c)
, as you assumed.
As mentioned in the other answer, you can use parentheses to change the precedence (because parentheses have a higher precedence than either of and
and or
), or even better, use in
. You can also turn your checks around, like this:
def Reclass(gridcode, CWHR_TYPE):
if CWHR_TYPE not in ("Annual Grassland", "AGS", "Perennial Grassland") or gridcode not in (0, 1):
return CWHR_TYPE
return "Avena Grassland" if gridcode == 0 else "Bromus Grassland"
Explore related questions
See similar questions with these tags.
gridcode
, given the rest to the right hand side is the same. Also, pyhon hasin
operator and it is great replacement for multipleor
s and easier to read, e.g.,CWHR_TYPE in ("Annual Grassland", "AGS", "Perennial Grassland")
CWHR_TYPE
is "Annual Grassland
") the correct language to use isSQL
. Do not use python. UseSQL
.SQL
is quite literally, designed to do nothing but manage tables of data.