escapecharacter
escapecharacter

Reputation: 965

How to automatically color matplotlib graphics using same color as pre-existing label?

I am plotting multiple instances of data that use the same label. There are techniques to remove duplicates from the legend, shown here.

However, I additionally want to prevent different colors being used for the same label.

If I call

import matplotlib.pyplot as plt
plt.plot([1,2,3], [1.0, 3.5, 2.5], label='a')
plt.plot([1,2,3], [1.5, 4.0, 3.0], label='a')
plt.plot([1,2,3], [2.0, 3.0, 3.1], label='b')
plt.plot([1,2,3], [1.5, 2.5, 1.0], label='b')
ax = plt.gca()
handles, labels = ax.get_legend_handles_labels()
unique = [(h, l) for i, (h, l) in enumerate(zip(handles, labels)) if l not in labels[:i]]
ax.legend(*zip(*unique))

I am hoping for a plot like:

enter image description here

However, I get this plot:

enter image description here

Is there a way I can get the former plot without having to explicitly set the colors, like so:

plt.plot([1,2,3], [1.0, 3.5, 2.5], label='a', color='C0')
plt.plot([1,2,3], [1.5, 4.0, 3.0], label='a', color='C0')
plt.plot([1,2,3], [2.0, 3.0, 3.1], label='b', color='C1')
plt.plot([1,2,3], [1.5, 2.5, 1.0], label='b', color='C1')

Upvotes: 1

Views: 216

Answers (1)

Tom
Tom

Reputation: 8800

I think the most straight-forward would be to just remove the labels for all but one of the lines for each label:

plt.plot([1,2,3], [1.0, 3.5, 2.5], label='a', color='C0')
plt.plot([1,2,3], [1.5, 4.0, 3.0], color='C0')
plt.plot([1,2,3], [2.0, 3.0, 3.1], label='b', color='C1')
plt.plot([1,2,3], [1.5, 2.5, 1.0], color='C1')
plt.legend()

enter image description here

You could achieve the same by using an initial underscore for any labels you don't want to show:

plt.plot([1,2,3], [1.0, 3.5, 2.5], label='a', color='C0')
plt.plot([1,2,3], [1.5, 4.0, 3.0], label='_a', color='C0')
plt.plot([1,2,3], [2.0, 3.0, 3.1], label='b', color='C1')
plt.plot([1,2,3], [1.5, 2.5, 1.0], label='_b', color='C1')
plt.legend()

I find this sometimes useful for plotting in a loop (inserting '_' to the start of a label depending on the iteration in the loop, perhaps including a list of colors to set the color for each line - though this would be trivial in your example).

I can't think of a scenario where you actually need matplotlib to "know" that each line is part of the same label. These type of approaches have been fine in my experience.

Upvotes: 1

Related Questions