Show the yticks in the marginal plots of seaborn.JointGrid - python

I need to show the yticks in the marginal distribution of a Seaborn.jointgrid plot, but it doesn't seem simple.
Here is an example of a code taken from the Seaborn documentation:
import seaborn as sns; sns.set(style="ticks", color_codes=True)
import bumpy as np
tips = sns.load_dataset("tips")
g = sns.JointGrid(x="total_bill", y="tip", data=tips)
g = g.plot_joint(sns.scatterplot, color="m")
_ = g.ax_marg_x.hist(tips["total_bill"], color="b", alpha=.6,
bins=np.arange(0, 60, 5))
_ = g.ax_marg_y.hist(tips["tip"], color="r", alpha=.6,
orientation="horizontal",
bins=np.arange(0, 12, 1))
I would like to add the yaxis and its values to the marginal plots. I can plot the yaxis using:
sns.despine(ax=g.ax_marg_x)
sns.despine(ax=g.ax_marg_y)
But it doesn't contain any values or ticks. I have tried the solution proposed here but it just doesn't do anything.
Here is the plot given by the code

The axes of the marginal plots are 'shared' with the main plot. Default, they don't get tick labels. To turn the tick labels on again, tick_params has options such as labelleft=True and labelbottom=True.
When setting ticks for the histogram values, it can be handy to also set gridlines. The default number of gridlines might be too low, they can be increased with a tick locator. Also, the default linestyle might be too heavy. Linestyle, color and thickness can be adapted via grid()
import seaborn as sns; sns.set(style="ticks", color_codes=True)
import numpy as np
from matplotlib.ticker import MaxNLocator
tips = sns.load_dataset("tips")
g = sns.JointGrid(x="total_bill", y="tip", data=tips)
g = g.plot_joint(sns.scatterplot, color="m")
_ = g.ax_marg_x.hist(tips["total_bill"], color="b", alpha=.6,
bins=np.arange(0, 60, 5))
_ = g.ax_marg_y.hist(tips["tip"], color="r", alpha=.6,
orientation="horizontal",
bins=np.arange(0, 12, 1))
g.ax_marg_y.tick_params(labeltop=True)
g.ax_marg_y.grid(True, axis='x', ls=':')
g.ax_marg_y.xaxis.set_major_locator(MaxNLocator(4))
g.ax_marg_x.tick_params(labelleft=True)
g.ax_marg_x.grid(True, axis='y', ls=':')
g.ax_marg_x.yaxis.set_major_locator(MaxNLocator(4))

Related

How to share facetgrid x and y axis using seaborn

Running this below code produces seaborn facetgrid graphs.
merged1=merged[merged['TEST'].isin(['VL'])]
merged2=merged[merged['TEST'].isin(['CD4'])]
g = sns.relplot(data=merged1, x='Days Post-ART', y='Log of VL and CD4', col='PATIENT ID',col_wrap=4, kind="line", height=4, aspect=1.5,
color='b', facet_kws={'sharey':True,'sharex':True})
for patid, ax in g.axes_dict.items(): # axes_dict is new in seaborn 0.11.2
ax1 = ax.twinx()
sns.lineplot(data=merged2[merged2['PATIENT ID'] == patid], x='Days Post-ART', y='Log of VL and CD4', color='r')
I've used the facet_kws={'sharey':True, 'sharex':True} to share the x-axis and y-axis but it's not working properly. Can someone assist?
As stated in the comments, the FacetGrid axes are shared by default. However, the twinx axes are not. Also, the call to twinx seems to reset the default hiding of the y tick labels.
You can manually share the twinx axes, and remove the unwanted tick labels.
Here is some example code using the iris dataset:
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
iris = sns.load_dataset('iris')
g = sns.relplot(data=iris, x='petal_length', y='petal_width', col='species', col_wrap=2, kind="line",
height=4, aspect=1.5, color='b')
last_axes = np.append(g.axes.flat[g._col_wrap - 1::g._col_wrap], g.axes.flat[-1])
shared_right_y = None
for species, ax in g.axes_dict.items():
ax1 = ax.twinx()
if shared_right_y is None:
shared_right_y = ax1
else:
shared_right_y.get_shared_y_axes().join(shared_right_y, ax1)
sns.lineplot(data=iris[iris['species'] == species], x='petal_length', y='sepal_length', color='r', ax=ax1)
if not ax in last_axes: # remove tick labels from secondary axis
ax1.yaxis.set_tick_params(labelleft=False, labelright=False)
ax1.set_ylabel('')
if not ax in g._left_axes: # remove tick labels from primary axis
ax.yaxis.set_tick_params(labelleft=False, labelright=False)
plt.tight_layout()
plt.show()

How to put a colorbar in seaborn scatterplot legend

I have the next scatterplot
But i want to change the dots on the legend by continuos color map like this:
This is my code:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
sns.set_style("whitegrid")
gene_list = pd.read_csv('interseccion.csv', header=None)
glist = gene_list.squeeze().str.strip().tolist()
names = gp.get_library_name()
enr = gp.enrichr(gene_list= glist,
gene_sets=['KEGG_2019_Human'],
organism='Human', # don't forget to set organism to the one you desired! e.g. Yeast
description='KEGG',
# no_plot=True,
cutoff=0.5 # test dataset, use lower value from range(0,1)
)
resultados = enr.results.head(15)
resultados['-log10(FDR)'] = -np.log10(resultados['Adjusted P-value'])
resultados['Genes'] = resultados['Genes'].str.split(';')
resultados['Genes'] = resultados['Genes'].apply(lambda x: len(x))
g = sns.scatterplot(data=resultados, x="-log10(FDR)", y="Term", hue='-log10(FDR)', palette="seismic"
, size="Genes", sizes=(30, 300), legend=True)
g.legend(loc=6, bbox_to_anchor=(1, 0.5), ncol=1)
g.fig.colorbar()
plt.ylabel('')
plt.xlabel('-log10(FDR)')
When i try to put a color bar with the funcion plt.colorbar() is not possible
I customized the code in the official sample with the understanding that I wanted to add a legend and color bars to the Seaborn scatterplot. A colormap has been created to match the colors of the sample graph, but it can be drawn without problems by specifying the colormap name. The color bar is customized by getting its position and adjusting it manually in the legend. The height of the color bar is halved to match the legend.
import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
fig, ax = plt.subplots()
g = sns.scatterplot(
data=tips, x="total_bill", y="tip", hue="size", size="size",
sizes=(20, 200), legend="full", ax=ax)
g.legend(loc='upper right', bbox_to_anchor=(1.2, 1.0), ncol=1)
norm = plt.Normalize(tips['size'].min(), tips['size'].max())
cmap = sns.cubehelix_palette(light=1, as_cmap=True)
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
cax = fig.add_axes([ax.get_position().x1+0.05, ax.get_position().y0, 0.06, ax.get_position().height / 2])
ax.figure.colorbar(sm, cax=cax)
plt.show()

Remove Labels and Tick-marks from Colorbar in Matplotlib

I have a heatmap and I want to remove the labels and tickmarks on the colorbar. How can I do this with the heatmap I've made so far (code below)?
import seaborn as sns
import matplotlib.pyplot as plt
sns.heatmap(my_heatmap, cmap='RdYlGn', vmin=0, vmax=1)
plt.rcParams["figure.figsize"] = (8, 6)
plt.title('10 mm Precipitation Probabilities\nTopeka, Kansas', fontsize = 16)
plt.xlabel('X', fontsize = 14)
plt.ylabel('Y', fontsize = 14)
plt.text(6.7,.18, 'High Probability')
plt.show()
(I would rather it just say High Probability at the top of the bar as shown with the label I made).
You can access the colorbar via cbar = ax.collections[0].colorbar (see e.g. this post).
Then, you can change the ticks (cbar.set_ticks([])) or set new ticks and new tick labels:
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (8, 6)
my_heatmap = np.random.rand(10, 10)
ax = sns.heatmap(my_heatmap, cmap='RdYlGn', vmin=0, vmax=1)
# ax.get_figure().set_size_inches(8, 6)
ax.set_title('10 mm Precipitation Probabilities\nTopeka, Kansas', fontsize=16)
ax.set_xlabel('X', fontsize=14)
ax.set_ylabel('Y', fontsize=14)
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, 0.5, 1])
cbar.set_ticklabels(['Low\nProbability', 'Average\nProbability', 'High\nProbability'])
# cbar.set_label('Probability')
plt.tight_layout()
plt.show()
Note that plt.rcParams["figure.figsize"] doesn't change the size of the figure, but sets the default size for the next figure that will be created. So you need to call it before sns.heatmap which creates a new figure if none was created before. To change the size of an already-created figure, use set_size_inches().

How to plot a paired histogram using seaborn

I would like to make a paired histogram like the one shown here using the seaborn distplot.
This kind of plot can also be referred to as the back-to-back histogram shown here, or a bihistogram inverted/mirrored along the x-axis as discussed here.
Here is my code:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
green = np.random.normal(20,10,1000)
blue = np.random.poisson(60,1000)
fig, ax = plt.subplots(figsize=(8,6))
sns.distplot(blue, hist=True, kde=True, hist_kws={'edgecolor':'black'}, kde_kws={'linewidth':2}, bins=10, color='blue')
sns.distplot(green, hist=True, kde=True, hist_kws={'edgecolor':'black'}, kde_kws={'linewidth':2}, bins=10, color='green')
ax.set_xticks(np.arange(-20,121,20))
ax.set_yticks(np.arange(0.0,0.07,0.01))
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.show()
Here is the output:
When I use the method discussed here (plt.barh), I get the bar plot shown just below, which is not what I am looking for.
Or maybe I haven't understood the workaround well enough...
A simple/short implementation of python-seaborn-distplot similar to these kinds of plots would be perfect. I edited the figure of my first plot above to show the kind of plot I hope to achieve (though y-axis not upside down):
Any leads would be greatly appreciated.
You could use two subplots and invert the y-axis of the lower one and plot with the same bins.
df = pd.DataFrame({'a': np.random.normal(0,5,1000), 'b': np.random.normal(20,5,1000)})
fig =plt.figure(figsize=(5,5))
ax = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
bins = np.arange(-20,40)
ax.hist(df['a'], bins=bins)
ax2.hist(df['b'],color='orange', bins=bins)
ax2.invert_yaxis()
edit:
improvements suggested by #mwaskom
fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(5,5))
bins = np.arange(-20,40)
for ax, column, color, invert in zip(axes.ravel(), df.columns, ['teal', 'orange'], [False,True]):
ax.hist(df[column], bins=bins, color=color)
if invert:
ax.invert_yaxis()
plt.subplots_adjust(hspace=0)
Here is a possible approach using seaborn's displots.
Seaborn doesn't return the created graphical elements, but the ax can be interrogated. To make sure the ax only contains the elements you want upside down, those elements can be drawn first. Then, all the patches (the rectangular bars) and the lines (the curve for the kde) can be given their height in negative. Optionally the x-axis can be set at y == 0 using ax.spines['bottom'].set_position('zero').
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
green = np.random.normal(20, 10, 1000)
blue = np.random.poisson(60, 1000)
fig, ax = plt.subplots(figsize=(8, 6))
sns.distplot(green, hist=True, kde=True, hist_kws={'edgecolor': 'black'}, kde_kws={'linewidth': 2}, bins=10,
color='green')
for p in ax.patches: # turn the histogram upside down
p.set_height(-p.get_height())
for l in ax.lines: # turn the kde curve upside down
l.set_ydata(-l.get_ydata())
sns.distplot(blue, hist=True, kde=True, hist_kws={'edgecolor': 'black'}, kde_kws={'linewidth': 2}, bins=10,
color='blue')
ax.set_xticks(np.arange(-20, 121, 20))
ax.set_yticks(np.arange(0.0, 0.07, 0.01))
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
pos_ticks = np.array([t for t in ax.get_yticks() if t > 0])
ticks = np.concatenate([-pos_ticks[::-1], [0], pos_ticks])
ax.set_yticks(ticks)
ax.set_yticklabels([f'{abs(t):.2f}' for t in ticks])
ax.spines['bottom'].set_position('zero')
plt.show()

Change position of marginal axis in seaborn jointplot

Seaborn by default plots the marginal distributions on the top and right of the main plot. Is it possible to change this location (e.g., to bottom and left)?
A minimal example, using the seaborn documentation:
tips = sns.load_dataset("tips")
g = sns.jointplot(x="total_bill", y="tip", data=tips)
gives...
It is a bit tedious, but you can adapt this example to your needs. It uses a make_axes_locatable divider. Changing this from top to bottom and from right to left is no problem, but then you need to change the labelling and ticks on all axes.
import seaborn as sns
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
tips = sns.load_dataset("tips")
x = tips["total_bill"]
y = tips["tip"]
fig, axScatter = plt.subplots(figsize=(5.5, 5.5))
fig.subplots_adjust(.1,.1,.9,.9)
axScatter.scatter(x, y)
divider = make_axes_locatable(axScatter)
axHistx = divider.append_axes("bottom", 1.2, pad=0.1, sharex=axScatter)
axHisty = divider.append_axes("left", 1.2, pad=0.1, sharey=axScatter)
# make some labels invisible
axHistx.tick_params(labelbottom=False, bottom=False,
left=False, labelleft=False, right=True, labelright=True)
axHisty.tick_params(labelleft=False, left=False,
bottom=False, labelbottom=False, top=True, labeltop=True)
axHistx.invert_yaxis()
axHisty.invert_xaxis()
axScatter.xaxis.tick_top()
axScatter.yaxis.tick_right()
axScatter.xaxis.set_label_position('top')
axScatter.yaxis.set_label_position('right')
axScatter.set(xlabel="Total Bill", ylabel="Tip")
axHistx.hist(x, bins=16, density=True)
axHisty.hist(y, bins=16, density=True, orientation='horizontal')
plt.show()

Categories