In trying to do some small multiple stuff, I want to make a bunch of subplots with Matplotlib and toss in varying data to each. pyplot.subplots() gives me a Figure and Numpy array of Axes, but in trying to iterate over the axes, I am stumped on how to actually get at them.
I'm trying something akin to:
import numpy as np
import matplotlib.pyplot as plt
f, axs = plt.subplots(2,2)
for ax in np.nditer(axs, flags=['refs_ok']):
ax.plot([1,2],[3,4])
However, the type of ax in each iteration is not an Axes, but rather an ndarray, so attempting to plot fails with:
AttributeError: 'numpy.ndarray' object has no attribute 'plot'
How can I loop over my axes?
You can do this more simply:
for ax in axs.ravel():
ax.plot(...)
Numpy arrays have a .flat attribute that returns a 1-D iterator:
for ax in axs.flat:
ax.plot(...)
Another option is reshaping the array to a single dimension:
for ax in np.reshape(axs, -1):
ax.plot(...)
Related
I am new to Pyplot and simply trying to read data from a .csv file and produce a line plot using ax.plot(x,y):
filepath ='Monthly_Raw_Financials.csv'
raw_data = pd.`read_csv`(filepath, index_col='Month', parse_dates=True)
fig, ax = plt.subplots()
ax.plot(raw_data.index, raw_data['Profit'])
plt.show()
I get only an empty axis with no data plotted and and error message "'Series' object has no attribute 'find'". I am following the example of a number of tutorials. What am I doing wrong?
In pandas, a column is a Series object, which isn't quite the same as a numpy array. It holds a numpy array in its .values attribute, but it also holds an index (.index attribute). I don't understand where your error comes from, but you could try plotting the values instead, i.e.
fig, ax = plt.subplots()
ax.plot(raw_data.index, raw_data['Profit'].values)
plt.show()
Note that you could use the plot method on your dataframe as:
ax = raw_data.plot('Profit')
plt.show()
I know how to plot a single numpy array
import matplotlib.pyplot as plt
plt.imshow(np.array)
But is there any way to plot multiple numpy array in one figure? I know plt.subplots() can display multiple pictures. But it seems hard in my case. I have tried to use a for loop.
fig, ax = plt.subplots()
for i in range(10):
ax.imshow(np.array) # i_th numpy array
This seems to plot a single numpy array one by one. Is there any ways to plot all my 10 numpy arrays in one figure?
PS: Here each my 2d numpy array represents the pixel of a picture. plot seems to plot lines which is not suitable in my case.
The documentation for plt.subplots() (here) specifies that it takes an nrows and ncols arguments and returns a fig object and an array of ax objects. For your case this would look like this:
fig, axs = plt.subplots(3, 4)
axs now contains a 2D array filled with ax objects that you can use to plot various things, e.g. axs[0,1].plot([1,2],[3,4,]) would plot something on the first row, second column.
If you want to remove a particular ax object you can do that with .remove(), e.g. axs[0,1].remove().
For .imshow it works in exactly the same way as .plot: select the ax you want and call imshow on it.
A full example with simulated image data for your case would be:
import numpy as np
import matplotlib.pyplot as plt
fig, axs = plt.subplots(3, 4)
images = [np.array([[1,2],[3,4]]) for _ in range(10)]
for i, ax in enumerate(axs.flatten()):
if i < len(images):
ax.imshow(images[i])
else:
ax.remove()
plt.show()
With as the result:
I am trying to create a figure which contains 9 subplots (3 x 3). X, and Y axis data is coming from the dataframe using groupby. Here is my code:
fig, axs = plt.subplots(3,3)
for index,cause in enumerate(cause_list):
df[df['CAT']==cause].groupby('RYQ')['NO_CONSUMERS'].mean().axs[index].plot()
axs[index].set_title(cause)
plt.show()
However, it does not produce the desired output. In fact it returned the error. If I remove the axs[index]before plot() and put inside the plot() function like plot(ax=axs[index]) then it worked and produces nine subplot but did not display the data in it (as shown in the figure).
Could anyone guide me where am I making the mistake?
You need to flatten axs otherwise it is a 2d array. And you can provide the ax in plot function, see documentation of pandas plot, so using an example:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
cause_list = np.arange(9)
df = pd.DataFrame({'CAT':np.random.choice(cause_list,100),
'RYQ':np.random.choice(['A','B','C'],100),
'NO_CONSUMERS':np.random.normal(0,1,100)})
fig, axs = plt.subplots(3,3,figsize=(8,6))
axs = axs.flatten()
for index,cause in enumerate(cause_list):
df[df['CAT']==cause].groupby('RYQ')['NO_CONSUMERS'].mean().plot(ax=axs[index])
axs[index].set_title(cause)
plt.tight_layout()
I am trying to plot box plots and violin plots for three variables against a variable in a 3X2 subplot formation. But I am not able to figure out how to include sns lib with subplot function.
#plots=plt.figure()
axis=plt.subplots(nrows=3,ncols=3)
for i,feature in enumerate(list(df.columns.values)[:-1]):
axis[i].plot(sns.boxplot(data=df,x='survival_status_after_5yrs',y=feature))
i+=1
axis[i].plot(sns.violinplot(data=df,x='survival_status_after_5yrs',y=feature))
plt.show()```
I am expecting 3X2 subplot, x axis stays same all the time y axis rolls over the three variables I have mentioned.
Thanks for your help.
I think you have two problems.
First, plt.subplots(nrows=3, ncols=2) returns a figure object and an array of axes objects so you should replace this line with:
fig, ax = plt.subplots(nrows=3, ncols=2). The ax object is now a 3x2 numpy array of axes objects.
You could turn this into a 1-d array with ax = ax.flatten() but given what I think you are trying to do I think it is easier to keep as 3x2.
(Btw I assume the ncols=3 is a typo)
Second, as Ewoud answer mentions with seaborn you pass the axes to plot on as an argument to the plot call.
I think the following will work for you:
fig, ax = plt.subplots(nrows=3, ncols=2)
for i, feature in enumerate(list(df.columns.values)[:-1]):
# for each feature create two plots on the same row
sns.boxplot(data=df, x='survival_status_after_5yrs',y=feature, ax=ax[i, 0])
sns.violinplot(data=df, x='survival_status_after_5yrs', y=feature, ax=ax[i, 1])
plt.show()
Most seaborn plot functions have an axis kwarg, so instead of
axis[i].plot(sns.boxplot(data=df,x='survival_status_after_5yrs',y=feature))
try
sns.boxplot(data=df,x='survival_status_after_5yrs',y=feature,axis=axis[i])
I tried to plot the subplots using the below code .But I am getting 'AttributeError: 'numpy.ndarray' object has no attribute 'boxplot'.
but changing the plt.subplots(1,2) it is plotting the box plot with indexerror.
import matplotlib.pyplot as plt
import seaborn as sns
fig = plt.Figure(figsize=(10,5))
x = [i for i in range(100)]
fig , axes = plt.subplots(2,2)
for i in range(4):
sns.boxplot(x, ax=axes[i])
plt.show();
I am expecting four subplots should be plotted but AttributeError is throwing
Couple of issues in your plot:
You are defining the figure twice which is not needed. I merged them into one.
You were looping 4 times using range(4) and using axes[i] for accessing the subplots. This is wrong for the following reason: Your axes is 2 dimensional so you need 2 indices to access it. Each dimension has length 2 because you have 2 rows and 2 columns so the only indices you can use are 0 and 1 along each axis. For ex. axes[0,1], axes[1,0] etc.
As #DavidG pointed out, you don't need the list comprehension. YOu can directly use range(100)
The solution is to expand/flatten make your 2d axes object and then directly iterate over it which gives you individual subplot, one at a time. The order of subplots will be row wise.
Complete working code
import matplotlib.pyplot as plt
import seaborn as sns
x = range(100)
fig , axes = plt.subplots(2,2, figsize=(10,5))
for ax_ in axes.flatten():
sns.boxplot(x, ax=ax_)
plt.show()