Ian Gilman
Ian Gilman

Reputation: 107

Remove line through points in matplotlib plot

I have the following matplotlib snippet:

fig, ax = plt.subplots(figsize=(6,6))
values = np.random.normal(loc=0, scale=1, size=10)
ax.plot(range(10), values, 'r^', markersize=15, alpha=0.4);

which produces

enter image description here

as planned.

I'd like to make the line invisible where it overlaps with the points so that the points look more joined by the line rather than lying on top of the line. It is possible to do this by either making the line invisible where they overlap or to create a new line object that simply links the points rather than traces them?

To be explicit, I do not want the entire line removed, just the sections that overlap with the points.

Upvotes: 1

Views: 3010

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339230

It is in general hard to let the lines stop at the edges of the markers. The reason is that lines are defined in data coordinates, while the markers are defined in points.

A workaround would be to hide the lines where the markers are. We may think of a three layer system. The lowest layer (zorder=1) contains the lines, just as they are. The layer above contains markers of the same shape and size as those which are to be shown. Yet they would be colored in the same color as the background (usually white). The topmost layer contains the markers as desired.

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(42)

fig, ax = plt.subplots(figsize=(6,5))

def plot_hidden_lines(x,y, ax = None, ms=15, color="r", 
                      marker="^", alpha=0.4,**kwargs):
    if not ax: ax=plt.gca()
    ax.scatter(x,y, c=color, s=ms**2, marker=marker, alpha=alpha, zorder=3)
    ax.scatter(x,y, c="w", s=ms**2, marker=marker, alpha=1, zorder=2)
    ax.plot(x,y, color=color, zorder=1,alpha=alpha,**kwargs)


values1 = np.random.normal(loc=0, scale=1, size=10)
values2 = np.random.normal(loc=0, scale=1, size=10)
x = np.arange(len(values1))

plot_hidden_lines(x,values1)
plot_hidden_lines(x,values2, color="indigo", ms=20, marker="s")

plt.show()

enter image description here

Upvotes: 2

Nathan
Nathan

Reputation: 3648

I think the best way to go about it is to overlay the triangles over the lines:

import matplotlib.pyplot as plt
import numpy as np

values = np.random.normal(loc=0, scale=1, size=10)
plt.plot( range(10), values, marker='^', markerfacecolor='red', markersize=15, color='red', linewidth=2)
plt.show()

The program outputs: output of program

If you really want the see through aspect, I suggest you somehow calculate where the lines overlap with the markers and only draw the lines inbetween:

import numpy as np
import matplotlib.pyplot as plt
values = np.random.normal(loc= 0, scale=1, size=10)
for i in range(9):
     start_coordinate, end_coordinate = some_function(values[i], values[i+1])
     plt.plot([i, i+1], [start_coordinate, end_coordinate], *whatever_other_arguments)
plt.scatter(range(10), values, *whatever_other_arguments)
plt.show()

The hard part here is of course calculating these coordinates (if you want to zoom in this won't work), but honestly, given the difficulty of this question, I think you won't find anything much better...

Upvotes: 0

Related Questions