Reputation: 4886
For plotting, I am defining colours based on a condition (the conditions are some values in certain columns of a pandas dataframe). Now I am not sure, if I make a mistake when defining the function. The function is as follows:
def getColour(C, threshold):
neg = 0 - threshold
half = threshold/2
if C <= (neg - half):
clr = '#2b83ba'
if ((neg - half) < C <= neg):
clr = '#abdda4'
if ((threshold + half) > C >= threshold):
clr = '#fdae61'
if (C > (threshold + half)):
clr = '#d7191c'
return clr
And this is how I implement it: I iterate through rows of a dataframe, then find columns fulfilling a condition, use the indices from these columns to get parameters from a list, apply another function that generates the results (this function works, the script is tested and worked fine when I set a fixed color for plotting) and then plot the results with different colour.
for index, row in Sparse.iterrows():
lim = row[row.notnull()]
ci = [row.index.get_loc(x) for x in lim.index]
params = np.array(myList)[ci]
for i, w in enumerate(params):
w = w.tolist()
print w, w[2]
print ci[i]
colour = getColour(ci[i], threshold)
x, y = myFunction(w)
plt.plot(x,y, color=colour,linestyle='-',linewidth=1.5)
But this throws an error UnboundLocalError: local variable 'clr' referenced before assignment
on the line colour = getColour(ci[i], threshold)
.
I have read other posts dealing with this error, but I can't see what my problem is.
Upvotes: 0
Views: 2489
Reputation: 9562
Even with an "if ... else" statement, it should fail. I leave the many if
s even though that is bad practice just to show that it is not about adding an else
or not. In a try
statement, an except
will not change it either, not speaking of finally
. What you need is to draw the declaration of a variable before any if
block (or before any try
block or other cascading code blocks).
Means:
def getColour(C, threshold):
neg = 0 - threshold
half = threshold/2
clr = None
if C <= (neg - half):
clr = '#2b83ba'
if ((neg - half) < C <= neg):
clr = '#abdda4'
if ((threshold + half) > C >= threshold):
clr = '#fdae61'
if (C > (threshold + half)):
clr = '#d7191c'
return clr
Another way is to return the variable only if it is in the dictionary that the globals()
function returns.
def getColour(C, threshold):
neg = 0 - threshold
half = threshold/2
if C <= (neg - half):
clr = '#2b83ba'
if ((neg - half) < C <= neg):
clr = '#abdda4'
if ((threshold + half) > C >= threshold):
clr = '#fdae61'
if (C > (threshold + half)):
clr = '#d7191c'
if 'clr' in `globals()`:
return clr
else:
return None
This is not needed since the function will return None by default:
else:
return None
It may make the code better readable with this check against globals()
, though.
Upvotes: 0
Reputation: 350
In general, it is a good idea to consolidate the logic of your condition.
Do your clr
will have all those value ? No so you can use some elif
:
def getColour(C, threshold):
neg = 0 - threshold
half = threshold/2
if C <= (neg - half):
clr = '#2b83ba'
elif ((neg - half) < C <= neg):
clr = '#abdda4'
elif ((threshold + half) > C >= threshold):
clr = '#fdae61'
elif (C > (threshold + half)):
clr = '#d7191c'
return clr
Then do your condition is looped ? Do you have all cases in your if ? If yes, it is a good idea to throw an error in an else
. If no, then that's mean you just forgot one case:
def getColour(C, threshold):
neg = 0 - threshold
half = threshold/2
if C <= (neg - half):
clr = '#2b83ba'
elif ((neg - half) < C <= neg):
clr = '#abdda4'
elif ((threshold + half) > C >= threshold):
clr = '#fdae61'
elif (C > (threshold + half)):
clr = '#d7191c'
else:
raise ValueError('Value expected for clr')
return clr
Edit : To answer to your comment, I think you misunderstand what i meant. In Python, it is better to throw an error if you have something unexpected.
So either:
PEP20: Errors should never pass silently.
Upvotes: 2