Why is the grid turned on only on the last subplot? - python-3.x

I am using subplots in a function which is using a slider widget inputs to calculate some stuff and plotting results.
I want to turn on the grid for all subplots of ax1. But somehow jupternotebooks only turns it on only on the last plot...
import numpy as np
from matplotlib import pyplot as plt
import ipywidgets as widgets
from IPython.html.widgets import interact
%matplotlib inline
## Plot
fig, ax1 = plt.subplots(6,2)
plt.subplots_adjust(right = 2, top = 8 )
# Show the major grid lines with dark grey lines
plt.grid(b=True, which='major', color='#666666', linestyle='-')
# Show the minor grid lines with very faint and almost transparent grey lines
plt.minorticks_on()
plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2)
## Giergeschwindigkeit über v und ay
ax1[0,0].plot(v_ms, omega)
ax1[0,0].set_ylabel('Giergeschwindigkeit [rad/s]')
ax1[0,0].set_xlabel('Geschwindigkeit [m/s]')
ax1[0,0].set_title('Giergeschwindigkeit über Geschwindigkeit')
# ... more subplots
plt.show()
It looks like this:
And can you explain to me why in my case
ax1.grid()
throws an error?
AttributeError: 'numpy.ndarray' object has no attribute 'grid'

This is because plt will only operate on the last-created axes object.
And the reason you're getting that error is that ax1 is a numpy n-dimensional array, not an axes object.
You can do this to iterate over the numpy n-dimensional array to create the grids:
for row in axes:
for ax in row:
ax.grid(b=True, which='major', color='#666666', linestyle='-')
ax.minorticks_on()
ax.grid(b=True, which='minor', color='#999999', linestyle='-',alpha=0.2)
Result (without plt.subplots_adjust()):

You can set grid for every ax object, so in your case you should set like this:
ax1[0,0].grid()
ax1[0,1].grid()

Related

Set specified grid lines in matplotlib without changing ticklabels

I try to plot a bar graph with a pre-defined number of grid lines like below. However, once I plot it, some yticklabels (A_2,A_3,etc) have not shown (only A_1, A_5, A_9,A_13,A_17 shown). I want to keep all ytick labels, but the gridline should be the same as x axis. Do you have any ideas to fix it?
import matplotlib.pyplot as plt
import numpy as np
mdict={"Column1":["A_"+str(i) for i in range(1,21)],"Value":[i for i in range(1,21)]}
# Create a dataframe
df=pd.DataFrame(mdict)
# Set plot params
fig, ax = plt.subplots(figsize=(12,8))
ax.barh(df.Column1,df.Value, color="darkgray",edgecolor="black", linewidth=0.5)
ax.set_xlabel("Numbers", fontsize=15)
# ax.set_yticklabels(list(df_cor.Country.values.tolist()), fontsize=15)
major_ticks_top=np.linspace(0,20,6)
minor_ticks_top=np.linspace(0,20,6)
ax.set_xticks(major_ticks_top)
ax.set_yticks(minor_ticks_top)
ax.grid(alpha=0.2,color="black")
plt.show()
I wouldn't explicitly set the ticks and labels but modify the output matplotlib generates:
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.ticker import MultipleLocator
mdict={"Column1":["A_"+str(i) for i in range(1,21)],"Value":[i for i in range(1,21)]}
df=pd.DataFrame(mdict)
fig, ax = plt.subplots(figsize=(12,8))
ax.barh(df.Column1, df.Value, color="darkgray", edgecolor="black", linewidth=0.5)
ax.set_xlabel("Numbers", fontsize=15)
#set every fourth tick
n=4
ax.xaxis.set_major_locator(MultipleLocator(n))
ax.grid(alpha=0.2,color="black")
#remove unwanted gridlines on the y-axis
ygrd_lines = ax.get_ygridlines()
[grd_line.set_visible(False) for i, grd_line in enumerate(ygrd_lines) if i%n]
plt.show()
Sample output:
Methods used:
MultipleLocator() setting ticks at defined intervals
.get_ygridlines returning gridlines as a list of Line2D objects for further modification

Bar missing while plotting using Matplotlib's Twinx

I'm using matplotlib.axes.Axes.twinx to have a shared x-axis in matplotlib for both . I dont know why instead of 13 bars to be plotted, only 12 of them are getting plotted.
Link of Data set
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
dataFrame=pd.read_csv("NEM.csv",sep=',')
dataFrame['ratio']=dataFrame['Expert']/dataFrame['Novice']
fig, ax1 = plt.subplots(figsize=(9, 6))
ax1.set_title('N-E Analysis')
xticklabels=dataFrame['Task'].tolist()
ax1.plot('Novice', data=dataFrame, marker='', color='dodgerblue', linewidth=2,label='Novice',zorder=100)
ax1.plot('Expert', data=dataFrame, marker='', color='darkorange', linewidth=2,label='Expert',zorder=200)
plt.ylim(0,120)
ax2 = ax1.twinx()
ax2.bar('Task','ratio', data=dataFrame, color='gray',width=0.35,label='NE',zorder=0)
ax1.spines['top'].set_visible(False)
ax1.spines['right'].set_visible(False)
ax1.spines['left'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax2.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax1.set_xticklabels(xticklabels, rotation = 45, ha="right")
ax1.yaxis.grid()
ax1.tick_params(left='off',bottom='off')
ax2.tick_params(right='off')
plt.ylim(0,12)
h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
p=ax1.legend(h2+h1, l2+l1, loc=2,frameon=False)
fig.tight_layout()
plt.show()
When using plots, it could be good practice to say explicitily how many bars or points you are going to plot. For instance, you can create an x-axis this way:
x_axis = np.arange(len(dataFrame[Task].tolist())
then:
ax1.plot(x_axis, dataFrame['Novice'].tolist(), ...)
after that you rename the xticklabels like this:
ax1.set_xticks(x_axis)
ax1.set_xticklabels(dataFrame[Task].tolist())
Do the same with the bar graph:
ax2.bar(x_axis, dataFrame['Ratio'].tolist(), ...)
This should do the trick.
Hope it helps.

How to remove or include errorbar plot from matplotlib axes?

This code shows an Attribute error:
I am plotting errorbar plot for let's say 10 different datasets (huge datasets) from a file containing multiple datasets (let's say for different days), and I am showing the user an option (Checkbox) to remove or include a plot of the particular dataset (through GUI).
So for this, I just want to erase the current axes and at a later time want to redraw it again.
How can I do this?
Below is a simplified example to show what I need.
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1)
x, y, yerr = np.random.rand(3,10)
l = ax.errorbar(x, y, yerr, marker='s', mfc='red', mec='green', ms=20, mew=4)
canvas = fig.canvas
canvas.draw()
bkg = canvas.copy_from_bbox(ax.bbox)
plt.show()
plt.pause(1)
ax.clear()
canvas.restore_region(bkg)
ax.draw_artist(l)
# here it throws an AttributeError: 'ErrorbarContainer'
#object has no attribute 'draw'

matplotlib.pyplot: create a subplot of stored plots

python 3.6 om mac
matplotlib 2.1.0
using matplotlib.pyplot (as plt)
Let's say i have a few plt.figures() that i appended into a list called figures as objects. When in command line i do: figures[0]it produces the plot for the index 0 of the list figures.
However, how can i arrange to have all the plots in figures to be in a subplot.
# Pseudo code:
plt.figure()
for i, fig in enumerate(figures): # figures contains the plots
plt.subplot(2, 2, i+1)
fig # location i+1 of the subplot is filled with the fig plot element
So as a result, i would a 2 by 2 grid that contains each plot found in figures.
hoping this makes sense.
A figure is a figure. You cannot have a figure inside a figure. The usual approach is to create a figure, create one or several subplots, plot something in the subplots.
In case it may happen that you want to plot something in different axes or figures, it might make sense to wrap the plotting in a function which takes the axes as argument.
You could then use this function to plot to an axes of a new figure or to plot to an axes of a figure with many subplots.
import numpy as np
import matplotlib.pyplot as plt
def myplot(ax, data_x, data_y, color="C0"):
ax.plot(data_x, data_y, color=color)
ax.legend()
x = np.linspace(0,10)
y = np.cumsum(np.random.randn(len(x),4), axis=0)
#create 4 figures
for i in range(4):
fig, ax = plt.subplots()
myplot(ax, x, y[:,i], color="C{}".format(i))
# create another figure with each plot as subplot
fig, ax = plt.subplots(2,2)
for i in range(4):
myplot(ax.flatten()[i], x, y[:,i], color="C{}".format(i))
plt.show()

Unable to plot 4 histograms of iris dataset features using matplotlib

using the iris dataset
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
from sklearn import datasets
iris= datasets.load_iris()
x_index = 3
colors = ['blue', 'red', 'green']
for label, color in zip(range(len(iris.target_names)), colors):
plt.hist(iris.data[iris.target==label, x_index],
label=iris.target_names[label],
color=color)
plt.xlabel(iris.feature_names[x_index])
plt.legend(loc='upper right')
plt.show()
enter image description here
This code is plotting only one histogram with sepal length (image attached) as the x-axis.
To plot other features of iris dataset in a similar manner, I have to change the x_index to 1,2 and 3 (manually) and run this bit of code again.
To plot all four histograms simultaneously, I tried the following code:
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
from sklearn import datasets
iris= datasets.load_iris()
fig, axes = plt.subplots(nrows= 2, ncols=2)
colors= ['blue', 'red', 'green', 'black']
x_index= 0
for ax in axes.flat:
for label, color in zip(range(len(iris.target_names)), colors):
ax= plt.hist(iris.data[iris.target==label, x_index], label=
iris.target_names[label], color=color)
plt.xlabel(iris.feature_names[x_index])
plt.legend(loc='upper right')
x_index+=1
plt.show()
This code gives me the following error:
IndexError: index 4 is out of bounds for axis 1 with size 4
Any advice?
Two issues:
ax is the name of the current axes in the loop. You should not redefine but instead use it as this is the axes you want to plot to. Replace ax = plt.hist by ax.hist.
x_index+=1 needs to be in the outer loop, not in the inner loop. Otherwise it will increment up to 11 instead of 3. Better get rid of it entirely and use a normal loop variable.
Complete code:
import matplotlib.pyplot as plt
from sklearn import datasets
iris= datasets.load_iris()
fig, axes = plt.subplots(nrows= 2, ncols=2)
colors= ['blue', 'red', 'green']
for i, ax in enumerate(axes.flat):
for label, color in zip(range(len(iris.target_names)), colors):
ax.hist(iris.data[iris.target==label, i], label=
iris.target_names[label], color=color)
ax.set_xlabel(iris.feature_names[i])
ax.legend(loc='upper right')
plt.show()

Resources