matplotlib with multiple scales showing only one plot - python

I'm using the function below to plot three lines with two different scales.
def plot2(x1, y1, x2, y2, x3, y3):
fig, ax1 = plt.subplots()
ax1.plot(x1, y1, 'b')
ax1.plot(x2, y2, 'g')
ax2 = ax1.twinx()
ax2.plot(x3, y3, 'r')
fig.tight_layout()
plt.show()
However, ax2 is shadowing ax1 in the plot.

I can't reproduce the problem. By extending the code to a minimal running example:
import matplotlib.pyplot as plt
def plot2(x1, y1, x2, y2, x3, y3):
fig, ax1 = plt.subplots()
ax1.plot(x1, y1, 'b')
ax1.plot(x2, y2, 'g')
ax2 = ax1.twinx()
ax2.plot(x3, y3, 'r')
fig.tight_layout()
plt.show()
x1 = [1,2,3,4,5]
x2 = [1.25,2.25,3.25,4.25,5.25]
x3 = [1.5, 2.5, 3.5, 4.5, 5.5]
y1 = [1,2,3,4,5]
y2 = [6,7,8,9,10]
y3 = [11,12,13,14,15]
plot2(x1,y1,x2,y2,x3,y3)
I get the following result:
png

Related

How to make dotted and bold lines in the same plot

I have a list and i want to plot the list in such a way that for certain range of x axis the lines are dotted while for other range it is solid.
e.g.:
y=[11,22,33,44,55,66,77,88,99,100]
x=[1,2,3,4,5,6,7,8,9,10]
i did this:
if i range(4,8):
plt.plot(x,y,marker='D')
else :
plt.plot(x,y,'--')
plt.show()
but this doesnot work.
can someone help?
Slice the data into 3 intervals
import matplotlib.pyplot as plt
import numpy as np
# Data for plotting
x = [1,2,3,4,5,6,7,8,9,10]
y = [11,22,33,44,55,66,77,88,99,100]
fig, ax = plt.subplots()
m, n = 4, 8
x1, x2, x3 = x[:m+1], x[m:n+1], x[n:]
y1, y2, y3 = y[:m+1], y[m:n+1], y[n:]
ax.plot(x1, y1, color='red', linestyle='solid', marker='D')
ax.plot(x2, y2, color='blue', linestyle='dashed')
ax.plot(x3, y3, color='red', linestyle='solid', marker='D')
plt.show()
Here is a solution with the same colours for the whole line:
import matplotlib.pyplot as plt
x = [1,2,3,4,5,6,7,8,9,10]
y = [11,22,33,44,55,66,77,88,99,100]
fig, ax = plt.subplots()
x1, y1 = x[:4], y[:4]
x2, y2 = x[3:8], y[3:8]
x3, y3 = x[7:], y[7:]
ax.plot(x1, y1, marker='D', color='b')
ax.plot(x2, y2, '--', color='b')
ax.plot(x3, y3, marker='D', color='b')
Change line characteristics based on the value of x:
import numpy as np
from matplotlib import pyplot as plt
Make arrays of the lists;
y = np.array([11,22,33,44,55,66,77,88,99,100])
x = np.array([1,2,3,4,5,6,7,8,9,10])
make a boolean array based on your condition(s);
dashed = np.logical_or(x<4,x>=8)
use the boolean array to filter the data when you plot.
plt.plot(x[~dashed],y[~dashed],color='blue',marker='D')
plt.plot(x[dashed],y[dashed],color='blue',ls='--')

Making the lines of the scatter plot smooth in MatPlotlib

I want to make the lines of the following graph smooth. I tried to search and it seems that we have to represent the x-axis in terms of a float or some type such as date time. Here since the x-axis are just labels, I could not figure out how I should change my code. Any help is appreciated.
import matplotlib.pyplot as plt
x1 = [">1", ">10",">20"]
y1 = [18,8,3]
y2 = [22,15,10]
y3=[32,17,11]
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.scatter(x1, y1, color='blue', label='Heuristic')
ax1.scatter(x1, y2, color='green', label='SAFE')
ax1.scatter(x1, y3, color='red', label='discovRE')
plt.plot(x1, y2, '.g:')
plt.plot(x1, y1, '.b:')
plt.plot(x1, y3, '.r:')
plt.ylabel('False Positives',fontsize=8)
plt.xlabel('Function instruction sizes',fontsize=8)
plt.legend()
plt.show()
Following is the graph that I get right now.
Maybe you can fit a curve to 'smooth' the curve
import matplotlib.pyplot as plt
x1 = [">1", ">10",">20"]
y1 = [18,8,3]
y2 = [22,15,10]
y3=[32,17,11]
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.scatter(x1, y1, color='blue', label='Heuristic')
ax1.scatter(x1, y2, color='green', label='SAFE')
ax1.scatter(x1, y3, color='red', label='discovRE')
buff_x = np.linspace(0,2,100)
def reg_func(y):
params = np.polyfit(range(len(y)),y,2)
return np.polyval(params,buff_x)
plt.plot(buff_x, reg_func(y2), 'g',linestyle='dotted')
plt.plot(buff_x, reg_func(y1), 'b',linestyle='dotted')
plt.plot(buff_x, reg_func(y3), 'r',linestyle='dotted')
plt.ylabel('False Positives',fontsize=8)
plt.xlabel('Function instruction sizes',fontsize=8)
plt.legend()
plt.show()
as you can see, I use a function reg_func to fit your data, and plot the predicted curves

make matplotlib fill_between overwrite the subplot in front

I am trying to plot several lines which partially overlap and occlude each other. This is what I tried:
# Create the figure
fig = plt.figure(figsize=(7, 4))
ax = plt.subplot(111)
# remove grid
ax.set_xticks([])
ax.set_yticks([])
# define data
X = np.linspace(-2*np.pi, 2*np.pi, 400)
Y1 = np.cos(2*X)
Y2 = X**2/10-0.5
ax.plot(X, Y1, lw=1)
ax.fill_between(X, Y1, -1, facecolor=(1,0,0,1))
ax.plot(X, Y2)
ax.fill_between(X, Y2, -1, facecolor=(1,1,1,1))
plt.show()
which produces
but when the second fill_between goes down to -1, I would like it to also occlude the blue graph. Like so:
Any suggestions are appreciated.
My solution:
# Create the figure
fig = plt.figure(figsize=(7, 4))
ax = plt.subplot(111)
# remove grid
ax.set_xticks([])
ax.set_yticks([])
# define data
X = np.linspace(-2*np.pi, 2*np.pi, 400)
Y1 = np.cos(2*X)
Y2 = X**2/10-0.5
# NEW #########################
for i in range(Y1.size):
if Y1[i] < Y2[i] :
Y1[i] = Y2[i]
###############################
ax.plot(X, Y1, lw=1, color="blue")
ax.fill_between(X, Y1, -1, facecolor=(1,0,0,1))
ax.plot(X, Y2, color="orange")
ax.fill_between(X, Y2, -1, facecolor=(1,1,1,1))
plt.show()
Output:
Basically at any point Y1 is less than Y2 we set the point on Y1 equal to Y2.
I ended up going with #JohanC's suggestion, as it makes it easier to generalize to more graphs. So for example
ax.plot(X, Y1, lw=1)
ax.fill_between(X, Y1, -1, facecolor=(1,0,0,1), zorder=2)
ax.plot(X, Y2)
ax.fill_between(X, Y2, -1, facecolor=(1,1,1,1), zorder=3)
ax.plot(X, Y3, lw=1, zorder=1)
ax.fill_between(X, Y3, -1, facecolor=(0,0,1,1), zorder=1)
ax.plot(X, Y4, lw=1, zorder=0)
ax.fill_between(X, Y4, -1, facecolor=(0,1,0,0.5), zorder=0)
Can plot something like this:

Why there is a extra graph in a subplot which i did not mention anywhere

I have used the following code and in the last the figure of thee subplot why I am having an extra plot(red curve)
fig= plt.figure()
plt.rcParams.update({'font.size':24})
fig, (ax1,ax2,ax3)=plt.subplots(3,1,figsize=
(20,24),sharex='row',sharey='col')
p1=plt.plot(x_axis,Clean_Current_TEST,"g",x_axis,Clean_Current_Prediction1,"r--")
ax1.plot(x_axis,Clean_Current_TEST,"g",x_axis,Clean_Current_Prediction1,"r--", lw=3.0)
ax2.plot(x_axis,Clean_Current_TEST,"g",x_axis,Clean_Current_Prediction2,"r--", lw=3.0)
ax3.plot(x_axis,Clean_Current_TEST,"g",x_axis,Clean_Current_Prediction3,"b--", lw=3.0)#,x_axis,Clean_Current_Prediction3,"b--"
ax1.legend(p1[:2], ["Experimental Output","Predicted Output1"],loc='best');
ax2.legend(p1[:2], ["Experimental Output","Predicted Output2"],loc='best');
ax3.legend(p1[:2], ["Experimental Output","Predicted Output3"],loc='best');
ax1.title.set_text('Short Circuit Current of Clean Module vs
Time Graph')
fig.text(0.5, 0.01, 'Time(hr)', ha='left', va='center')
fig.text(0.01, 0.5, 'Clean Module Current(mA)', ha='center',
va='center', rotation='vertical')
[enter image description here][1]
plt.show()
plt.tight_layout(pad=1)
(The last figure of the subplot)
Here is a minimum, reproducible example that recreates the problem you are experiencing:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1,1,20)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.arctan(x)
fig, (ax1,ax2) = plt.subplots(2,1)
plt.plot(x, y3, "g", x, y1, "r--")
ax1.plot(x, y3, "g", x, y1, "r--", lw=3.0)
ax2.plot(x, y3, "g", x, y2, "b--", lw=3.0)
plt.show()
It seems that the plt.plot function actually plots its graph on the last axis. This is why you are seeing the "red" graph on the last axis, even though the line that plots on axis 2 explicitly calls for a "blue" line. In general, if you are plotting separate things on various axes, then you should not use the convenience methods in matplotlib.pyplot, and should instead use the methods on the Axis objects.
fig, (ax1,ax2) = plt.subplots(2,1)
ax1.plot(x, y3, 'g', x, y1, "r--", lw=3.0)
ax2.plot(x, y3, 'g', x, y2, "b--", lw=3.0)
plt.show()

Controlling the tracker when using twinx

The tracker in the lower-right corner (highlighted in red) reports y-values relative to the y-axis on the right.
How can I get the tracker to report y-values relative to the y-axis on the left instead?
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(6)
numdata = 100
t = np.linspace(0.05, 0.11, numdata)
y1 = np.cumsum(np.random.random(numdata) - 0.5) * 40000
y2 = np.cumsum(np.random.random(numdata) - 0.5) * 0.002
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.plot(t, y1, 'r-', label='y1')
ax2.plot(t, y2, 'g-', label='y2')
ax1.legend()
plt.show()
I know swapping y1 with y2 will make the tracker report y1-values,
but this also places the y1 tickmarks on the right-hand side, which is not what I want to happen.
ax1.plot(t, y2, 'g-', label='y2')
ax2.plot(t, y1, 'r-', label='y1')
Ah, found it: ax.yaxis.set_ticks_position("right").
Instead of trying to "control the tracker", you can swap the location of the y-axes.
ax1.yaxis.set_ticks_position("right")
ax2.yaxis.set_ticks_position("left")
ax1.plot(t, y2, 'g-', label='y1')
ax2.plot(t, y1, 'r-', label='y2')
AFAIK, the tracker always follows ax2 when using twinx.
Please note that if you create an ax3= ax1.twiny() axes after ax1 and ax2, the tracker goes to ax3 and you have again it reporting y1 values.
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(6)
numdata = 100
t = np.linspace(0.05, 0.11, numdata)
y1 = np.cumsum(np.random.random(numdata) - 0.5) * 40000
y2 = np.cumsum(np.random.random(numdata) - 0.5) * 0.002
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.plot(t, y1, 'r-', label='y1')
ax2.plot(t, y2, 'g-', label='y2')
ax1.legend()
ax3 = ax1.twiny()
ax3.set_xticks([])
plt.show()

Categories