Set a minimum tile size for seaborn heatmap - python

Using seaborn and matplotlib.pyplot in python is there a way to enforce a minimum/maximum size for the tiles in a heatmap?
I want to show the annotated values inside the tiles, but for more than a 9-10 samples the tiles become too small for the text. I dont want to set a fixed larger figure size to increase the tile size, since its not a one-time graph and I dont know how many samples will need to be displayed each time.
#graph plotting part
rcParams.update({"figure.constrained_layout.use": True})
ax = seaborn.heatmap(plotdata, cmap=seaborn.color_palette("flare", as_cmap=True), annot=True, linewidths=.5, fmt=".2f")
plt.show(ax)
Leads to:

Related

Is it possible to automatically scale the figure size, but keep the plot size constant in matplotlib?

I am using matplotlib to create multiple bar plots using the following code:
fig = plt.figure(figsize=(4, 4))
plt.barh(y=y, width=width, height=0.5)
plt.yticks(y, labels)
plt.xlabel("Contribution")
plt.tight_layout()
plt.show()
Since the length of my y-ticks labels can vary, the plot can get squeezed together as in the case below:
In other cases the plot looks fine:
Now, I was wondering, if there is an option in matplotlib to keep the plot size constant, but scale the figure size automatically (in horizontal direction)? My goal is that the plot size stays always the same, independent of the y-label length (because they vary inbetween plots). Thank you!

Use color intensities instead of bubble size for weighted scatter plot

Is there any way that we can use color intensities instead of bubble size for a weighted scatter plot? I have been searching for solutions online for hours, but I still did not find one. I use the following Penguins data for illustration.
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
penguins_data="https://raw.githubusercontent.com/datavizpyr/data/master/palmer_penguin_species.tsv"
penguins_df = pd.read_csv(penguins_data, sep="\t")
sns.set_context("talk", font_scale=1.1)
plt.figure(figsize=(10,6))
sns.scatterplot(x="culmen_length_mm",
y="culmen_depth_mm",
size="body_mass_g",
sizes=(20,500),
alpha=0.5,
data=penguins_df)
# Put the legend out of the figure
plt.legend(bbox_to_anchor=(1.01, 1),borderaxespad=0)
# Put the legend out of the figure
#plt.legend(bbox_to_anchor=(1.01, 0.54), borderaxespad=0.)
plt.xlabel("Culmen Length (mm)")
plt.ylabel("Culmen Depth (mm)")
plt.title("Bubble plot in Seaborn")
plt.tight_layout()
plt.savefig("Bubble_plot_size_range_Seaborn_scatterplot.png",
format='png',dpi=150)
The bubble plot with the smallest bubble corresponding to the smallest body mass and the biggest bubble corresponds to the largest body mass. However, I need the color intensity for the weighted scatter plot. For example, a darker color indicates that it occurs more frequently, and a lighter color indicates that it occurs less frequently. Any suggestion using Stata (preferred), Python, or R is highly appreciated.
I found something in Stata like this one, but my data structure is completely different, so it does not work out.
Have you considered creating a new column in your dataframe for the color, where you adjust the alpha channel by yourself?
After that you can probably work from this question to use it as the color column as the hue for the markers.

Plot 2D data with xarray (pcolormesh) while keeping aspect ratio

I am trying to plot a 2D data set using xarray (which uses matplotlib.pcolormesh) while keeping the natural aspect ratio of the data.
Example:
import xarray as xr
import matplotlib.pyplot as plt
plt.close('all')
data = xr.DataArray(np.random.randn(2, 3), dims=('x', 'y'),coords={'x': [10, 20],'y' : [0,50,100]})
data.plot() # Will produce a square plot
The result is
Adding a plt.gca().set_aspect('equal') does scale the plot in the way I want, however, the height of the colorbar is unchanged yielding
Using the parameters size, aspect, or figsize does not help either.
For the above example:
data.plot(size=6, aspect=150 / 30. * 6)
(or with the same result data.plot(figsize=(150 / 30. * 6,6)))
which is better but still off (maybe due to the colorbar?).
Both the size/aspect as well as the figsize arguments affect the size of the figure, not of the axes.
The aspect ratio of the axes is somewhat influenced by those arguments but difficult to control exactly. For instance, as you noted, the colorbar will also take up some space so that the width left for the axes is less.
I would recommend the following:
ax = data.plot(figsize=(18, 2))
# Alternatively
# ax = data.plot(size=2, aspect=9)
ax.axes.set_aspect('equal')
The second line ensures that the axes have the correct aspect ratio (just as in your first attempt).
If you do not additionally specify a figure size, the it will be determined from default parameters. The problem is that the default figure size does not fit very well with your actual data aspect ratio. Therefore the axes will have to be very small in order to fit into the default width.
You can solve this by providing a figure size that roughly matches your data aspect ratio (which is in your case 7.5).
To me, it looks best if you choose the figure aspect ratio a bit larger than the data aspect ratio to give the colorbar some space.

matplotlib - change figsize but keep fontsize constant

I want to display several figures with different sizes, making sure that the text has always the same size when the figures are printed. How can I achieve that?
As an example. Let's say I have two figures:
import matplotlib.pylab as plt
import matplotlib as mpl
mpl.rc('font', size=10)
fig1 = plt.figure(figsize = (3,1))
plt.title('This is fig1')
plt.plot(range(0,10),range(0,10))
plt.show()
mpl.rc('font', size=?)
fig2 = plt.figure(figsize = (20,10))
plt.title('This is fig2')
plt.plot(range(0,10),range(0,10))
plt.show()
How can I set the fontsize in such way that when printed the title and axis ticklabels in fig1 will have the same size as those in fig2?
In this case, the font size would be the same (i.e. also 10 points).
However, in Jupyter Notebook the figures may be displayed at a different size if they are too wide, see below:
Note that font size in points has a linear scale, so if you would want the size of the letters to be exactly twice as big, you would need to enter exactly twice the size in points (e.g. 20pt). That way, if you expect to print the second figure at 50% of the original size (length and width, not area), the fonts would be the same size.
But if the only purpose of this script is to make figures to then print, you would do best to set the size as desired (on paper or on screen), and then make the font size equal. You could then paste them in a document at that exact size or ratio and the fonts would indeed be the same size.
As noted by tcaswell, bbox_inches='tight' effectively changes the size of the saved figure, so that the size is different from what you set as figsize. As this might crop more whitespaces from some figures than others, the relative sizes of objects and fonts could end up being different for a given aspect ratio.

Matplotlib: Constrain plot width while allowing flexible height

What I would like to achive are plots with equal scale aspect ratio, and fixed width, but a dynamically chosen height.
To make this more concrete, consider the following plotting example:
import matplotlib as mpl
import matplotlib.pyplot as plt
def example_figure(slope):
# Create a new figure
fig = plt.figure()
ax = fig.add_subplot(111)
# Set axes to equal aspect ratio
ax.set_aspect('equal')
# Plot a line with a given slope,
# starting from the origin
ax.plot([x * slope for x in range(5)])
# Output the result
return fig
This example code will result in figures of different widths, depending on the data:
example_figure(1).show()
example_figure(2).show()
Matplotlib seems to fit the plots into a certain height, and then chooses the width to accomodate the aspect ratio. The ideal outcome for me would be the opposite -- the two plots above would have the same width, but the second plot would be twice as tall as the first.
Bonus — Difficulty level: Gridspec
In the long run, I would like to create a grid in which one of the plots has a fixed aspect ratio, and I would again like to align the graphs exactly.
# Create a 2x1 grid
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(2, 1)
# Create the overall graphic, containing
# the top and bottom figures
fig = plt.figure()
ax1 = fig.add_subplot(gs[0, :], aspect='equal')
ax2 = fig.add_subplot(gs[1, :])
# Plot the lines as before
ax1.plot(range(5))
ax2.plot(range(5))
# Show the figure
fig.show()
The result is this:
So again, my question is: How does one create graphs that vary flexibly in height depending on the data, while having a fixed width?
Two points to avoid potential misunderstandings:
In the above example, both graphs have the same x-axis. This cannot be
taken for granted.
I am aware of the height_ratios option in the gridspec. I can compute
the dimensions of the data, and set the ratios, but this unfortunately
does not control the graphs directly, but rather their bounding boxes,
so (depending on the axis labels), graphs of different widths still occur.
Ideally, the plots' canvas would be aligned exactly.
Another unsolved question is similar, but slightly more convoluted.
Any ideas and suggestions are very welcome, and I'm happy to specify the question further, if required. Thank you very much for considering this!
Have you tried to fix the width with fig.set_figwidth()?

Categories

Resources