Matplotlib: displaying only unique labels for the legend - python

Let's say I have an array of X (X.shape = [N, 2]) and labels (labels.shape = N).
I want to produce a scatter of X[:,0], X[:,1], color corresponding to the label, and only the unique labels displayed.
Code:
import numpy as np
from numpy.random import rand
import matplotlib
from matplotlib import pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set(context='poster', style='dark')
X = rand(500)
Y = rand(500)
labels = np.round(rand(500)*4).astype(int)
print(np.unique(labels)) # array([0, 1, 2, 3, 4])
plt.scatter(X, Y, c=labels, cmap='rainbow') # this does what I want minus the labels
plt.scatter(X, Y, c=labels, cmap='rainbow', label=labels)
plt.legend(loc='best') # this produces 500 labels instead of 5

You could plot each label individually. You need to choose its color from the cmap, which you need to normalize to your labels first.
import numpy as np
from numpy.random import rand
import matplotlib.pyplot as plt
from matplotlib import cm, colors
%matplotlib inline
import seaborn as sns
sns.set(context='poster', style='dark')
X = rand(500)
Y = rand(500)
labels = np.round(rand(500)*4).astype(int)
unique_labels=np.unique(labels) # array([0, 1, 2, 3, 4])
norm = colors.Normalize(vmin=unique_labels[0], vmax=unique_labels[-1])
m = cm.ScalarMappable(norm=norm, cmap=cm.rainbow)
for label in np.unique(labels):
color = m.to_rgba(label)
plt.scatter(X[labels==label], Y[labels==label], c=color, label=label)
plt.legend(loc='best')
produces this (without seaborn, as I don't have that installed, but you get the idea):

Related

Seaborn viridis with white background

I have some simple to code create a hex plot with Seaborn. I want to use the viridis color palette but I want it to be white where the density is 0. Is this possible? I would like the block of purple below to be white/not visible.
g = sns.jointplot(x =depth, y = abs(depth-med), kind="hex", joint_kws={"color":'White', 'cmap':'viridis'})
sns.set_style("whitegrid")
You can set vmin for the normalization to a value below 1 and set the clipped data points to white:
import matplotlib.pyplot as plt
from matplotlib import cm
import seaborn as sns
my_viridis = cm.get_cmap("viridis", 1024).with_extremes(under="white")
penguins = sns.load_dataset("penguins")
sns.jointplot(data=penguins, x="bill_length_mm", y="bill_depth_mm", kind="hex", joint_kws={"color":'White', "camp": my_viridis, "vmin": 0.1})
plt.show()
Sample output:
Alternatively, we can change the specific value for zero of the colormap:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm, colors
import seaborn as sns
dummy = cm.get_cmap("viridis")
dummy2 = dummy(np.linspace(0, 1, 1024))
dummy2[0] = np.asarray([1, 1, 1, 1])
#or you can set zero to transparent with
#dummy2[0] = np.asarray([1, 1, 1, 0])
my_viridis = colors.ListedColormap(dummy2)
penguins = sns.load_dataset("penguins")
sns.jointplot(data=penguins, x="bill_length_mm", y="bill_depth_mm", kind="hex", joint_kws={"color":'White', "cmap": my_viridis})
plt.show()

Isometric orientation for heatmap with matplotlib

Assume we have a heat-map as below
construct using the code
import string
import numpy as np
from matplotlib import pyplot as plt
label=list(string.ascii_uppercase)
mdata = np.random.randn(3, len(label), len(label))
data = mdata[0, :, :]
data=np.tril(data,-1)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)
plt.show()
Is possible whether using Matplotlib, Seaborn or any other package to render into isometric
alignment as below.
With matplotlib's 3D toolkit, and using numpy's triu_indices, you could create a bar plot from the triangular matrix:
import numpy as np
import matplotlib.pyplot as plt
ax = plt.figure().add_subplot(projection='3d')
N = 26
data = np.random.randn(3, N, N)
for i, (plane, cmap) in enumerate(zip(data, ['Reds', 'Greens', 'Blues'])):
indices = np.triu_indices(N, 1)
norm = plt.Normalize(plane.min(), plane.max())
ax.bar(left=indices[0], bottom=indices[1], height=0.9,
zs=i, zdir='y',
color=plt.get_cmap(cmap)(norm(plane[indices])))
plt.show()
PS: To have full rectangles, the sub-arrays from np.indices need to be made 1D:
import numpy as np
import matplotlib.pyplot as plt
ax = plt.figure().add_subplot(projection='3d')
N = 26
data = np.random.randn(3, N, N)
for i, (plane, cmap) in enumerate(zip(data, ['Reds', 'Greens', 'Blues'])):
indices = np.indices((N,N))
norm = plt.Normalize(plane.min(), plane.max())
ax.bar(left=indices[0].ravel(), bottom=indices[1].ravel(), height=0.9,
zs=i, zdir='y',
color=plt.get_cmap(cmap)(norm(plane).ravel()))
plt.show()

Plotting bar charts with a colormap legend

Consider the following:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
plot = plt.scatter(y, y, c = y, cmap = 'hsv')
plt.clf()
plt.colorbar(plot)
plt.bar(range(len(y)), y, color = colors)
plt.show()
I want to colormap legend to appear on the top right of the graph (much smaller of course). My image at the moment looks rather clunky as the colormap is clashing somewhat with the actual bars.
Thanks.
Following this answer:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
fig, ax = plt.subplots()
plot = ax.scatter(y, y, c = y, cmap = 'hsv')
plt.cla()
ax.bar(range(len(y)), y, color = colors)
cbaxes = inset_axes(ax, width="30%", height="3%", loc=2)
plt.colorbar(plot, cax=cbaxes, orientation='horizontal', ticks=[0,2,4,6,8,10])
I use plt.subplots to easily reference the Axes (ax). You can move the color bar and change its size by editing the last 2 lines (for instance changing loc can set which corner you want the colorbar to be in).

Seaborn: stripplot x-log scale collapses values

Hi I am trying to use stripplot in seaborn with log scale for the x-axis. It seems that the path I have taken does not work as intended. I would appreciate if someone could help me with that.
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
x = np.logspace(-8, -2, 10)
y = np.linspace(0, 100, 10)
sns.stripplot(x,y)
plt.gca().set_xscale('log')
all the xvalues are collapsed on the right edge of the plot (see plot). I works fine if I set the y-axis to be log.
PS: I would also need to restrict the number of x tick labels.
Thanks.
A scatter plot on a log scale using pyplot.scatter:
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
x = np.logspace(-8, -2, 10)
y = np.linspace(0, 100, 10)
c = np.random.rand(10)
s = 20+np.random.rand(10)*40
plt.scatter(x,y, c=c, s=s, cmap="jet")
plt.gca().set_xscale('log')
plt.xlim(5e-9, 5e-2)
plt.show()
The same scatter plot on a linear scale:
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
x = np.logspace(-8, -2, 10)
y = np.linspace(0, 100, 10)
c = np.random.rand(10)
s = 20+np.random.rand(10)*40
plt.scatter(x,y, c=c, s=s, cmap="jet")
plt.xlim(-0.003, 0.012)
plt.show()

Defining colors of Matplotlib 3D bar plot

I can't figure out the right way to set a cmap (or colors) for a 3d bar plot in matplotlib in my iPython notebook. I can setup my chart correctly (28 x 7 labels) in the X and Y plane, with some random Z values. The graph is hard to interpret, and one reason is that the default colors for the x_data labels [1,2,3,4,5] are all the same.
Here is the code:
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as npfig = plt.figure(figsize=(18,12))
ax = fig.add_subplot(111, projection='3d')
x_data, y_data = np.meshgrid(np.arange(5),np.arange(3))
z_data = np.random.rand(3,5).flatten()
ax.bar3d(x_data.flatten(),
y_data.flatten(),np.zeros(len(z_data)),1,1,z_data,alpha=0.10)
Which produces the following chart:
I don't want to define the colors manually for the labels x_data. How can I set up different 'random' cmap colors for each of the labels in x_data, still keeping the
ax.bar3d
parameter? Below is a variation using
ax.bar
and different colors, but what I need is ax.bar3d.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(18,12))
ax = fig.add_subplot(111, projection='3d')
x_data, y_data = np.meshgrid(np.arange(5),np.arange(3))
z_data = np.random.rand(3,5)
colors = ['r','g','b'] # colors for every line of y
# plot colored 3d bars
for i in xrange(3): # cycle though y
# I multiply one color by len of x (it is 5) to set one color for y line
ax.bar3d(x_data[i], y_data[i], z_data[i], 1, 1, z_data[i], alpha=0.1, color=colors[i]*5)
# or use random colors
# ax.bar3d(x_data[i], y_data[i], z_data[i], 1, 1, z_data[i], alpha=0.1, color=[np.random.rand(3,1),]*5)
plt.show()
Result:

Categories

Resources