6

I am using matplotlib.pyplot to plot several curves on the same graph. Sometimes they have equal values, so the last one hides the others, like this:

import matplotlib.pyplot as plt
plt.figure()
plt.plot([1,2,3,4], label="up")
plt.plot([1,2,3,2.5], label="down")
plt.show()

hidden curve

I would like the curves to be slightly shifted so they don't hide one another, like this:

all curves visible

Is there any proper way to do this, without changing the actual values I am plotting?

Update: The best answer so far (for my case) is that of theImportanceOfBeingErnest. However, if I have n curves to plot, instead of just 2, I would have to compute the accumulated offset for each. But given the complex calculations that this answer gets into, I suppose there is no way for matplotlib to do this automatically?

PS: since my values are all multiples of 0.5, the (slight) shifting doesn't risk to create a confusion about the actual value...

Ariane
  • 326
  • 2
  • 11

5 Answers5

5

I suppose the usual way of translating an artist with a size in points is to use matplotlib.transforms.offset_copy. Since the default linewidth of lines is 1.5 points, one would translate the curve by approximately that number.

import matplotlib.pyplot as plt
import matplotlib.transforms as mtrans

fig, ax = plt.subplots()
ax.plot([1,2,3,4], label="up")

tr = mtrans.offset_copy(ax.transData, fig=fig, x=0.0, y=-1.5, units='points')
ax.plot([1,2,3,2.5], label="down", transform=tr)

plt.show()

enter image description here

Note that this works well in case the line is spread and without many up- and downs. A more sophisticated solution (but also largely more complicated) is found in In matplotlib, how can I plot a multi-colored line, like a rainbow

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Concerning the edit: I suppose "compute the offset" really means `i*(-1.5)` which is easy enough? – ImportanceOfBeingErnest Apr 16 '19 at 15:54
  • Yes, that's what I mean and it is easy enough. I was just hoping there would be a kind of parameter or built-in function to automatically prevent the curves from hiding one another, but I suppose that is not the case... – Ariane Apr 17 '19 at 09:54
3

You can use alpha attribute.

import matplotlib.pyplot as plt
plt.figure()
plt.plot([1,2,3,4], label="up")
plt.plot([1,2,3,2.5], label="down", alpha=.3)
plt.legend()
plt.show()

Alter the ratio between [0, 1] in order to get best way you wanted. With this way you don't have to change your values.

In order to improve visibility you can add a "linewidth" attribute with "alpha". e.g.

import matplotlib.pyplot as plt
plt.figure()
plt.plot([1,2,3,4], label="up")
plt.plot([1,2,3,2.5], label="down", linewidth=4, alpha=.5)
plt.legend()
plt.show()

Change the values as you like.

TheDarkKnight
  • 401
  • 1
  • 4
  • 9
1

I would use a transform that moves the points in the second plot downward slightly (you can also apply it to the first plot to move the points upward):

import matplotlib.pyplot as plt
from matplotlib import transforms

fig, ax = plt.subplots()

transform = transforms.Affine2D().translate(0, -0.03) + ax.transData

ax.plot([1, 2, 3, 4], label="up")
ax.plot([1, 2, 3, 2.5], label="down", transform=transform)

enter image description here

gmds
  • 19,325
  • 4
  • 32
  • 58
  • This is more or less the same as [this answer](https://stackoverflow.com/a/55710445/4124317), it just translates everything in data coordinates. The disadvantage of that is that you cannot scale or zoom the plot without needing to readjust the number `-0.03`. – ImportanceOfBeingErnest Apr 16 '19 at 14:32
0

You can simply scale the values

import matplotlib.pyplot as plt
plt.figure()
plt.plot([1,2,3,4], label="up")
plt.plot([x-0.02 for x in [1,2,3,2.5]], label="down")
plt.legend()
plt.show()

output

Sheldore
  • 37,862
  • 7
  • 57
  • 71
CAPSLOCK
  • 6,243
  • 3
  • 33
  • 56
0

Another option would be to use a dashed line with a darker color that overlaps.

import matplotlib.pyplot as plt
plt.figure()
plt.plot([1,2,3,4], color="red", label="up", lw=2)
plt.plot([1,2,3,2.5], color="black", linestyle=":", label="down", lw=2)

enter image description here

Grant Williams
  • 1,469
  • 1
  • 12
  • 24