Reputation: 125
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.
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
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()
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()
Upvotes: 16
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