Seaborn viridis with white background - python

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()

Related

Change boxplot color for boxplot displayed by categories

This is my code and I have tried most functions to change the color and shape of my boxes but nothing seems to work .
Try the palette option:
https://seaborn.pydata.org/generated/seaborn.boxplot.html
import seaborn as sns
import matplotlib.pyplot as plt
df = sns.load_dataset('diamonds')
sns.boxplot(x=df["clarity"], y=df["price"], palette="Reds", showfliers = False)
plt.show()
It's a bit more complicated to use pandas + matplotlib, you have to set the face colors of the boxes:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
df = pd.DataFrame({'Age':np.random.uniform(0,1,20),
'family_history':np.repeat(["No","Yes"],10)})
fig, ax = plt.subplots(1, 1)
bplot = df.boxplot(column="Age",by="family_history",vert=False,
patch_artist=True,return_type='both',ax=ax)
colors = ['lightblue', 'lightgreen']
for patch, color in zip(bplot[0][1]['boxes'], colors):
patch.set_facecolor(color)
Or you can use seaborn:
sns.boxplot(data = df,x = "Age",y="family_history",hue="family_history")

How to color swarmplot dots depending on quartile?

I would like to create a plot where dots are overlaid depending on whether or not they are within the 1st-3rd quartiles in seaborn. What function to use?
Something similar to the figure:
The following code creates a Seaborn swarmplot and then recolors the dots depending on their quartile. Looping through the collections created by the swarmplot, the y-data are retrieved. np.percentile calculates the borders of the quartiles and np.digitize calculates the corresponding quartiles. These quartiles can be used to define the color.
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from matplotlib.colors import ListedColormap
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
# cmap = plt.get_cmap('tab10')
cmap = ListedColormap(['gold', 'crimson', 'teal', 'orange'])
ax = sns.swarmplot(x="day", y="total_bill", data=tips)
for col in ax.collections:
y = col.get_offsets()[:,1]
perc = np.percentile(y, [25, 50, 75])
col.set_cmap(cmap)
col.set_array(np.digitize(y, perc))
plt.show()
The same approach can be used for a stripplot (optionally without jitter) to create a plot similar to the one in the question.
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from matplotlib.colors import ListedColormap
sns.set(style="whitegrid")
N = 200
x = np.repeat(list('abcdefg'), N)
y = np.random.normal(np.repeat(np.random.uniform(11, 15, 7), N), 1)
cmap = ListedColormap(['grey', 'turquoise', 'grey'])
ax = sns.stripplot(x=x, y=y, jitter=False, alpha=0.2)
for col in ax.collections:
y = col.get_offsets()[:, 1]
perc = np.percentile(y, [25, 75])
col.set_cmap(cmap)
col.set_array(np.digitize(y, perc))
plt.show()

matplotlib color gradient between two colors

I want a color gradient between black and red in matplotlib, where the low values are black and become more and more red with increasing Y-value.
import matplotlib.pyplot as plt
xvals = np.arange(0, 1, 0.01)
yvals = xvals
plt.plot(xvals, yvals, "r")
axes = plt.axes()
plt.show()
What do I have to change to get such a color gradient?
From the matplotlib documentation you can check this link as an example.
To create that colormap you just need to do:
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
colors = [(0, 0, 0), (1, 0, 0)] # first color is black, last is red
cm = LinearSegmentedColormap.from_list(
"Custom", colors, N=20)
mat = np.indices((10,10))[1]
plt.imshow(mat, cmap=cm)
plt.show()
This results in this:

White pcolor introduces white bar

I have the following script
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(24,7)
heatmap = plt.pcolor(data)
plt.show()
Which results into this image
How can I remove the white bar at the very top?
You have to manually set the x and y limits sometimes when you're using pcolor.
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(24,7)
heatmap = plt.pcolor(data)
plt.ylim(0, 24)
plt.show()
I am assuming here that your matrix is not a jagged matrix:
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(24,7)
nrow, ncol = data.shape
heatmap = plt.pcolor(data)
# put the major ticks
heatmap.axes.set_xticks(np.arange(ncol), minor=False)
heatmap.axes.set_yticks(np.arange(nrow), minor=False)
heatmap.axes.set_xlim(0,ncol) # Assuming a non jagged matrix
heatmap.axes.set_ylim(0,nrow)
plt.show()
Just simple change. np.random.rand(24,7) replace to np.random.rand(25,7)
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(25,7)
heatmap = plt.pcolor(data)
plt.show()
Output:
Or add axis Like plt.axis([0,7,0,24])
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(24,7)
heatmap = plt.pcolor(data)
plt.axis([0,7,0,24])
plt.show()
Output:

Matplotlib: displaying only unique labels for the legend

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):

Categories

Resources