onewhaleid
onewhaleid

Reputation: 355

Offset parallel overlapping lines

I am creating a step plot with matplotlib, but some parallel line sections overlap others (hiding those beneath).

import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4, 5]
y1 = [12, 12, 8, 10, 12, 11]
y2 = [11, 11, 8, 9, 11, 11]
y3 = [11, 10, 7, 11, 11, 11]

for y in [y1, y2, y3]:
    plt.step(x, y, lw=3, where='mid')

enter image description here

I would like something more like this: enter image description here

The problem is a bit like drawing a metro map, where some lines run between the same two stations.

Is there a package or algorithm I can use to help me re-align my lines?

This question Suggestions to plot overlapping lines in matplotlib? is related, but none of the solutions work for me.

Upvotes: 0

Views: 257

Answers (1)

JohanC
JohanC

Reputation: 80329

The following approach offsets each line with the line thickness (of 3 dots). The axes limits can be set manually, as the transform doesn't calculate them automatically.

import matplotlib.pyplot as plt
from matplotlib.transforms import offset_copy

x = [0, 1, 2, 3, 4, 5]
y1 = [12, 12, 8, 10, 12, 11]
y2 = [11, 11, 8, 9, 11, 11]
y3 = [11, 10, 7, 11, 11, 11]

fig, ax = plt.subplots()

for i, y in enumerate([y1, y2, y3], start=-1):
    trans_offset = offset_copy(ax.transData, fig=fig, x=3*i, y=3*i, units='dots')
    ax.step(x, y, lw=3, where='mid', transform=trans_offset)

ax.set_xlim(x[0] - .2, x[-1] + .2)
ax.set_ylim(min(min(y) for y in [y1, y2, y3]) - .2, max(max(y) for y in [y1, y2, y3]) + .2)

plt.show()

offsetting lines with the line thickness

Upvotes: 3

Related Questions