Facetgrid: how to space the xticks - python

I have several histograms that I need to plot with seaborn / facetgrid. They each have their own different x/y axis scales. I need to control the space between the ticks, so as to make it readable (right now they are all overlapping with each other). It won't help to force set the ticks, as each histogram has it's own scale. Here is my current code:
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.set(style="ticks")
g = sns.FacetGrid(test, col="someCol", sharex=False, sharey=False)
g.map(plt.hist, "someVal")
And this is what my histograms look like so far:

You can rotate the ticks using this command :
ax.tick_params(axis='x', rotation = 90, labelsize = 20)

Related

fixing the y scale in python matplotlib

I want to draw multiple bar plots with the same y-scale, and so I need the y-scale to be consistent.
For this, I tried using ylim() after yscale()
plt.yscale("log")
plt.ylim(top=2000)
plt.show()
However, python keeps autoscaling the intermittent values depending on my data.
Is there a way to fix this?
overlayed graphs
import numpy as np
import matplotlib.pyplot as plt
xaxis = np.arange(10)
yaxis = np.random.rand(10)*100
fig = plt.subplots(figsize =(10, 7))
plt.bar(xaxis, yaxis, width=0.8, align='center', color='y')
# show graph
plt.yscale("log")
plt.ylim(top=2000)
plt.show()
You can set the y-axis tick labels manually. See yticks for an example. In your case, you will have to do this for each plot to have consistent axes.

Colorbar for sns.jointplot "kde"-style on the side

I'm trying to plot a colorbar next to my density plot with marginal axes.
It does plot the colorbar, but unfortunately not on the side.
That's what a tried so far:
sns.jointplot(x,y, data=df3, kind="kde", color="skyblue", legend=True, cbar=True,
xlim=[-10,40], ylim=[900,1040])
It looks like this:
I also tried this:
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
kdeplot = sns.jointplot(x=tumg, y=pumg, kind="kde")
plt.subplots_adjust(left=0.2, right=0.8, top=0.8, bottom=0.2)
cbar_ax = kdeplot.fig.add_axes([.85, .25, .05, .4])
plt.colorbar(cax=cbar_ax)
plt.show()
But with the second option I'm getting a runtime error:
No mappable was found to use for colorbar creation.
First define a mappable such as an image (with imshow) or a contour set (with contourf).
Does anyone have an idea how to solve the problem?
There only seems to be information for a colorbar when effectively creating the colorbar.
So, an idea is to combine both approaches: add a colorbar via kdeplot, and then move it to the desired location. This will leave the main joint plot with insufficient width, so its width also should be adapted:
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
# create some dummy data: gaussian multivariate with 10 centers with each 1000 points
tumg = np.random.normal(np.tile(np.random.uniform(10, 20, 10), 1000), 2)
pumg = np.random.normal(np.tile(np.random.uniform(10, 20, 10), 1000), 2)
kdeplot = sns.jointplot(x=tumg, y=pumg, kind="kde", cbar=True)
plt.subplots_adjust(left=0.1, right=0.8, top=0.9, bottom=0.1)
# get the current positions of the joint ax and the ax for the marginal x
pos_joint_ax = kdeplot.ax_joint.get_position()
pos_marg_x_ax = kdeplot.ax_marg_x.get_position()
# reposition the joint ax so it has the same width as the marginal x ax
kdeplot.ax_joint.set_position([pos_joint_ax.x0, pos_joint_ax.y0, pos_marg_x_ax.width, pos_joint_ax.height])
# reposition the colorbar using new x positions and y positions of the joint ax
kdeplot.fig.axes[-1].set_position([.83, pos_joint_ax.y0, .07, pos_joint_ax.height])
plt.show()

How to have the axis ticks in both top and bottom, left and right of a heatmap

I am trying to draw a big heatmap with sns.heatmap function. However, since the map is too big, it's a little hard to find the xtick label or ytick label with corresponding rows and columns. Can I add the xtick and xlabels also on the top and ytick and ylabels also on the right??
I have tried many different ways. But they all didn't work.
The usual way would be via tick_params, which has the labelrotation parameter, and accepts rotation:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(0)
import seaborn as sns
uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data)
ax.tick_params(right=True, top=True, labelright=True, labeltop=True, labelrotation=0)
plt.show()
Without labelrotation=0 or rotation=0
Axis ticks for all sides can be placed using tick_params from matplotlib
#Get sample correlation data to plot something. 'data' is a dataframe
corr=data.corr()
#Create Heatmap
axr = sns.heatmap(corr,cmap="coolwarm", annot=True, linewidths=.5,cbar=False)
#Set all sides
axr.tick_params(right=True, top=True, labelright=True, labeltop=True,rotation=0)
#Rotate X ticks
plt.xticks(rotation='vertical')

Matplotlib - imshow twiny() problems

I am trying to have two inter-depedent x-axis in a matplotlib imshow() plot. I have bottom x-axis as the radius squared and I want the top as just the radius. I have tried so far:
ax8 = ax7.twiny()
ax8._sharex = ax7
fmtr = FuncFormatter(lambda x,pos: np.sqrt(x) )
ax8.xaxis.set_major_formatter(fmtr)
ax8.set_xlabel("Radius [m]")
where ax7 is the y-axis and the bottom x-axis (or radius squared). Instead of getting the sqrt (x_bottom) as the ticks at the top I just get a range from 0 to 1. How can I fix this?
Thanks a lot in advance.
You're misunderstanding what twiny does. It makes a completely independent x-axis with a shared y-axis.
What you want to do is have a different formatter with a linked axis (i.e. sharing the axis limits but nothing else).
The simple way to do this is to manually set the axis limits for the twinned axis:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
fig, ax1 = plt.subplots()
ax1.plot(range(10))
ax2 = ax1.twiny()
formatter = FuncFormatter(lambda x, pos: '{:0.2f}'.format(np.sqrt(x)))
ax2.xaxis.set_major_formatter(formatter)
ax2.set_xlim(ax1.get_xlim())
plt.show()
However, as soon as you zoom or interact with the plot, you'll notice that the axes are unlinked.
You could add an axes in the same position with both shared x and y axes, but then the tick formatters are shared, as well.
Therefore, the easiest way to do this is using a parasite axes.
As a quick example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
from mpl_toolkits.axes_grid1.parasite_axes import SubplotHost
fig = plt.figure()
ax1 = SubplotHost(fig, 1,1,1)
fig.add_subplot(ax1)
ax2 = ax1.twin()
ax1.plot(range(10))
formatter = FuncFormatter(lambda x, pos: '{:0.2f}'.format(np.sqrt(x)))
ax2.xaxis.set_major_formatter(formatter)
plt.show()
Both this and the previous plot will look identical at first. The difference will become apparent when you interact (e.g. zoom/pan) with the plot.

how to turn on minor ticks only on y axis matplotlib

How can I turn the minor ticks only on y axis on a linear vs linear plot?
When I use the function minor_ticks_on to turn minor ticks on, they appear on both x and y axis.
Nevermind, I figured it out.
ax.tick_params(axis='x', which='minor', bottom=False)
Here's another way I found in the matplotlib documentation:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import MultipleLocator
a = np.arange(100)
ml = MultipleLocator(5)
plt.plot(a)
plt.axes().yaxis.set_minor_locator(ml)
plt.show()
This will place minor ticks on only the y-axis, since minor ticks are off by default.
To clarify the procedure of #emad's answer, the steps to show minor ticks at default locations are:
Turn on minor ticks for an axes object, so locations are initialized as Matplotlib sees fit.
Turn off minor ticks that are not desired.
A minimal example:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
plt.plot([1,2])
# Currently, there are no minor ticks,
# so trying to make them visible would have no effect
ax.yaxis.get_ticklocs(minor=True) # []
# Initialize minor ticks
ax.minorticks_on()
# Now minor ticks exist and are turned on for both axes
# Turn off x-axis minor ticks
ax.xaxis.set_tick_params(which='minor', bottom=False)
Alternative Method
Alternatively, we can get minor ticks at default locations using AutoMinorLocator:
import matplotlib.pyplot as plt
import matplotlib.ticker as tck
fig, ax = plt.subplots()
plt.plot([1,2])
ax.yaxis.set_minor_locator(tck.AutoMinorLocator())
Result
Either way, the resulting plot has minor ticks on the y-axis only.
To set minor ticks at custom locations:
ax.set_xticks([0, 10, 20, 30], minor=True)
Also, if you only want minor ticks on the actual y-axis, rather than on both the left and right-hand sides of the graph, you can follow the plt.axes().yaxis.set_minor_locator(ml) with plt.axes().yaxis.set_tick_params(which='minor', right = 'off'), like so:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import MultipleLocator
a = np.arange(100)
ml = MultipleLocator(5)
plt.plot(a)
plt.axes().yaxis.set_minor_locator(ml)
plt.axes().yaxis.set_tick_params(which='minor', right = 'off')
plt.show()
The following snippets should help:
from matplotlib.ticker import MultipleLocator
ax.xaxis.set_minor_locator(MultipleLocator(#))
ax.yaxis.set_minor_locator(MultipleLocator(#))
# refers to the desired interval between minor ticks.

Categories