Problem with drawing multiple lines using matplotlib with Python - python

I am new to python and trying to create a plot with one y variable and two x variables. I want the two lines to show up in the same plot with different labels and colors/makrers. Here is my code to attempt:
y = lambda x: x**(-3)
z = lambda x: x**(-10)
x_grid = np.linspace(1,10, 10)
v_y = []
v_z = []
for i in x_grid:
vy=y(i)
v_y.append(vy)
v_y_array = np.array(v_y)
for j in x_grid:
vz=y(j)
v_z.append(vz)
v_z_array = np.array(v_z)
fig, ax = plt.subplots()
line1, = ax.plot(x_grid, v_y_array, 'b--', label='function 1')
line2, = ax.plot(x_grid, v_z_array, 'r--', label='function 1')
ax.legend()
plt.show()
However, the figure only shows the second line and ignores the first.
But if I try to do the following, it works out fine.
y = lambda x: x**(-3)
z = lambda x: x**(-10)
x_grid = np.linspace(1,10, 10)
v_y = []
v_z = []
for i in x_grid:
vy=y(i)
v_y.append(vy)
v_y_array = np.array(v_y)
for j in x_grid:
vz=y(j)
v_z.append(vz)
v_z_array = np.array(v_z)
fig,ax=plt.subplots()
ax.plot(x_grid,v_y_array,'r--', v_z_array, 'b--', label='x**(-3) function')
ax.set_title('Two Functions')
ax.legend(['x**(-3) function','x**(-10) function'])
plt.show()
I wonder what was the problem with my first set of codes that won't produce the figure that I want?

The reason why the red and blue lines don't overlap in the second plot lies in the official documentation.
ax.plot(x_grid, v_y_array,'r--', v_z_array, 'b--', label='x**(-3) function')
The first set of three arguments x_grid, v_y_array,'r--', v_z_array, follows this pattern:
plot(x, y, 'bo') # plot x and y using blue circle markers
The second set has only two arguments: v_z_array, 'b--', and follow this pattern:
plot(y) # plot y using x as index array 0..N-1
plot(y, 'r+') # ditto, but with red plusses
Thus, the second set is infering a sequence of x values that equals range(0, 10)(values from 0 to 9 inclusive), while the first set of arguments uses x_gridwhich equals range(1, 11) (values from 1 to 10 inclusive).

Related

Subplots within a for-loop

I want to create subplots within a loop, but the outcome is not excactly what I imagined. I want scatter plots in one big plot. The data originates from the matching columns of two dataframes DF and dfr. DFand dfr have the same amount of rows columns and indexes. The first two columns of both dataframes should be excluded.
This is my approach, but I get i plots with one subplot each. What am I missing?
measurements = 9
for i in range(2,measurements+1):
try:
x = DF.iloc[1:,i]
y = dfr.iloc[1:,i]
inds = ~np.logical_or(np.isnan(x), np.isnan(y))
x = x[inds]
y = y[inds]
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
b, m = polyfit(x, y, 1)
fig, ax = plt.subplots(measurements+1,facecolor='w', edgecolor='k')
ax[i].scatter(x, y, c=z, s=50, cmap='jet', edgecolor='', label=None, picker=True, zorder= 2)
ax[i].plot(x, b + m * x, '-')
except KeyError:
continue
plt.show()
Currently I get several plots, but i would like to have one with multipile subplots.
Indeed, you have to put fig, ax = plt.subplots() out of the loop.
A few other things :
Setting edgecolor='' that way might raise an error. Remove it, or add a specific color.
I am sure if using try and except KeyError is relevant in your code. Python raises a KeyError whenever a dict() object is requested (using the format a = adict[key]) and the key is not in the dictionary. Maybe for: x = x[inds] ? if so, I would suggest do this check earlier in your process.
Try this :
measurements = 9
fig, ax = plt.subplots(measurements+1, facecolor='w', edgecolor='k')
for i in range(2, measurements+1):
try:
x = DF.iloc[1:,i]
y = dfr.iloc[1:,i]
inds = ~np.logical_or(np.isnan(x), np.isnan(y))
x = x[inds]
y = y[inds]
xy = np.vstack([x,y])
z = stats.gaussian_kde(xy)(xy)
b, m = np.polyfit(x, y, 1)
ax[i].scatter(x, y, c=z, s=50, cmap='jet', label=None, picker=True, zorder= 2)
ax[i].plot(x, b + m * x, '-')
except KeyError:
# Temporarily pass but ideally, do something
pass
plt.show()

Jupyter | How to use matplotlib to plot multiple lines on only one plot in a for loop and keeping the previous lines?

I am trying to plot 5 lines on a plot in a for-loop. In every iteration, the values of x and y appended to an np.array and then plotted on a figure.
The problem that I have is that I want all the lines on one plot as their x values are always the same but the values of y will change.
Here is how I do it:
for i in range (0,5):
for epoch in range(0, num_epochs):
x = np.append(x,epoch)
y = np.append(y,accuracy)
z = np.append(z, running_loss/j)
fig, axs = plt.subplots(2)
fig.suptitle('Model Evlauation')
axs[0].plot(x, y)
axs[1].plot(x, z)
axs[0].set_xlabel('Number of epochs')
axs[1].set_xlabel('Number of epochs')
axs[0].set_ylabel('Accuracy')
axs[1].set_ylabel('Loss')
fig.tight_layout(pad=2)
plt.show()
in this way, I get 5 different figures and each one includes only one line:
while I want something like the following figure:
When you put the subplots in the for loop, it is set again every time. So instead you want:
fig, axs = plt.subplots(2)
for i in range (0,5):
for epoch in range(0, num_epochs):
x = np.append(x,epoch)
y = np.append(y,accuracy)
z = np.append(z, running_loss/j)
axs[0].plot(x, y)
axs[1].plot(x, z)
fig.suptitle('Model Evlauation')
axs[0].set_xlabel('Number of epochs')
axs[1].set_xlabel('Number of epochs')
axs[0].set_ylabel('Accuracy')
axs[1].set_ylabel('Loss')
fig.tight_layout(pad=2)
plt.show()

How to rotate matplotlib bar-chart?

The following code is used to produce a barchart. I would like to rotate it so that it becomes vertical e.g. the current labels at the x axis go to the y axis ,the current y axis labels to the x axis and the bars rotate accordingly.
I am new to matplotlib and python so any help would be welcomed.
def plot_coefficients(classifier, feature_names, top_features=40):
if classifier.__class__.__name__ == 'SVC':
coef = classifier.coef_
coef2 = coef.toarray().ravel()
coef1 = coef2[:len(feature_names)]
else:
coef2 = classifier.coef_.ravel()
coef1 = coef2[:len(feature_names)]
top_positive_coefficients = np.argsort(coef1)[-top_features:]
top_negative_coefficients = np.argsort(coef1)[:top_features]
top_coefficients = np.hstack([top_negative_coefficients, top_positive_coefficients])
# create plot
plt.figure(figsize=(15, 5))
colors = ['red' if c < 0 else 'blue' for c in coef1[top_coefficients]]
plt.bar(np.arange(2 * top_features), coef1[top_coefficients], color=colors)
feature_names = np.array(feature_names)
plt.xticks(np.arange(1, 1 + 2 * top_features), feature_names[top_coefficients], rotation=90, ha='right')
plt.show()
Update
Expected output:
Look at the matplotlib method barh. You can find example from: https://matplotlib.org/gallery/lines_bars_and_markers/barh.html

Generate random plot for slope

I want to generate a set of random plots like this one: ; where I randomly generate the equation (in this case, y =2x + 3) and then draw an empty plot for students to plot the points for that equation.
I wrote this code, that generates the equation, and tells me what dimensions the plot should be:
start_pos_number = random.randint(1,5)
start_neg_number = start_pos_number * -1
eq_connector = ['+','-']
equation_x_y = random.sample(range(1, 5), 2)
eq = 'y = ' + str(equation_x_y[0]) + 'x' + str(random.choice(eq_connector)) + str(equation_x_y[1])
x = range(start_neg_number,start_pos_number)
pos_y = equation_x_y[0]*start_pos_number + equation_x_y[1]
neg_y = equation_x_y[0]*start_neg_number + equation_x_y[1]
y_range = range(neg_y,pos_y)
print(eq)
print(x)
print(y_range)
I was then trying to plot the data:
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
plt.plot()
plt.show()
Which gives me:
I can see there are multiple issues with this. Can someone tell how to change this code to:
1. Actually draw the line (like in the example) as there is no line drawn in my attempt.
2. make the numbers/limits of the x and y axis match the numbers generated in the first part of the code (or more generally, how do I just put in two random ranges, an x range and a y range, and change the plot accordingly.

How to change the names in matplotlib legend box?

I have file in.txt, which have many rows. and 1-20 columns (it's undefined). and contains numbers.
I draw a graphic with this code
y=np.loadtxt('in.txt')
t=np.arange(len(y))*1
plt.subplot(211)
plt.title(r'in')
plt.grid(1)
plt.plot(t,y, label = 'in')
plt.legend(borderpad = 0.1, labelspacing = 0.1)
plt.show()
It is what I have now (in this example I have 10 columns in file in.txt)
But, rather than all names in legend are "in", I want names like "1", "2", "3" etc. (from 1 to n, where n is a number of columns in my in.txt file)
One way you could do this is by plotting each line in an iteration of a for-loop. For example:
y = np.random.random((3,5)) # create fake data
t = np.arange(len(y))
plt.subplot(211)
plt.title(r'in')
plt.grid(1)
for col_indx in range(y.shape[1]):
plt.plot(t, y[:,col_indx], label = col_indx)
plt.legend(borderpad = 0.1, labelspacing = 0.1)
plt.show()
Alternatively, and I'd recommend this solution in your case, is to use the optional arguments of the call to plt.legend. Like this:
plt.plot(t, y)
plt.legend(range((len(y)))
Check out the doc-string of plt.legend when you want to go a bit more advanced.
If you wanted to start labelling using a 1-based index, rather than zero-based, don't forget to add +1 in the label and the range ;-)
You are taking advantage of the broadcasting in plot for the x/y, but the kwargs do not also get broadcast. Either
x = np.arange(25)
y = np.random.rand(25, 6)
fig, ax = plt.subplots()
for j, _y in enumerate(y.T, start=1):
ax.plot(x, _y, label=str(j))
ax.legend(borderpad=0.1, labelspacing=0.1)
or
fig, ax = plt.subplots()
lns = ax.plot(x, y)
labels = [str(j) for j in range(1, y.shape[1] + 1)]
ax.legend(handles=lns, labels=labels, borderpad=0.1, labelspacing=0.1)

Categories

Resources