简体   繁体   中英

How can I ask matplotlib to slightly shift overlapping curves so they don't hide one another?

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()

隐藏曲线

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

所有曲线可见

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...

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()

在此处输入图片说明

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

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". eg

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.

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)

在此处输入图片说明

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()

产量

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)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM