1

I am using ArcGIS Desktop 10.3.

I have a number of polygons representing exploration licences and a series of attributes including licence name, operator, partners and associated interests (%) within each licence. I am trying to create a stacked label expression that will display in the following order: Licence name, operator and interest, partner(s) name and interest. The way the attribute table is setup is that the percentage interest values are 0 where there is no partner. The dataset is read only and so I can't edit the table to remove the zeros. So far I have the following code:

def FindLabel ([AREABLK] , [Own1] , [Asgnpct1] , [Own2] , [Asgnpct2] , [Own3] , [Asgnpct3] , [Own4] , [Asgnpct4] , [Own5] , [Asgnpct5]):
    if [Own5] is not None:
        return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")" + "\n" + [Own3] + " (" + [Asgnpct3] + "%" + ")" + "\n" + [Own4] + " (" + [Asgnpct4] + "%" + ")" + "\n" + [Own5] + " (" + [Asgnpct5] + "%" + ")"
    elif ([Own4] is not None and [Own5] is None):
        return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")" + "\n" + [Own3] + " (" + [Asgnpct3] + "%" + ")" + "\n" + [Own4] + " (" + [Asgnpct4] + "%" + ")"
    elif ([Own3] is not None and [Own4] is None):
        return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")" + "\n" + [Own3] + " (" + [Asgnpct3] + "%" + ")"
    elif ([Own2] is not None and [Own3] is None):
        return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")"
    elif  [Own2] is None:
        return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")"

This gives the following output:

enter image description here

The first few rows work fine but where the partner isn't present it still shows the 0 value with the (%) text added.

I would therefore like to ignore the 0 values where there is no partner in the expression.

5
  • 4
    Just a note on code readability: You will be doing yourself a favor if you get in the habit of using the .format() function of the string object. Not so many plus symbols. return "{0}\n{1} ({2}%)\n{3} ({4}%)\n{5} ({6}%)\n{7} ({8}%)\n{9} ({10}%)".format([AREABLK], [Own1], [Asgnpct1], [Own2], [Asgnpct2], [Own3], [Asgnpct3], [Own4], [Asgnpct4], [Own5], [Asgnpct5])
    – CStarbird
    Commented Feb 3, 2016 at 19:33
  • Appreciated. That said, it was a label expression for a user so if it works...I'm happy. Scriptwise your notes are valid in this case.
    – Howeitzer
    Commented Feb 3, 2016 at 19:36
  • Howe - I gotta thank you again for asking this question. The answer we worked up makes labeling in these situations so easy and clean.
    – Barrett
    Commented Feb 10, 2016 at 16:19
  • It does indeed. I've encountered it a lot and this makes me much less annoyed :)
    – Howeitzer
    Commented Feb 10, 2016 at 16:22
  • Hey, I edited my answer because when I used it for manhole inverts, it wouldn't print some inverts if they had the same value. With the new answer you don't have to worry about data not showing up.
    – Barrett
    Commented Feb 22, 2016 at 22:16

3 Answers 3

3

The code section at the bottom of this answer is better than using dict. The problem with using dict is that the keys must be unique, and in-some cases (not this particular question) they might not be.


I changed your code somewhat but it produces what you want. It checks for owner to be empty or none, then it checks the same for percent. If they both have values it adds them to the label. You can modify any section of this with an else to replace the empty value with something if needed. Yes intial problem was the way you were checking for the value, but I went down a rabbit hole and wanted to post this.

from collections import OrderedDict
def FindLabel ([AREABLK] , [Own1] , [Asgnpct1] , [Own2] , [Asgnpct2] , [Own3] , [Asgnpct3] , [Own4] , [Asgnpct4] , [Own5] , [Asgnpct5]):
  dict = ([Own1],[Asgnpct1]),([Own2],[Asgnpct2]),([Own3],[Asgnpct3]),([Own4],[Asgnpct4]),([Own5],[Asgnpct5])
  dict = OrderedDict(dict)
  x = [AREABLK]
  for k, v in dict.iteritems():
    if k is not None:
      if k.strip() != "":
       if v is not None:
         if v.strip() !="":
           x = x + "\n" +  k + " (" + v + "%)"
  return x

Updated code to work around using dictionary for key:values and problems associated with it:

def validate(element):
  return element and element.strip()

def FindLabel ([AREABLK] , [Own1] , [Asgnpct1] , [Own2] , [Asgnpct2] , [Own3] , [Asgnpct3] , [Own4] , [Asgnpct4] , [Own5] , [Asgnpct5]):
  fields = [Own1] , [Asgnpct1] , [Own2] , [Asgnpct2] , [Own3] , [Asgnpct3] , [Own4] , [Asgnpct4] , [Own5] , [Asgnpct5]
  area = [AREABLK]
  label = ["{}".format(area)]
  for i in range(len(fields)/2): 
    f1 = fields[i*2]
    f2 = fields[i*2+1]
    if validate(f1) and validate(f2):
      label.append("{} ({}%)".format(f1,f2))
  return '\n'.join(label)
7
  • Super thanks Barrett. I'll check it out tomorrow. It certainly has more elegance!
    – Howeitzer
    Commented Feb 3, 2016 at 19:24
  • 1
    Yeah it does, i can use it in my own work so that was my main interest. It works with the table I tested it on. Again, add an else to any one of the checks to replace the null or zero value with something if you need to. BTW you can shorten your code "%" + ")" to "%)".
    – Barrett
    Commented Feb 3, 2016 at 19:26
  • Also, it probably won't label if [AREABLK] is none or empty, so you might add the same checks unless there is no chance of that happening
    – Barrett
    Commented Feb 3, 2016 at 19:34
  • It's always present so not a problem.
    – Howeitzer
    Commented Feb 3, 2016 at 19:38
  • 1
    hey man i just edited the code. I changed 3 lines: added import, modified the dict = line and then added a new line setting it to ordereddict. Hope this does it for you, it did it with my quick testing
    – Barrett
    Commented Feb 4, 2016 at 16:17
2

Ok so I changed the code somewhat, as inelegant as it is, it works for what I need.

def FindLabel ([AREABLK] , [Own1] , [Asgnpct1] , [Own2] , [Asgnpct2] , [Own3] , [Asgnpct3] , [Own4] , [Asgnpct4] , [Own5] , [Asgnpct5]):
if [Own4] != " " and [Asgnpct5] == '0':
    return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")" + "\n" + [Own3] + " (" + [Asgnpct3] + "%" + ")" + "\n" + [Own4] + " (" + [Asgnpct4] + "%" + ")"
elif [Own3] != " " and [Asgnpct4] == '0':
    return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")" + "\n" + [Own3] + " (" + [Asgnpct3] + "%" + ")"
elif [Own2] != " " and [Asgnpct3] == '0':
    return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")"
elif [Own1] != " " and [Asgnpct2] == '0':
    return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")"
else:
    return [AREABLK] + "\n" + [Own1] + " (" + [Asgnpct1] + "%" + ")" + "\n" + [Own2] + " (" + [Asgnpct2] + "%" + ")" + "\n" + [Own3] + " (" + [Asgnpct3] + "%" + ")" + "\n" + [Own4] + " (" + [Asgnpct4] + "%" + ")" + "\n" + [Own5] + " (" + [Asgnpct5] + "%" + ")"

enter image description here

2

You never get past the first if statement because you are comparing and empty list to None which will always result in True because it exists - even though it is empty.

An example:

own1 = "own1"
[own1] is not None
> True

own2 = None
[own2] is not None
> True

The second statement is also true because you are using the brackets around own2 that create an empty list.

[] is not None
> True

What you should do instead is test the variables for their existance:

own1 = "own1"
own1 is not None
> True

own2 = None
own2 is not None
> False

edit:

As pointed out by @Howeitzer and @recurvata the brackets are not designating lists as any sane Python user would expect. This answer is therefore mute since I expected ESRI wouldn't dare change something so fundamental to Python as the behaviour of lists!

4
  • Thanks Kersten although I'm not sure I quite follow you.
    – Howeitzer
    Commented Feb 3, 2016 at 15:50
  • 2
    Where is a list? The brackets in this case are just the field designators. Why the label engine uses [] for python rather than !! I don't know.
    – recurvata
    Commented Feb 3, 2016 at 16:28
  • @recurvata I just rechecked in ArcPy. You're absolutely right. My answer would be valid for any Python distribution except ArcPy. It is beyond me why they would change such a fundamental part of Python.
    – Kersten
    Commented Feb 3, 2016 at 16:52
  • I think it's what the label engine uses for Python, not ArcPy, but I don't know how ESRI implements it. Agree that this is confusing at best.
    – recurvata
    Commented Feb 3, 2016 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.