I have a field, CHPROPSC, that I would like to code with missings as -97, -98 or -99 and a calculated value based on the value of field PRCHSCH04 and PRCHSCH13.
Essentially, if the value in PRCHSCH04 is -99 only then CHPROPSC = -98. If the value in PRCHSCH13 is -99 only then CHPROPSC = -97. If the value in both is -99 then CHPROPSC = -99. Otherwise CHPROPSC = PRCHSCH13 - PRCHSCH04.
I tried this Python script (and a few variations of this) without the codeblock but there was a processing failure:
-97 if !PRCHSCH13! == -99 & !PRCHSCH04! <> -99
-98 elif !PRCHSCH13! <> -99 & !PRCHSCH04! == -99
-99 elif !PRCHSCH13! == -99 & !PRCHSCH04! == -99
else float( !PRCHSCH13! )- !PRCHSCH04!
I am sure my syntax with the elif is the most likely problem. Any advice as to where the error is here?
Thanks,
Steve
Welll firstly, I don't think you want to do bitwise operations do you? 5. Built-in Types — Python 2.7.11 documentation
in python ... & ... is not the same as ... and ...
>>> a = 5 >>> b = 6 >>> a == b False >>> a & b 4
Not quite what you expect
Also reformulate your code into a standard if elif else statement before you try to simplify it.
Try:
-97 if !PRCHSCH13! == -99 and !PRCHSCH04! <> -99
else -98 if !PRCHSCH13! <> -99 and !PRCHSCH04! == -99
else -99 if !PRCHSCH13! == -99 and !PRCHSCH04! == -99
else float( !PRCHSCH13! ) - !PRCHSCH04!
I'll just say this type of thing is somewhat frowned upon as being difficult to read.
Other thoughts
pretend you have two lists
fld_0 = [-99,-99,-98,10]
fld_1 = [-98,-99,-99,5]
and you want to use a function. I didn't like your -99,-98,
ans = [ -98-(a-b) for a,b in zip(fld_0, fld_1)]
returns
>>> ans
[-97, -98, -99, -103] Don't like the -103
this works conceptually like in python script below except for the last case which means you would need to fix the expression like
ans = [( -98 - (a-b)) if (a-b) <= 1 else (a-b) for a,b in zip(fld_0,fld_1)]
or in stacked list comprehension form...
ans = [ ( -98 - (a-b)) # do this
if (a-b) <= 1 # if this
else (a-b) # else this
for a,b in zip(fld_0,fld_1)] # using these
I
will think on the options some more.
a,b = ans: -99,-98=-97
a,b = ans: -99,-99=-99
a,b = ans: -98,-99=-98
a,b = ans: 10,5=5.0
# ---- The field calculator ----
as a code block it would look like this
# code block
def func(a,b):
if (a == -99):
if (b <> -99):
ans = -97
else:
ans = -99
else:
if (b == -99):
ans = -98
else:
ans = float(a) - b
return ans
# expression box
func(( !Fld_0!, !Fld_1!)
as a list comprehension expression you still have to use a code block since the field calculator doesn't support iterable objects etc.
You can also use a generator like in the second example
# code block
def LC_func(a,b):
return [ ( -98 - (a-b)) if ((a-b) <= 1) else (a-b) ][0]
# expression box
LC_func( !Fld_0!, !Fld_1!)
#OR
def LC_func2(a,b):
return ( ( -98 - (a-b)) if ((a-b) <= 1) else (a-b) )
# expression box
LC_func2( !Fld_0!, !Fld_1!)
now the extra [0] is because a list comprehension returns a list, and since you are working with only 2 fields and one output value, you only need to get the first one.
EDIT-----------
Totally untried, since I am on an iThing with Arc*
It has been tried
THE FINE PRINT
in the above example, it is assumed that ... a - b .... does not produce values in the range -1 to 1 inclusive... If this is a possibility, then the reclass values will need to be changed... think about it.
EDIT
updated expression to account for -97, -99 combination
Code block
def LC_func2(a,b):
return ( (a+abs(a-b)) if ((a-b)<=1) else min(a,(a-b)) )
Expression box LC_func2( !Fld_0!, !Fld_1!)
Example now provide for both a conventional and list comprehension and generator expression.