Below is the output (subplots) from my codes
What I want to do is -
on the first graph (left most) instead of putting "Category1 y axis / Category2 x axis" at the top I wanted Category1 along the y axis and Category2 along the x-axis at the bottom.
Also can I move xticklabels for all the graphs to the top?
codes
import matplotlib.pyplot as plt
import seaborn as sns
dataf = np.random.randint(1,10,9).reshape(3,3)
dataA = np.random.randint(1,10,9).reshape(3,3)
dataB = np.random.randint(1,10,9).reshape(3,3)
fig, (ax1, ax2, ax3) = plt.subplots(1,3)
ax1.set_title("Category1 y axis / Category2 x axis")
ax2.set_title("Category1 average value")
ax3.set_title("Category2 average value")
sns.heatmap(dataf, ax=ax1,annot=True)
sns.heatmap(dataA, ax=ax2,annot=True)
sns.heatmap(dataB, ax=ax3,annot=True)
plt.show()
To set the x- and y-labels, use set_xlabel() and set_ylabel().
To move the x-ticks, use labeltop=True in tick_params().
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
dataf = np.random.randint(1,10,9).reshape(3,3)
dataA = np.random.randint(1,10,9).reshape(3,3)
dataB = np.random.randint(1,10,9).reshape(3,3)
fig, (ax1, ax2, ax3) = plt.subplots(1,3)
sns.heatmap(dataf, ax=ax1, annot=True)
sns.heatmap(dataA, ax=ax2, annot=True)
sns.heatmap(dataB, ax=ax3, annot=True)
# set leftmost ylabel
ax1.set_ylabel('Category 1')
# set xlabels
ax1.set_xlabel('Category 2')
ax2.set_xlabel('Category 1 average value')
ax3.set_xlabel('Category 2 average value')
# move xticklabels to top
ax1.tick_params(which='major', labelbottom=False, labeltop=True)
ax2.tick_params(which='major', labelbottom=False, labeltop=True)
ax3.tick_params(which='major', labelbottom=False, labeltop=True)
ax1.set_ylabel('Category1')
ax1.set_xlabel('Category2')
Related
I have the following code to create a heatmap. However, it creates an overlap of the color bar and the right axis text. The text has no problems, I want it to be in that length.
How can I locate the colorbar on the right/left side of the heatmap with no overlap?
I tried with "pad" parameter in cbar_kws but it didn't help.enter image description here
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
PT=pd.DataFrame(np.random.randn(300,3), columns=list('ABC'))
miniPT=PT.iloc[:,:-1]
SMALL_SIZE = 8
MEDIUM_SIZE = 80
BIGGER_SIZE = 120
plt.rc('font', size=MEDIUM_SIZE) # controls default text sizes
plt.rc('axes', titlesize=MEDIUM_SIZE) # fontsize of the axes title
plt.rc('axes', labelsize=MEDIUM_SIZE) # fontsize of the x and y labels
plt.rc('xtick', labelsize=MEDIUM_SIZE) # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE) # fontsize of the tick labels
plt.rc('legend', fontsize=MEDIUM_SIZE) # legend fontsize
plt.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title
plt.figure(figsize=(10, miniPT.shape[0]/5.2))
ax =sns.heatmap(miniPT, annot=False, cmap='RdYlGn')
for _, spine in ax.spines.items():
spine.set_visible(True)
# second axis
asset_list=np.asarray(PT['C'])
asset_list=asset_list[::-1]
ax3 = ax.twinx()
ax3.set_ylim([0,ax.get_ylim()[1]])
ax3.set_yticks(ax.get_yticks())
ax3.set_yticklabels(asset_list, fontsize=MEDIUM_SIZE*0.6)
# colorbar
cbar = ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=MEDIUM_SIZE)
One way to get the overlap automatically adjusted by matplotlib, is to explicitly create subplots: one for the heatmap and another for the colorbar. sns.heatmap's cbar_ax= parameter can be set to point to this subplot. gridspec_kws= is needed to set the relative sizes. At the end, plt.tight_layout() will adjust all the paddings to make everything fit nicely.
The question's code contains some strange settings (e.g. a fontsize of 80 is immense). Also, 300 rows will inevitably lead to overlapping text (the fontsize needs to be so small that non-overlapping text wouldn't be readable). Here is some more simplified example code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
PT = pd.DataFrame(np.random.randn(100, 3), columns=list('ABC'))
fig, (ax, cbar_ax) = plt.subplots(ncols=2, figsize=(10, len(PT) / 5.2), gridspec_kw={'width_ratios': [10, 1]})
sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=cbar_ax, ax=ax)
for _, spine in ax.spines.items():
spine.set_visible(True)
# second axis
asset_list = np.asarray(PT['C'])
ax3 = ax.twinx()
ax3.set_ylim(ax.get_ylim())
ax3.set_yticks(np.arange(len(PT)))
ax3.set_yticklabels(asset_list, fontsize=80)
# colorbar
cbar_ax.tick_params(labelsize=80)
plt.tight_layout()
plt.show()
As the plot is quite large, here only the bottom part is pasted, with a link to the full plot.
This is how it would look like with:
fontsize 80 (Note that font sizes are measured in "points per inch", standard 72 points per inch);
figure width of 20 inches (instead of 10);
300 rows
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
PT = pd.DataFrame(np.random.randn(300, 3), columns=list('ABC'))
fig, (ax, cbar_ax) = plt.subplots(ncols=2, figsize=(20, len(PT) / 5.2), gridspec_kw={'width_ratios': [15, 1]})
sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=cbar_ax, ax=ax)
for _, spine in ax.spines.items():
spine.set_visible(True)
# second axis
asset_list = np.asarray(PT['C'])
ax3 = ax.twinx()
ax3.set_ylim(ax.get_ylim())
ax3.set_yticks(np.arange(len(PT)))
ax3.set_yticklabels(asset_list, fontsize=80)
# colorbar
cbar_ax.tick_params(labelsize=80)
plt.tight_layout()
plt.show()
My solution was eventually move the colorbar to left side. This is the code and the output:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
PT = pd.DataFrame(np.random.randn(300, 3), columns=list('ABC'))
fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, len(PT) / 5.2), gridspec_kw={'width_ratios': [15, 15]})
sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=ax0, ax=ax1)
for _, spine in ax1.spines.items():
spine.set_visible(True)
# second axis
asset_list = np.asarray(PT['C'])
ax3 = ax1.twinx()
ax3.set_ylim(ax1.get_ylim())
ax3.set_yticks(np.arange(len(PT)))
ax3.set_yticklabels(asset_list, fontsize=80)
# colorbar
ax0.tick_params(labelsize=80)
plt.tight_layout()
plt.show()
Could you change my code in this way so as to have these 2 plots alongside, means in 1 row and 2 column (subplot nrows=1, ncols=2) ? Currently I have these charts in 2 separate cells, and I want to have them in 1.
my code:
First plot:
from yellowbrick.classifier import (PrecisionRecallCurve)
fig, ax = plt.subplots(figsize=(10, 6))
viz = PrecisionRecallCurve(DecisionTreeClassifier(max_depth=4))
viz.fit(X_train_model_2, y_train_model_2)
print(viz.score(X_test_model_2, y_test_model_2))
viz.ax.set(title="Krzywa precyzja-czułość klasyfikatora drzewa losowego",
xlabel="Czułość",
ylabel="Precyzja")
ax.legend(("Binarna krzywa precyzja-czułość",
"Średnia precyzja = {:0.2f}".format(viz.score(X_test_model_2,y_test_model_2))),
frameon=True,
loc="lower left")
plt.show()
Second plot:
import scikitplot as skplt
fig, ax = plt.subplots(figsize=(10, 6))
y_probas = decision_tree.predict_proba(X_test_model_2)
skplt.metrics.plot_cumulative_gain(y_test_model_2,
y_probas,
ax=ax)
ax.set(title="Krzywa skumulowanych zysków",
xlabel="Odsetek próbek",
ylabel="Zysk")
ax.legend(("Klasa 0",
"Klasa 1",
"Krzywa odniesienia"),
frameon=True,
loc="lower right")
plt.show()
Maybe that helps:
from yellowbrick.classifier.prcurve import PrecisionRecallCurve
import scikitplot as skplt
import numpy as np
import sklearn
import sklearn.tree
import matplotlib.pyplot as plt
#generate some test data
X = np.arange(200)+np.random.normal(0,10,200)
y = np.array([True if (x <100) and (x > 50) else False for x in X])
X = X.reshape(-1,1)
X_train_model_2 = []
y_train_model_2 = []
X_test_model_2 = []
y_test_model_2 = []
X_train_model_2,X_test_model_2,y_train_model_2,y_test_model_2=
sklearn.model_selection.train_test_split(
X, y,
test_size=0.4,
random_state=0)
fig, (ax1, ax2) = plt.subplots(1,2) #1 row, 2 columns
viz = PrecisionRecallCurve(sklearn.tree.DecisionTreeClassifier(max_depth=4),
ax = ax1) #set the axis to plot one (ax1)
decision_tree = viz.fit(X_train_model_2, y_train_model_2)
print(viz.score(X_test_model_2, y_test_model_2))
#Set the attributes for plot one
ax1.set(title="Krzywa precyzja-czułość klasyfikatora drzewa losowego",
xlabel="Czułość",
ylabel="Precyzja")
ax1.legend(("Binarna krzywa precyzja-czułość",
"Średnia precyzja {:0.2f}".format(viz.score(X_test_model_2,y_test_model_2))),
frameon=True,
loc="lower left")
y_probas = decision_tree.predict_proba(X_test_model_2)
skplt.metrics.plot_cumulative_gain(y_test_model_2,
y_probas,
ax=ax2) #set the axis to plot two (ax2)
#Set the attributes for plot two
ax2.set(title="Krzywa skumulowanych zysków",
xlabel="Odsetek próbek",
ylabel="Zysk")
ax2.legend(("Klasa 0",
"Klasa 1",
"Krzywa odniesienia"),
frameon=True,
loc="lower right")
#Show the whole plot
plt.show()
This is a follow up for a question which i asked here:
The code is as follows:
from pandas_datareader import data as web
import matplotlib.pyplot as plt
import matplotlib.dates as md
fig, (ax1, ax2) = plt.subplots(2, 1)
df = web.DataReader('F', 'yahoo')
df2 = web.DataReader('Fb', 'yahoo')
ax = df.plot(figsize=(35,15), ax=ax1)
df2.plot(y = 'Close', figsize=(35,15), ax=ax2)
plt.xticks(fontsize = 25)
for ax in (ax1, ax2):
ax.xaxis.set_major_locator(md.MonthLocator(bymonth = range(1, 13, 6)))
ax.xaxis.set_major_formatter(md.DateFormatter('%b\n%Y'))
ax.xaxis.set_minor_locator(md.MonthLocator())
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 0 )
plt.show()
This produces this plot:
How can i increase the size of both the xticks in the two subplots as you can see the size was increased for the bottom one only.
[1]: https://stackoverflow.com/questions/62358966/adding-minor-ticks-to-pandas-plot
You can use the tick_params function on the ax instance to control the size of the tick-labels on the x-axis. If you want to control the size of both x and y axis, use axis='both'. You can additionally specify which='major' or which='minor' or which='both' depending on if you want to change major, minor or both tick labels.
for ax in (ax1, ax2):
# Rest of the code
ax.tick_params(axis='x', which='both', labelsize=25)
I'm trying to create a simple 1 by 3 subplot of the maps I have. They only have 2 dimensions (longitude and latitude) after time averaging. The final map plots perfectly, but the first two subplots are just blank.
Thanks in advance for any advice!
import numpy as np
import xarray as xa
import cmocean.cm as cm
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
lgm = xa.open_dataset('lgm.nc', decode_times=False)
pre = xa.open_dataset('pre-i.nc', decode_times=False)
pd = xa.open_dataset('present.nc', decode_times=False)
def pco2_diff():
lgm_pco2 = lgm.O_pco2sur
pre_pco2 = pre.O_pco2sur
pd_pco2 = pd.O_pco2sur
#-------------------------Time averaged data-------------------------------
lgm_pco2_mean = lgm_pco2.mean("time")
pre_pco2_mean = pre_pco2.mean("time")
pd_pco2_mean = pd_pco2.mean("time")
#-----------------Get the ocean-atmosphere fluxes--------------------------
lgm_pco2_diff = lgm_pco2_mean - 189.65
pre_pco2_diff = pre_pco2_mean - 277.44
pd_pco2_diff = pd_pco2_mean - 368.89
#---------------------Basic plots, 1 at a time-----------------------------
lgm_pco2_diff.plot()
pre_pco2_diff.plot()
pd_pco2_diff.plot()
#-----------------------------Subplots-------------------------------------
f, (ax1, ax2, ax3) = plt.subplots(1, 3, sharey=True, sharex=False)
#1 row, 3 columns, sharing the y-axis, not sharing the x-axis
ax1 = lgm_pco2_diff.plot(vmin=-300, vmax=300, add_colorbar=False)
ax2 = pre_pco2_diff.plot(vmin=-300, vmax=300, add_colorbar=False)
ax3 = pd_pco2_diff.plot(vmin=-300, vmax=300,cmap=cm.thermal)
Maybe try the following:
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharey=True, sharex=False)
ax1.plot(lgm_pco2_diff, vmin=-300, vmax=300, add_colorbar=False)
ax2.plot(pre_pco2_diff, vmin=-300, vmax=300, add_colorbar=False)
ax3.plot(pd_pco2_diff, vmin=-300, vmax=300, cmap=cm.thermal)
I'm plotting a CSV file from my simulation results. The plot has three graphs in the same figure fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(24, 6)).
However, for comparison purposes I want the y-axis in all graphs starting at zero and the ending at a specific value. I tried the solution mentioned here from the Seaborn author. I don't get any errors, but the solution also does not work for me.
Here's my script:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
fname = 'results/filename.csv'
def plot_file():
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(24, 6))
df = pd.read_csv(fname, sep='\t')
profits = \
df.groupby(['providerId', 'periods'], as_index=False)['profits'].sum()
# y-axis needs to start at zero and end at 10
g = sns.lineplot(x='periods',
y='profits',
data=profits,
hue='providerId',
legend='full',
ax=axes[0])
# y-axis need to start at zero and end at one
g = sns.scatterplot(x='periods',
y='price',
hue='providerId',
style='providerId',
data=df,
legend=False,
ax=axes[1])
# y-axis need to start at zero and end at one
g = sns.scatterplot(x='periods',
y='quality',
hue='providerId',
style='providerId',
data=df,
legend=False,
ax=axes[2])
g.set(ylim=(0, None))
plt.show()
print(g) # -> AxesSubplot(0.672059,0.11;0.227941x0.77)
The resulting figure is as follows:
How can I adjust each individual plot?
Based on the way you've written your code, you can refer to each subplot axis with g.axis and use g.axis.set_ylim(low,high). (A difference compared to the linked answer is that your graphs are not being plotted on a seaborn FacetGrid.)
An example using dummy data and different axis ranges to illustrate:
df = pd.DataFrame(np.random.uniform(0,10,(100,2)), columns=['a','b'])
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(8,4))
g = sns.lineplot(x='a',
y='b',
data=df.sample(10),
ax=axes[0])
g.axes.set_ylim(0,25)
g = sns.scatterplot(x='a',
y='b',
data=df.sample(10),
ax=axes[1])
g.axes.set_ylim(0,3.5)
g = sns.scatterplot(x='a',
y='b',
data=df.sample(10),
ax=axes[2])
g.axes.set_ylim(0,0.3)
plt.tight_layout()
plt.show()