customized matplotlib colorbar - python

colors = ['white', '#FFFFBB', '#C3FDB8', '#B5EAAA', '#64E986', '#54C571',
'#4AA02C','#347C17','#347235','#25383C','#254117']
I made a plot using matplotlib (similar to a heatmap)
I would like to either :
1) make a legend using the colors I defined in the list or
2) is there anyway of automating it in matplotlib to create as beautiful as an effect in R?
the normal matplotlib color gradient is too "sharp" looking...
Thanks!

Fairly simple using ListedColormap:
import matplotlib.cm as cm # color map
import matplotlib.gridspec as gridspec
import matplotlib as mpl
import numpy as np
#dummy data
hm = np.random.randint(0, 100, size=(5, 5))
#define colors
cmap = mpl.colors.ListedColormap(['white', '#FFFFBB', '#C3FDB8', '#B5EAAA', '#64E986', '#54C571',
'#4AA02C', '#347C17', '#347235', '#25383C', '#254117'])
#create plot frames
gs = gridspec.GridSpec(2,2, height_ratios=[6,2], width_ratios=[20,1],)
ax = plt.subplot(gs[0, 0])
#heatmap and colorbar
im = ax.pcolor(hm, cmap=cmap)
cbar = plt.colorbar(im, cax=plt.subplot(gs[1]))
plt.show()

Related

How to plot a density bar next to my density scatter plot? [duplicate]

I'm working with data that has the data has 3 plotting parameters: x,y,c. How do you create a custom color value for a scatter plot?
Extending this example I'm trying to do:
import matplotlib
import matplotlib.pyplot as plt
cm = matplotlib.cm.get_cmap('RdYlBu')
colors=[cm(1.*i/20) for i in range(20)]
xy = range(20)
plt.subplot(111)
colorlist=[colors[x/2] for x in xy] #actually some other non-linear relationship
plt.scatter(xy, xy, c=colorlist, s=35, vmin=0, vmax=20)
plt.colorbar()
plt.show()
but the result is TypeError: You must first set_array for mappable
From the matplotlib docs on scatter 1:
cmap is only used if c is an array of floats
So colorlist needs to be a list of floats rather than a list of tuples as you have it now.
plt.colorbar() wants a mappable object, like the CircleCollection that plt.scatter() returns.
vmin and vmax can then control the limits of your colorbar. Things outside vmin/vmax get the colors of the endpoints.
How does this work for you?
import matplotlib.pyplot as plt
cm = plt.cm.get_cmap('RdYlBu')
xy = range(20)
z = xy
sc = plt.scatter(xy, xy, c=z, vmin=0, vmax=20, s=35, cmap=cm)
plt.colorbar(sc)
plt.show()
Here is the OOP way of adding a colorbar:
fig, ax = plt.subplots()
im = ax.scatter(x, y, c=c)
fig.colorbar(im, ax=ax)
If you're looking to scatter by two variables and color by the third, Altair can be a great choice.
Creating the dataset
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
df = pd.DataFrame(40*np.random.randn(10, 3), columns=['A', 'B','C'])
Altair plot
from altair import *
Chart(df).mark_circle().encode(x='A',y='B', color='C').configure_cell(width=200, height=150)
Plot

Change color of violin plot in matplotlib according to how broad the distribution is

I have been trying to work on plotting a nice violin plot to present my data using Matplotlib library in Python. This is the code I have used:
ax.violinplot(vdistances,showmeans=False,showmedians=True)
ax.set_title('Distance analysis for molecule 1')
ax.set_xlabel('Atomic distances')
ax.set_ylabel('Distances in Amstrongs')
ax.set_xticks([x for x in range(1,len(distances)+1)])
plt.show()
And this is what I have come up with:
What I have been wondering is if it is possible to assign different tones of the same color to each of the violins depending on how broad the distribution is, and so the more disperse the data is.
You could loop through the generated violins, extract their height and use that to set a color:
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
from matplotlib.cm import ScalarMappable
import numpy as np
fig, ax = plt.subplots(figsize=(12, 5))
vdistances = np.random.normal(np.random.uniform(10, 20, (20, 10)), np.random.uniform(2, 5, (20, 10)))
violins = ax.violinplot(vdistances, showmeans=False, showmedians=True)
ax.xaxis.set_major_locator(MultipleLocator(1))
heights = [violin.get_paths()[0].get_extents().height for violin in violins['bodies']]
norm = plt.Normalize(min(heights), max(heights))
cmap = plt.get_cmap('plasma')
for violin, height in zip(violins['bodies'], heights):
violin.set_color(cmap(norm(height)))
violin.set_alpha(0.5)
plt.colorbar(ScalarMappable(norm=norm, cmap=cmap), alpha=violin.get_alpha(), label='Violin Extent', ax=ax)
plt.tight_layout()
plt.show()

How to correct subplot image size with colorbars in matplotlib python?

I want to make a 3x2 subplot image in python. With the images in third row I have added a colorbar. But it the image size gets small as compared to the top rows. Is there anyway to fix the image size the same as of top two rows while having a colorbar in the third row?
Here's my python code
#Imports
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib.image as image
import matplotlib.colors
from matplotlib.colors import ListedColormap
#data
bird = image.imread('Desktop/bird.jpeg')
fig, (ax1, ax2, ax3) = plt.subplots(3,2,figsize=(5,5))
ax1[0].imshow(bird)
ax1[0].set_ylabel('Row 1', size=8)
ax1[0].set_yticks([]) #display no ticks
ax1[0].set_xticks([])
ax1[1].imshow(bird)
ax1[1].set_yticks([])
ax1[1].set_xticks([])
ax2[0].imshow(bird)
ax2[0].set_yticks([])
ax2[0].set_xticks([])
ax2[0].set_ylabel('Row 2', size=8)
ax2[1].imshow(bird)
ax2[1].set_yticks([])
ax2[1].set_xticks([])
#Generating Color Map
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", ["Red","Green","Blue"])
# Right Image
bird_3 = ax3[1].imshow(bird, cmap = cmap)
ax3[1].set_yticks([])
ax3[1].set_xticks([])
cbar_int = fig.colorbar(bird_3,orientation='horizontal', ax=ax3[1])
cbar_int.set_label('CBar', size=8, rotation=0)
cbar_int.ax.tick_params(labelsize=8)
bird_3.set_clim(vmin=-1, vmax=1)
# Left Image
bird_4 = ax3[0].imshow(bird, cmap = cmap)
ax3[0].set_yticks([])
ax3[0].set_xticks([])
ax3[0].set_ylabel('Row 3', size=8)
cbar_int = fig.colorbar(bird_4,orientation='horizontal', ax=ax3[0])
cbar_int.set_label('CBar', size=8, rotation=0)
cbar_int.ax.tick_params(labelsize=8)
bird_3.set_clim(vmin=-1, vmax=1)
plt.show()
The following results I get with it. You see row 3 images are small compared to row 1 and 2.
Matplotlib steals space from the host axes. However, you can specify more than one axes to steal space from. So above you can easily do:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
fig, axs = plt.subplots(3, 2)
for ax in axs.flat:
pc = ax.imshow(np.random.randn(20,40))
fig.colorbar(pc, ax=axs[:, 1], orientation='horizontal')
fig.colorbar(pc, ax=axs[:, 0], orientation='horizontal')
plt.show()
and space is stolen from all three axes in each column.
You can also specify constrained_layout=True for slightly better layout.
Note that with imshow the axes have a fixed aspect ratio, so there is always going to be issues with white space.

Set transparency (alpha) of matplotlib 3d grid

I would like to change the transparency of the grid in matplotlib 3d plot.
But I find that it is not as easy as in 2d, which is simply plt.grid(alpha=0.2).
Here I give a mini code
import numpy as np
import matplotlib.pyplot as plt
data = np.random.randn(3, 100)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.scatter(data[0], data[1], data[2])
# How to change the grid transparency?
plt.show()
How to set the transparency of the x,y,z-grids?
I have tried:
Using ax.zaxis._axinfo['grid'].update({"alpha": 0.1}). But it appears that it does not have the key alpha.
I checked the source code of ax.grid() here in github. From the comments, it seems that the alpha functionality is not implemented for 3d case at all.
plt.grid does not seem to do anything for 3d plots. But you can set the color as a RGB+Alpha tuple using rcparams:
import numpy as np
import matplotlib.pyplot as plt
# fourth parameter is alpha=0.1
plt.rcParams['grid.color'] = (0.5, 0.5, 0.5, 0.1)
data = np.random.randn(3, 100)
fig = plt.figure()
ax = plt.axes(projection ="3d")
ax.scatter(data[0], data[1], data[2])
plt.show()
Result:

Matplotlib - draw several plots with different color shade

I am pretty much a beginner in using python's matplotlib library.
I have ten plots to be drawn in the same figure, using matplotlib.pyplot.plot assigns. I would like to pick the colors from a ranger "shorter" than the default one, for example "around the red" (like from reddish purple to orange). Is it possible? How can I do it in python?
I also found this https://matplotlib.org/examples/color/colormaps_reference.html, but it seems quite useless to me.
Thanks for answering
EDIT: to better clarify what I need, I am looking for a way to communicate to the "plt.plot" function that I want it to iterate over a different set of colors
If you want to create a color ramp you can do the following. Using https://matplotlib.org/3.2.1/tutorials/colors/colormap-manipulation.html as a reference:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
def plot_examples(colormaps):
"""
Helper function to plot data with associated colormap.
"""
np.random.seed(19680801)
data = np.random.randn(30, 30)
n = len(colormaps)
fig, axs = plt.subplots(1, n, figsize=(n * 2 + 2, 3),
constrained_layout=True, squeeze=False)
for [ax, cmap] in zip(axs.flat, colormaps):
psm = ax.pcolormesh(data, cmap=cmap, rasterized=True, vmin=-4, vmax=4)
fig.colorbar(psm, ax=ax)
plt.show()
colors = ["purple", "red"]
cmap1 = LinearSegmentedColormap.from_list("mycmap", colors)
plot_examples([cmap1])
You can also use the colormap to get values for a normal plot:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# Creating the colar map
colors = ["purple", "red"]
cmap1 = LinearSegmentedColormap.from_list("mycmap", colors)
# Data used in plot
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
plt.plot(t, s, color=cmap1(0.1))
plt.show()
Here you can change the 0.1 in the second to last line to choose where on the colormap you want to query (0-255).

Categories