This question already has answers here:
How to plot in multiple subplots
(12 answers)
Closed 3 years ago.
I have the following code:
def compare(f,a,b,c,d,n,points):
"""Plots 2 figures - one of the color map of f, and one of the color map of a rectangle [a,b] x [c,d], split
into n^2 subareas, using the list of points to estimate the color map"""
#fig, axes = plt.subplots(nrows=2, ncols=2)
q = plt.figure(1)
colorMapList(f,a,b,c,d,n,points)
#q.show()
p = plt.figure(2)
colorMap(f)
plt.show()
The functions colorMapList and colorMap both return ax.contourf(Y,X,z).
When I have the code the way I have it, the program outputs two diagrams, one below the other. How can I have it so that the diagrams are displayed horizontally next to each other?
Thanks!
If you want both graphs on a single figure then you can use plt.subplot(121) and plt.subplot(122). The first index is the number of rows and the second index is the number of cols. The third index is the position count of the figure layout, so if it was subplot(221) would be a 2x2 display of graphs and the 1 represents the graph in the upper left. Then, subplot(222) would be upper right, subplot(223) is bottom left, and subplot(224) is bottom right. This follow the sequence from top left to right for each row.
However, if you want to plot 2 different figures that are side-by-side then you can look at this solution.
Related
This question already has answers here:
When should you use ax. in matplotlib?
(1 answer)
What is the difference between drawing plots using plot, axes or figure in matplotlib?
(2 answers)
Closed 5 months ago.
I am trying to subplot these 2 pandas bar plot but when I create a subplot the tags provided with xticks are deleted in the first subplot. I tried to plt.hold(True) but didn't solve the problem. What exactly is causing this error? You can find visualization of the problem and code below, thanks in advance.
fig, (ax1, ax2) = plt.subplots(1, 2)
#Get the first 10 common words by head
words_freq_head = pd.DataFrame(words_freq).head(10)
#Plot the first 10 common words
words_freq_head.plot.bar(ax=ax1)
#Set the label of common words on x axes
plt.xticks(np.arange(len(words_freq_head[0])), words_freq_head[0])
#Get the first 10 uncommon words by tail
words_freq_tail = pd.DataFrame(words_freq).tail(10)
#Plot the first 10 uncommon words
words_freq_tail.plot.bar(ax=ax2)
#Set the label of uncommon words on x axes
plt.xticks(np.arange(len(words_freq_tail[0])), words_freq_tail[0])
This question already has answers here:
How to highlight specific x-value ranges
(2 answers)
Closed 1 year ago.
I went through the examples in the matplotlib documentation, but it wasn't clear to me how I can make a plot that fills the area between two specific vertical lines.
For example, say I want to create a plot between x=0.2 and x=4 (for the full y range of the plot). Should I use fill_between, fill or fill_betweenx?
Can I use the where condition for this?
It sounds like you want axvspan, rather than one of the fill between functions. The differences is that axvspan (and axhspan) will fill up the entire y (or x) extent of the plot regardless of how you zoom.
For example, let's use axvspan to highlight the x-region between 8 and 14:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(range(20))
ax.axvspan(8, 14, alpha=0.5, color='red')
plt.show()
You could use fill_betweenx to do this, but the extents (both x and y) of the rectangle would be in data coordinates. With axvspan, the y-extents of the rectangle default to 0 and 1 and are in axes coordinates (in other words, percentages of the height of the plot).
To illustrate this, let's make the rectangle extend from 10% to 90% of the height (instead of taking up the full extent). Try zooming or panning, and notice that the y-extents say fixed in display space, while the x-extents move with the zoom/pan:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(range(20))
ax.axvspan(8, 14, ymin=0.1, ymax=0.9, alpha=0.5, color='red')
plt.show()
This question already has an answer here:
How to return a matplotlib.figure.Figure object from Pandas plot function
(1 answer)
Closed 2 years ago.
I have created a 3x3 subplots by using the pandas df.line.plot:
ax=df.plot.line(subplots=True, grid=True,layout=(3, 3), sharex=True, legend=False,ylim=[-5,25])
It returns 3x3 matrix of Axes objects.
Now I want to create a joint legend for those subplots.
As the other post suggests I should use:
handles, labels = ax.get_legend_handles_labels()
fig.legend(handles, labels, loc='upper center')
The problem is I can't use it because I have no figure created here. I only have axes. How can I make it work?
I edited the post, because I thought I could create a figure and prescribe the axes, but I guess it came from my confusion on subject.
You have two options:
First: Either use double indices (for row and column) as shown in the comments and then use ax[0,0], ax[0,1], ax[0,2] ... ax[2,0], ax[2,1], ax[2,2]. For 3 rows and 3 columns, the indices will run from 0 up to 2 (so 0, 1, 2)
You can also use ax[0][0] and so on. Both formats are equivalent.
Second: If you don't want to use two indices, you can flatten the ax and then use a single index as
ax = ax.flatten()
This will convert ax from 2d object to a 1-d array of 9 subfigures. Then you can use ax[0], ax[1], ax[2], ... ax[8] (9-1 because indexing starts from 0 in python)
Using matlotlib, I can create figures that look like this:
Here, each row consists of a series of numbers from 0 to 0.6. The left hand axis text indicates the maximum value in each row. The bottom axis text represents the column indices.
The code for the actual grid essentially involves this line:
im = ax[r,c].imshow(info_to_use, vmin=0, vmax=0.6, cmap='gray')
where ax[r,c] is the current subplot axes at row r and column c, and info_to_use is a numpy array of shape (num_rows, num_cols) and has values between 0 and 0.6.
I am wondering if there is a way to convert the code above so that it instead displays bar charts, one per row? Something like this hand-drawn figure:
(The number of columns is not the same in my hand-drawn figure compared to the earlier one.) I know this would result in a very hard-to-read plot if it were embedded into a plot like the first one here. I would have this for a plot with fewer rows, which would make the bars easier to read.
The references that helped me make the first plot above were mostly from:
Python - Plotting colored grid based on values
custom matplotlib plot : chess board like table with colored cells
https://matplotlib.org/3.1.1/gallery/subplots_axes_and_figures/colorbar_placement.html#sphx-glr-gallery-subplots-axes-and-figures-colorbar-placement-py
https://matplotlib.org/3.1.1/gallery/images_contours_and_fields/image_annotated_heatmap.html#sphx-glr-gallery-images-contours-and-fields-image-annotated-heatmap-py
But I'm not sure how to make the jump from these to a bar chart in each row. Or at least something that could mirror it, e.g., instead of shading the full cell gray, only shade as much of it based on the percentage of the vmax?
import numpy as np
from matplotlib import pyplot as plt
a = np.random.rand(10,20)*.6
In a loop, call plt.subplot then plt.bar for each row in the 2-d array.
for i, thing in enumerate(a,1):
plt.subplot(a.shape[0],1,i)
plt.bar(range(a.shape[1]),thing)
plt.show()
plt.close()
Or, create all the subplots; then in a loop make a bar plot with each Axes.
fig, axes = plt.subplots(a.shape[0],1,sharex=True)
for ax, data in zip(axes, a):
ax.bar(range(a.shape[1]), data)
plt.show()
plt.close()
The att_sales table has 3 fields item,qty and yr_mon. The buckets(i) function returns a list of 20 SKUs(list of item values). A group by function is used to find the monthly sales for each of these SKUs
and then churns out a violinplot. The exercise wors fine till this point.
I am trying to visualize the monthly sales for about 200 SKUs along 10 subplots.To do this I intended an iterator to run from 1 through 10 and populate each of the subplots.The code below populates the last subplot out of 10 empty ones. How do I go about achieving this?
fig, (axis1) = plt.subplots(5,2,figsize=(15,30))
plt.xticks(rotation=45)
s=att_sales[['item','qty','yr_mon']]
s=s[s.item.isin(buckets(i))]
s=s.groupby(['item','yr_mon'], as_index=False).qty.sum()
sns.violinplot(x="item", y="qty", data=s)
Edit1: On implmenting #Ted's solution I got an error min() arg is an empty sequence when the for loop ran from 0 to n. Changing the for loop to run between 1 and n, provides most the solution but not quite.
I need to know how to increase the size of the overall plot and of the individual subplots, and also change the orientation of the xticks to 45 degrees.
Here is a simplified example that I think you can tweak to make it work for you. I am using the tips dataset in seaborn and plotting 4 different violin plots based on what day it is. I have also created a buckets function that returns a single element list of one day.
When the figure is created with fig, axes = plt.subplots(2,2,figsize=(10,10)), it returns both a matplotlib figure object which is stored into fig and a 2 dimensional numpy array of matplotlib axes objects which is stored in axes. To get the top left plot you would do axes[0, 0]. If you wanted the bottom right hand plot you would do axes[1, 1]. If you created a 5 row by 2 column figure axes[3,0] would be the plot on the 4th row and first column.
# create function that will return a list of items
# this particular example returns just a list of one element
def buckets(i):
return [tips.day.unique()[i]]
# load dataset and create figure
tips = sns.load_dataset("tips")
num_plots = 4
fig, axes = plt.subplots(2,2,figsize=(10,10))
# iterate through all axes and create a violin plot
for i in range(num_plots):
df = tips[tips.day.isin(buckets(i))]
row = i // 2
col = i % 2
ax_curr = axes[row, col]
sns.violinplot(x="sex", y="tip", data=df, ax=ax_curr)
ax_curr.set_title(buckets(i))
Note that in this particular example you can use a facet grid which will do the same exact thing as what I did by plotting each day in a separate plot. You can take advantage of the facet grid if you label each bucket of SKUs a unique id. See the very last example on this page