Calculate Field with Python 3 / <Null> values

4091
5
Jump to solution
09-04-2019 01:01 PM
JustinWolff
Occasional Contributor

I'm attempting to concatenate several fields, where one of the source fields is a double, the rest are string, and all of them have some <Null> values.  If I use the following syntax in Calculate Field in Pro 24.1/Python 3:

str(!AddrPrimaryHighNo!) + " " + str(!StreetPreDrctnAbbrev!) + " " + str(!StreetName!) + " " + str(!StreetSuffixAbbrev!) + " " + str(!StreetPostDrctnAbbrev!)

I get values like:

1498.0 None AVENUE K NONE NONE

where I would expect:

1498  AVENUE K

AddrPrimaryHighNo is Double

StreetPreDrctnAbbrev is Text

StreetName is Text

StreetSuffixAbbrev is Text

StreetostDrctnAbbrev is Text

If I perform the field calculation below in ArcMap 10.5.1/VB Script, it works out just fine:

[AddrPrimaryHighNo]&" "& [StreetPreDrctnAbbrev]&" "& [StreetName]&" "& [StreetSuffixAbbrev]&" "& [StreetPostDrctnAbbrev]

Meanwhile I'm just going to go back to ArcMap.  Thanks

-Justin

1 Solution

Accepted Solutions
LanceCole
MVP Regular Contributor

https://community.esri.com/migrated-users/3420 ,

You are correct, I should not assume Justin would understand how to place a def in a code block.  I was also using my phone to reply while traveling.  Below are the call, def and a Calculate Field screen shot to use a function called "joinAddress" with the needed address fields which returns the assembled address string less any None values. 

You call the function using:

joinAddress(!AddrPrimaryHighNo!, !StreetPreDrctnAbbrev!, !StreetName!, !StreetSuffixAbbrev!, !StreetPostDrctnAbbrev!)

The Code Block:

def joinAddress(a,b,c,d,e):
    flds = [a,b,c,d,e]
    return " ".join([str(i) for i in flds if i is not None])‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Side note: If all your fields were string you could also use " ".join(filter(None, flds)).  You can still use this by changing the following; flds = [str(a),b,c,d,e].  I prefer the method above as you can also change the str(i) to str(i).strip() to remove any leading or training spaces that may be in your fields.

Calculate Field:

Calculate Field

If you do not want to use the code block with a call, you can use the following as a calculate statement:

" ".join([str(i) for i in [!AddrPrimaryHighNo!, !StreetPreDrctnAbbrev!, !StreetName!, !StreetSuffixAbbrev!, !streetPostDrctnAbbrev!] if i is not None])

View solution in original post

5 Replies
LanceCole
MVP Regular Contributor

Justin,

You can use something like the following as a def in a code block:

flds = [!AddrPrimaryHighNo!, !StreetPreDrctnAbbrev!, !StreetName!, !StreetSuffixAbbrev!, !StreetPostDrctnAbbrev!]

" ".join([str(i) for i in flds if i is not None])‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

JoshuaBixby
MVP Esteemed Contributor

Although I agree with this approach, it won't work within the Field Calculator unless the user creates a code block.  Creating a function in a code block and passing the fields to it isn't difficult, I am just not sure whether that is more than the OP wants to deal with.

LanceCole
MVP Regular Contributor

https://community.esri.com/migrated-users/3420 ,

You are correct, I should not assume Justin would understand how to place a def in a code block.  I was also using my phone to reply while traveling.  Below are the call, def and a Calculate Field screen shot to use a function called "joinAddress" with the needed address fields which returns the assembled address string less any None values. 

You call the function using:

joinAddress(!AddrPrimaryHighNo!, !StreetPreDrctnAbbrev!, !StreetName!, !StreetSuffixAbbrev!, !StreetPostDrctnAbbrev!)

The Code Block:

def joinAddress(a,b,c,d,e):
    flds = [a,b,c,d,e]
    return " ".join([str(i) for i in flds if i is not None])‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Side note: If all your fields were string you could also use " ".join(filter(None, flds)).  You can still use this by changing the following; flds = [str(a),b,c,d,e].  I prefer the method above as you can also change the str(i) to str(i).strip() to remove any leading or training spaces that may be in your fields.

Calculate Field:

Calculate Field

If you do not want to use the code block with a call, you can use the following as a calculate statement:

" ".join([str(i) for i in [!AddrPrimaryHighNo!, !StreetPreDrctnAbbrev!, !StreetName!, !StreetSuffixAbbrev!, !streetPostDrctnAbbrev!] if i is not None])

JoshuaBixby
MVP Esteemed Contributor

Are you really getting values like:

1498.0 None AVENUE K NONE NONE

or is it

1498.0 None AVENUE K None None

0 Kudos
JustinWolff
Occasional Contributor

Josh,

I've since modified my data so the AddrPrimaryHighNo field is now a string, but for the following (when AddrPrimaryHighNo was a double):

AddrPrimaryHighNoStreetPreDrctnAbbrevStreetNameStreetSuffixAbbrevStreetPostDrctnAbbrev
1699<Null>220THST<Null>

When I use:

str(!AddrPrimaryHighNo!) + " " + str(!StreetPreDrctnAbbrev!) + " " + str(!StreetName!) + " " + str(!StreetSuffixAbbrev!) + " " + str(!StreetPostDrctnAbbrev!)

I receive:

1699.0 None 220TH ST None

So I may have not typed out the correct outcome in my original message, sorry about that.

Thank you all for your quick replies and helpful information.  A coworker also pointed out there is a Concatenate Fields under Helpers in the Calculate Field geoprocessing window, which sets up a code block with a def, etc.  

-Justin

0 Kudos