Reputation: 101
I'm kind of stuck here, where it seems that I am missing something. I need to calculate percentages for each class of a legend over a dictionnairy of listed elements. Here is my content:
Legend = {u'Conifer': 1.0, u'Hardwood': 4.0, u'Field': 5.0, u'Urban': 6.0, u'Water': 8.0}
PolyItems = {u'5423': [1.0, 2.0, 1.0, 4.0],
u'425': [6.0, 6.0, 6.0, 6.0, 8.0, 1.0, 6.0, 1.0, 4.0, 4.0, 4.0],
u'9756': [1.0, 1.0, 4.0],
u'6418': [4.0, 8.0, 1.0, 1.0]}
Now, I was trying to make a loop over the Legend variable and use a lambda function to calculate the percentages of each class, but I always get 0.0
for each items.
nb = lambda v, c: float(len([x for x in v if v==c]))
nbtot = lambda v: float(len(v))
for name, cla in Legend.iteritems():
result = {id: nb(vals, cla)/nbtot(vals) * 100
for id, vals in PolyItems.items() if len(id) > 0}
Can I use a lambda function for this? Is there a better way to achieve this?
Upvotes: 0
Views: 169
Reputation: 123473
I think the nb
lambda should be defined as shown:
from operator import itemgetter
Legend = {u'Conifer': 1.0, u'Hardwood': 4.0, u'Field': 5.0, u'Urban': 6.0, u'Water': 8.0}
PolyItems = {u'5423': [1.0, 2.0, 1.0, 4.0],
u'425' : [6.0, 6.0, 6.0, 6.0, 8.0, 1.0, 6.0, 1.0, 4.0, 4.0, 4.0],
u'9756': [1.0, 1.0, 4.0],
u'6418': [4.0, 8.0, 1.0, 1.0]}
nb = lambda v, c: v.count(c)
nbtot = lambda v: float(len(v))
longest_name = max(len(name) for name in Legend)
for name, cla in sorted(Legend.iteritems(), key=itemgetter(1)):
result = {id: nb(vals, cla)/nbtot(vals) * 100
for id, vals in PolyItems.items() if len(id) > 0}
print('{:<{width}}(class {}): {}'.format(name, cla, result, width=longest_name+1))
Output:
Conifer (class 1.0): {u'9756': 66.66666666666666, u'425': 18.181818181818183, u'6418': 50.0, u'5423': 50.0}
Hardwood (class 4.0): {u'9756': 33.33333333333333, u'425': 27.27272727272727, u'6418': 25.0, u'5423': 25.0}
Field (class 5.0): {u'9756': 0.0, u'425': 0.0, u'6418': 0.0, u'5423': 0.0}
Urban (class 6.0): {u'9756': 0.0, u'425': 45.45454545454545, u'6418': 0.0, u'5423': 0.0}
Water (class 8.0): {u'9756': 0.0, u'425': 9.090909090909092, u'6418': 25.0, u'5423': 0.0}
Note: The two lambda functions aren't really necessary since Python has built-ins that perform those operations. This means the code can be simplified somewhat by omitting them—i.e. the following code will produce exactly the same output:
longest_name = max(len(name) for name in Legend)
for name, cla in sorted(Legend.iteritems(), key=itemgetter(1)):
result = {id: vals.count(cla)/float(len(vals)) * 100
for id, vals in PolyItems.items() if len(id) > 0}
print('{:<{width}}(class {}): {}'.format(name, cla, result, width=longest_name+1))
Upvotes: 1
Reputation: 52163
nb = ... if v==c]))
You are comparing a list v
against a float value c
in nb
which always returns False
making the function produce 0.0
for any parameters.
I don't know what that function is for but I think it should be defined as:
nb = lambda v, c: float(len([x for x in v if x==c]))
Upvotes: 1