DudeWah
DudeWah

Reputation: 361

Changing line color in matplotlib based on logic

I can't seem to figure out how to change linecolor in matplotlib based on some simple logic.

For instance,let's say I have:

import numpy as np
from matplotlib import pyplot as plt

A = [1,2,3,4,5]
B = [2,4,6,8,10]
C = [1,3,5,6,7]
D = [1,2,3,3,3]
combined = [A,B,C,D]

Now, let's say I want matplotlib to plot this as a line graph. Thus, there should be 4 separate lines based on each list in combined.

I want to add the condition if a number in list (of combined) is greater than 5 then the individual line be blue. Else, let the individual line be orange.

How do I go about doing something like this? I know the following would plot it just fine.

np_combined = np.array(combined)
times = np.linspace(0,1,5)
plt.plot(times,np_combined.T)

Would I need a double for loop? I tried more than a few, but seem to end up getting an error each time.

for h in np_combined:
    for k in range(5):
        if k > 5:
            plt.plot(times,k,color = 'blue')
        else:
            plt.plot(times,k,color = 'orange')

Error is EOL while scanning string literal

Upvotes: 0

Views: 2047

Answers (2)

Jonathan Eunice
Jonathan Eunice

Reputation: 22433

rassar's answer, using a conditional to choose the color (or drawing style) is correct. For simple cases, it's perfectly fine.

For more complex cases, and just to set yourself up for them, there is another option: a decision function. You see these commonly in d3js, Bokeh, and visualization apps.

For a simple case, it's something like:

color_choice = lambda x: 'blue' if x > 5 else 'orange'

for sublist in np_combined:
    plt.plot(times, sublist, color=color_choice(max(sublist)))

Here color_choice could also be a traditional function definition. Using a lambda function is just because it's a short one-liner.

For simple cases, defining a selection function may not be much better than a conditional. But say you also wanted to define a line style, and not use the same conditions as the color choice. E.g.:

for sublist in np_combined:
    largest = max(sublist)
    if largest > 5:
        if largest > 10:
            plt.plot(times, sublist, color='blue', ls='--')
        else:
            plt.plot(times, sublist, color='blue', ls='-')
    else:
        if largest <= 2:
            plt.plot(times, sublist, color='orange', ls='.')
        else:
            plt.plot(times, sublist, color='orange', ls='-')

Now you're in a confusing pickle, because you have so much code for just relatively simple color and line choices. It's repetitive, violating the DRY principle of software engineering, inviting errors.

Decision functions can clean that up greatly:

color_choice = lambda x: 'blue' if x > 5 else 'orange'

def line_choice(x):
    if x > 10: return '--'
    if x > 2:  return '-'
    return '.'

for sublist in np_combined:
    largest = max(sublist)
    plt.plot(times, sublist, 
             color=color_choice(largest)),
             ls=line_choice(largest))

Not only does this clean up the code, localizing the decision logic, it makes it easier to change your color, style, and other choices as your program evolves. The only fly in this ointment is that Python lacks, AFIAK, D3's excellent selection of mapping functions, aka "scales".

Upvotes: 2

rassar
rassar

Reputation: 5660

Based on your attempt, try:

for sublist in np_combined:
    if max(sublist) > 5:
        plt.plot(times,sublist,color = 'blue')
    else:
        plt.plot(times,sublist,color = 'orange')

Also, since your error is that you are missing a end quote (that's what EOL means), the error is probably in another line.

Upvotes: 1

Related Questions