Script to return multiple missing values based on other criteria

3489
4
02-04-2016 03:48 PM
SteveCline
Occasional Contributor

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

0 Kudos
4 Replies
DanPatterson_Retired
MVP Emeritus

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.

DarrenWiens2
MVP Honored Contributor

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.

DanPatterson_Retired
MVP Emeritus

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

LC_demo.png

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!)

DanPatterson_Retired
MVP Emeritus

Example now provide for both a conventional and list comprehension and generator expression.

0 Kudos