Sceeerutinizer
Sceeerutinizer

Reputation: 125

Change matplotlib line style mid-graph

I'm graphing some data (two lines) and I'd like to change the line style for the portions of the lines where the difference between them is statistically significant. So, in the below image (now a link b/c anti-spam policies don't allow me to post an image) I'd like the lines to look different (i.e. dashed perhaps) up until they start converging at about 35 on the x axis.

line plot

Is there a way to do this easily? I have the values for the x axis where the differences are significant, I'm just not clear how to change line styles at certain x-axis locations.

Upvotes: 12

Views: 5905

Answers (2)

Joe Kington
Joe Kington

Reputation: 284880

Edit: I'd had this open and left, so I didn't notice @Ricardo's answer. Because matplotlib will convert things to numpy arrays regardless, there are more efficient ways to do it.

As an example:

Just plot two different lines, one with a dashed linestyle and another with a solid linestyle.

E.g.

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y1 = 2 * x
y2 = 3 * x

xthresh = 4.5
diff = np.abs(y1 - y2)
below = diff < xthresh
above = diff >= xthresh

# Plot lines below threshold as dotted...
plt.plot(x[below], y1[below], 'b--')
plt.plot(x[below], y2[below], 'g--')

# Plot lines above threshold as solid...
plt.plot(x[above], y1[above], 'b-')
plt.plot(x[above], y2[above], 'g-')

plt.show()

enter image description here

For the case where they're cyclic, use masked arrays:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y1 = 2 * np.cos(x)
y2 = 3 * np.sin(x)

xthresh = 2.0
diff = np.abs(y1 - y2)
below = diff < xthresh
above = diff >= xthresh

# Plot lines below threshold as dotted...
plt.plot(np.ma.masked_where(below, x), np.ma.masked_where(below, y1), 'b--')
plt.plot(np.ma.masked_where(below, x), np.ma.masked_where(below, y2), 'g--')

# Plot lines above threshold as solid...
plt.plot(np.ma.masked_where(above, x), np.ma.masked_where(above, y1), 'b-')
plt.plot(np.ma.masked_where(above, x), np.ma.masked_where(above, y2), 'g-')

plt.show()

enter image description here

Upvotes: 16

Ricardo C&#225;rdenes
Ricardo C&#225;rdenes

Reputation: 9172

Let's say that your data is on NumPy arrays dataset1 and dataset2 and you've defined threshold as your significance

def group(data):
    """Assumes that len(data) > 0"""
    prev = 0
    index = 1
    value = data[0]

    while (index < len(data)):
        if data[index] != value:
            yield (value, prev, index)

            value = not value
            prev = index
        index += 1

    yield (value, prev, index)

diff = np.abs(dataset1 - dataset2)
for significant, start, end in group(diff < threshold):
   # Plot data from dataset1[start:end] and dataset2[start:end]
   # Use the value in "significant" (True/False) to figure out
   # The style

Upvotes: 3

Related Questions