Increasing plot size with multiple plots? - python-3.x

I am trying to plot a histogram with my data.
Using python on Jupyter notebook
viz = cdf[['GyrNative', 'GyMutant', 'Hbond_native', 'HMutant', 'RMSDNative','RMSDMutant', 'RMSFNative', 'RMSFMutant', 'SASANative', 'SASAMutant']]
plt.figure(figsize = (15,10))
viz.hist(grid=True, rwidth = 0.9, color ='red')
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.1)
plt.show()
The plot generated are really tiny... How may I increase the size of each plot at once?

Following from the comments, if you just want to make the whole thing bigger, you should just add figsize to this and rearrange your plt. calls:
plt.tight_layout(pad=0.9, w_pad=0.5, h_pad=0.1)
viz.hist(grid=True, rwidth = 0.9, color ='red', figsize=(15,10))
plt.show()

Related

How to make the scatterplot square than rectangle? [duplicate]

This question already has answers here:
How can I set the aspect ratio in matplotlib?
(7 answers)
Closed last month.
I created a scatter plot which has equal min, max, steps for both x and y axis. However the result keeps making my graph look rectangle rather than a square. How can I fix this?
'''
ax = ctrl_ra.plot.scatter(x='Control', y='Infection(Ra)', color='black', alpha=0.5)
ax2 = df_sig.plot.scatter(ax=ax, x= 'Control', y='Infection(Ra)', color='red', alpha=0.5, s=5)
#Set the x-axis and y-axis scales
ax.set_xticks(np.arange(0,21,5))
ax.set_yticks(np.arange(0,21,5))
ax2.set_xticks(np.arange(0,21,5))
ax2.set_yticks(np.arange(0,21,5))
plt.show()
'''
This is what I got when I ran my code.
At first I thought it was the axis scale and/or size but it wasn't so I'm not sure where to go about to fix this problem.
Any help is appreciated. Thank you.
It is the figure size, not axes scale.
Try adding
plt.figure(figsize=(12, 12))
before plotting. Or, better, use
fig, ax = plt.subplots(figsize=(12, 12))

Python 3 matplotlib add a watermark with multiple scale axis

In python 3, i am trying to add watermark with multiple scale axis in the following pandas data frame
index,as_of_date,Total_10bn,close
0,2020-08-05,620.55975367473,332.11
1,2020-08-12,621.9414641848599,337.44
2,2020-08-19,628.88298116372,337.23
3,2020-08-26,627.26943375402,347.57
4,2020-09-02,630.01703674403,357.7
5,2020-09-09,630.70673674269,339.79
6,2020-09-16,637.50390815142,338.82
I can make the multiple scale works
df_soma_spy=pd.read_csv('df_soma_spy.csv')
print(df_soma_spy)
# create figure and axis objects with subplots()
fig,ax = plt.subplots()
plt.xticks(rotation=90)
ax.plot(df_soma_spy.as_of_date, df_soma_spy.Total_10bn, color="red") ## , marker="o"
# set x-axis label
ax.set_xlabel("Date", fontsize=12)
# set y-axis label
ax.set_ylabel("Fed SOMA ($10bn)",color="red",fontsize=14)
plt.grid(True, axis='both', which='both')
# twin object for two different y-axis on the sample plot
ax2=ax.twinx()
# make a plot with different y-axis using second axis object
ax2.plot(df_soma_spy.as_of_date, df_soma_spy["close"], color="black") ## , marker="o"
ax2.set_ylabel("$SPY Price",color="black",fontsize=14)
plt.title('Federal Reserves SOMA Total vs $SPY')
plt.show()
# save the plot as a file
fig.savefig('soma_spy.png',
format='jpeg',
dpi=300,
bbox_inches='tight')
Now I am trying to add a logo behind the picture. But no matter how I try, it will mess up one of the axis.
For example
import matplotlib.image as image
im = image.imread('xxx.png')
myaximage = ax.imshow(im, aspect='auto', extent=(0.1,0.1,0.1,0.1), alpha=0.5, zorder=-1)
In this case, the logo doesn't show up and the red axis is totally messed up.
There are some other solutions but none of them seems to work.
Scale image in matplotlib without changing the axis
Matplotlib automate placement of watermark
Scale image in matplotlib without changing the axis
Any thoughts? Thank you!
Instead of ax.imshow(), you can use fig.figimage() as shown below and described here. Just insert the following two lines in your code:
logo = image.imread(fname='logo.png')
fig.figimage(logo,alpha= 0.1)
Using the partial data you provided, here is the saved image:

How to align heights and widths subplot axes with gridspec and matplotlib?

I am trying to use matplotlib with gridspec to create a subplot such that the axes are arranged to look similar to the figure below; the figure was taken from this unrelated question.
My attempt at recreating this axes arrangement is below. Specifically, my problem is that the axes are not properly aligned. For example, the axis object for the blue histogram is taller than the axis object for the image with various shades of green; the orange histogram seems to properly align in terms of width, but I attribute this to luck. How can I properly align these axes? Unlike the original figure, I would like to add/pad extra empty space between axes such that there borders do not intersect; the slice notation in the code below does this by adding a blank row/column. (In the interest of not making this post longer than it has to be, I did not make the figures "pretty" by playing with axis ticks and the like.)
Unlike the original picture, the axes are not perfectly aligned. Is there a way to do this without using constrained layout? By this, I mean some derivative of fig, ax = plt.subplots(constrained_layout=True)?
The MWE code to recreate my figure is below; note that there was no difference between ax.imshow(...) and ax.matshow(...).
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
## initialize figure and axes
fig = plt.figure()
gs = fig.add_gridspec(6, 6, hspace=0.2, wspace=0.2)
ax_bottom = fig.add_subplot(gs[4:, 2:])
ax_left = fig.add_subplot(gs[:4, :2])
ax_big = fig.add_subplot(gs[:4, 2:])
## generate data
x = np.random.normal(loc=50, scale=10, size=100)
y = np.random.normal(loc=500, scale=50, size=100)
## get singular histograms
x_counts, x_edges = np.histogram(x, bins=np.arange(0, 101, 5))
y_counts, y_edges = np.histogram(y, bins=np.arange(0, 1001, 25))
x_mids = (x_edges[1:] + x_edges[:-1]) / 2
y_mids = (y_edges[1:] + y_edges[:-1]) / 2
## get meshed histogram
sample = np.array([x, y]).T
xy_counts, xy_edges = np.histogramdd(sample, bins=(x_edges, y_edges))
## subplot histogram of x
ax_bottom.bar(x_mids, x_counts,
width=np.diff(x_edges),
color='darkorange')
ax_bottom.set_xlim([x_edges[0], x_edges[-1]])
ax_bottom.set_ylim([0, np.max(x_counts)])
## subplot histogram of y
ax_left.bar(y_mids, y_counts,
width=np.diff(y_edges),
color='steelblue')
ax_left.set_xlim([y_edges[0], y_edges[-1]])
ax_left.set_ylim([0, np.max(y_counts)])
## subplot histogram of xy-mesh
ax_big.imshow(xy_counts,
cmap='Greens',
norm=Normalize(vmin=np.min(xy_counts), vmax=np.max(xy_counts)),
interpolation='nearest',
origin='upper')
plt.show()
plt.close(fig)
EDIT:
One can initialize the axes by explicitly setting width_ratios and height_ratios per row/column; this is shown below. This doesn't affect the output, but maybe I'm using it incorrectly?
## initialize figure and axes
fig = plt.figure()
gs = gridspec.GridSpec(ncols=6, nrows=6, figure=fig, width_ratios=[1]*6, height_ratios=[1]*6)
ax_bottom = fig.add_subplot(gs[4:, 2:])
ax_left = fig.add_subplot(gs[:4, :2])
ax_big = fig.add_subplot(gs[:4, 2:])
The problem is with imshow, which resizes the axes automatically to maintain a square pixel aspect.
You can prevent this by calling:
ax_big.imshow(..., aspect='auto')

How to plot fill_betweenx to fill the area between y1 and y2 with different scales using matplotlib.pyplot?

I am trying to fill the area between two vertical curves(RHOB and NPHI) using matplotlib.pyplot. Both RHOB and NPHI are having different scale of x-axis.
But when i try to plot i noticed that the fill_between is filling the area between RHOB and NPHI in the same scale.
#well_data is the data frame i am reading to get my data
#creating my subplot
fig, ax=plt.subplots(1,2,figsize=(8,6),sharey=True)
ax[0].get_xaxis().set_visible(False)
ax[0].invert_yaxis()
#subplot 1:
#ax01 to house the NPHI curve (NPHI curve are having values between 0-45)
ax01=ax[0].twiny()
ax01.set_xlim(-15,45)
ax01.invert_xaxis()
ax01.set_xlabel('NPHI',color='blue')
ax01.spines['top'].set_position(('outward',0))
ax01.tick_params(axis='x',colors='blue')
ax01.plot(well_data.NPHI,well_data.index,color='blue')
#ax02 to house the RHOB curve (RHOB curve having values between 1.95,2.95)
ax02=ax[0].twiny()
ax02.set_xlim(1.95,2.95)
ax02.set_xlabel('RHOB',color='red')
ax02.spines['top'].set_position(('outward',40))
ax02.tick_params(axis='x',colors='red')
ax02.plot(well_data.RHOB,well_data.index,color='red')
# ax03=ax[0].twiny()
# ax03.set_xlim(0,50)
# ax03.spines['top'].set_position(('outward',80))
# ax03.fill_betweenx(well_data.index,well_data.RHOB,well_data.NPHI,alpha=0.5)
plt.show()
ax03=ax[0].twiny()
ax03.set_xlim(0,50)
ax03.spines['top'].set_position(('outward',80))
ax03.fill_betweenx(well_data.index,well_data.RHOB,well_data.NPHI,alpha=0.5)
above is the code that i tried, but the end result is not what i expected.
it is filling area between RHOB and NPHI assuming RHOB and NPHI is in the same scale.
How can i fill the area between the blue and the red curve?
Since the data are on two different axes, but each artist needs to be on one axes alone, this is hard. What would need to be done here is to calculate all data in a single unit system. You might opt to transform both datasets to display-space first (meaning pixels), then plot those transformed data via fill_betweenx without transforming again (transform=None).
import numpy as np
import matplotlib.pyplot as plt
y = np.linspace(0, 22, 101)
x1 = np.sin(y)/2
x2 = np.cos(y/2)+20
fig, ax1 = plt.subplots()
ax2 = ax1.twiny()
ax1.tick_params(axis="x", colors="C0", labelcolor="C0")
ax2.tick_params(axis="x", colors="C1", labelcolor="C1")
ax1.set_xlim(-1,3)
ax2.set_xlim(15,22)
ax1.plot(x1,y, color="C0")
ax2.plot(x2,y, color="C1")
x1p, yp = ax1.transData.transform(np.c_[x1,y]).T
x2p, _ = ax2.transData.transform(np.c_[x2,y]).T
ax1.autoscale(False)
ax1.fill_betweenx(yp, x1p, x2p, color="C9", alpha=0.4, transform=None)
plt.show()
We might equally opt to transform the data from the second axes to the first. This has the advantage that it's not defined in pixel space and hence circumvents a problem that occurs when the figure size is changed after the figure is created.
x2p, _ = (ax2.transData + ax1.transData.inverted()).transform(np.c_[x2,y]).T
ax1.autoscale(False)
ax1.fill_betweenx(y, x1, x2p, color="grey", alpha=0.4)

Seaborn: lining up 2 distplots on same axes

I'm trying to create 2 distplots that overlap on same axes, but they seem to be offset. How can I adjust this so that their overlapping is exact? Please see the image link below for the issue I have.
plt.figure(figsize=(10,8))
ax1 = sns.distplot(loans['fico'][loans['credit.policy']==1], bins= 10, kde=False, hist_kws=dict(edgecolor='k', lw=1))
ax2 = sns.distplot(loans['fico'][loans['credit.policy']==0], bins= 10, color='Red', kde=False, hist_kws=dict(edgecolor='k', lw=1))
ax1.set_xlim([600, 850])
ax2.set_xlim([600, 850])
Problematic result
The plots aren't lining up because Seaborn (well, Matplotlib behind the scenes) is working out the best way to give you ten bins for each set of data you pass to it. But the two sets might not have the same range.
You can provide a sequence as the bins argument, which defines the edges of the bins. Assuming you have numpy available you can use its linspace function to easily create this sequence from the smallest and largest values in your data.
plt.figure(figsize(10,8))
bins = np.linspace(min(loans['fico']), max(loans['fico']), num=11)
ax1 = sns.distplot(loans['fico'][loans['credit.policy']==1], bins=bins,
kde=False, hist_kws=dict(edgecolor='k', lw=1))
ax2 = sns.distplot(loans['fico'][loans['credit.policy']==0], bins=bins,
color='Red', kde=False, hist_kws=dict(edgecolor='k', lw=1))
And then you shouldn't need to set the x limits.
An example with some randomly generated values:

Resources