I am trying to highlight minimum values of each row using the same color:
For instance, the first row minimum is 0.3. I want to highlight it with blue color. Similarly, for the second row, 0.042 and so on.
Here's the code.
import numpy as np
import seaborn as sns
import matplotlib.pylab as plt
from matplotlib.patches import Rectangle
Pe = np.random.rand(5,5)
annot=True
fig, ax1 = plt.subplots(1)
ax1 = sns.heatmap(Pe, linewidth=0.5,ax=ax1,annot=annot)
You could loop through the rows, find the index of the minimum, and draw a rectangle there. Setting clip_on=False prevents that the rectangles would be clipped by the border.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
Pe = np.random.rand(5, 5)
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 4))
sns.set_style('white')
sns.heatmap(Pe, linewidth=0.5, annot=True, ax=ax1)
for ind, row in enumerate(Pe):
min_col = np.argmin(row)
ax1.add_patch(plt.Rectangle((min_col, ind), 1, 1, fc='none', ec='skyblue', lw=5, clip_on=False))
sns.heatmap(Pe, mask=Pe != Pe.min(axis=1, keepdims=True), annot=True, lw=2, linecolor='black', clip_on=False,
cmap=ListedColormap(['skyblue']), cbar=False, ax=ax2)
plt.tight_layout()
plt.show()
PS: To create animations, the Celluloid library is a lightweight option:
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import seaborn as sns
import numpy as np
from celluloid import Camera
Pe = np.random.rand(5, 5)
fig, ax1 = plt.subplots()
camera = Camera(fig)
sns.set_style('white')
row_array = np.arange(Pe.shape[0]).reshape(-1, 1)
for row in range(Pe.shape[0]):
sns.heatmap(Pe, mask=(Pe != Pe.min(axis=1, keepdims=True)) | (row < row_array),
annot=True, lw=2, linecolor='black', clip_on=False,
cmap=ListedColormap(['skyblue']), cbar=False, ax=ax1)
camera.snap()
animation = camera.animate(interval=800)
animation.save('animation.gif')
plt.show()
For more complicated animations, matplotlib's animation API can be considered.
Related
I am trying to align the matplotlib plot with its colorbar. However, when there is a tick on the top of the colormap, the figure itself shrinks a little bit:
Is there a way to equalize this distance (blue arrows) consistently?
For generating the plot, I am using following code:
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
ax.plot(...)
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes('right', '5%', pad='3%')
sm = plt.cm.ScalarMappable(cmap=plt.get_cmap('viridis'),
norm=mpl.colors.Normalize(vmin=0, vmax=60))
sm.set_array([])
fig.colorbar(sm, cax=cax)
plt.tight_layout()
plt.savefig('pic.png', dpi=500)
I would like to use varying degrees of red color to represent the different importance of each time element and fill in that region.
The example code is shown below.
import matplotlib.pyplot as plt
X_example = np.random.rand(400)
importance_values = np.random.rand(400)
plt.figure(figsize=(13,7))
plt.plot(X_example)
for j in range(len(X_example)):
plt.axvspan(xmin=j, xmax=j+1,facecolor="r",alpha=importance_values[j])
It generates a graph like:
Now I would like to add a colormap in this figure to show that, e.g. the light red means low importance and the dark red means high importance, just like this:
How could I achieve that in my case?
One solution would be to create a LinearSegmentedColormap which takes a list of colors and turns it into a matplotlib colorbar object. Then you can set the "alpha channel":
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap, ListedColormap
from matplotlib.colorbar import ColorbarBase
X_example = np.random.rand(400)
importance_values = np.random.rand(400)
fig, (ax, cax) = plt.subplots(ncols=2, figsize=(8,5), gridspec_kw={'width_ratios': [1, 0.05]})
ax.plot(X_example, color='b')
for j in range(len(X_example)):
ax.axvspan(xmin=j, xmax=j+1,facecolor="r",alpha=importance_values[j])
N = 20 # the number of colors/alpha-values in the colorbar
cmap = LinearSegmentedColormap.from_list(None, ['r' for i in range(N)], N=N)
alpha_cmap = cmap(np.arange(N))
alpha_cmap[:,-1] = np.linspace(0, 1, N)
alpha_cmap = ListedColormap(alpha_cmap, N=N)
cbar = ColorbarBase(cax, cmap=alpha_cmap, ticks=[0., 1],)
cbar.ax.set_yticklabels(["low importance", "high importance"])
This gives the following plot, where the two colors of the colorbar have custom labels:
You could create a colormap mixing the red color with a range of alpha values:
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap, to_rgba
from matplotlib.cm import ScalarMappable
import numpy as np
X_example = np.random.rand(400)
importance_values = np.random.rand(400)
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(X_example)
for j in range(len(X_example)):
ax.axvspan(xmin=j, xmax=j + 1, facecolor="r", alpha=importance_values[j])
ax.margins(x=0)
cmap = LinearSegmentedColormap.from_list(None, [to_rgba('r', 0), 'r'])
cbar = plt.colorbar(ScalarMappable(cmap=cmap), ticks=[0, 1], pad=0.02)
cbar.ax.set_yticklabels(["low", "high"], fontsize=20)
cbar.ax.set_ylabel("importance", labelpad=-30, fontsize=20)
plt.tight_layout()
plt.show()
An example of a horizontal colorbar:
cbar = plt.colorbar(ScalarMappable(cmap=cmap), ticks=[0, 1], orientation='horizontal')
cbar.ax.set_xticklabels(["low", "high"], fontsize=20)
cbar.ax.set_xlabel("importance", labelpad=-15, fontsize=20)
I want to change the color of lineborder of violinplots.
I can set lines.linewidth to 0 but I want to show borders not to hide them. How to change the color of the border?
sns.set_context("paper", rc={"lines.linewidth": 0.8})
My code is as follows:
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import style
import pandas as pd
import numpy as np
datasets = pd.read_csv("merged.csv", index_col=0);
df = datasets
df.protocol = df.protocol.astype(str)
f, ax = plt.subplots(figsize=(18, 6))
sns.violinplot(x="time",
y="values",
hue="protocol",
data=df,
bw=.5,
scale="count"
)
sns.despine(left=True)
f.suptitle('Title', fontsize=22, fontweight='bold')
ax.set_xlabel("Time",size = 16,alpha=0.7)
ax.set_ylabel("Values",size = 16,alpha=0.7)
ax.set_xticklabels(df.qber, rotation=90)
ax.grid(True)
plt.legend(loc='upper right')
plt.grid(linestyle='--', alpha=0.7)
fig = ax.get_figure()
fig.savefig('time_v.pdf', bbox_inches='tight')
Thank you!
this should be very close to what you're looking for:
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import style
import pandas as pd
import numpy as np
def patch_violinplot(palette, n):
from matplotlib.collections import PolyCollection
ax = plt.gca()
violins = [art for art in ax.get_children() if isinstance(art, PolyCollection)]
colors = sns.color_palette(palette, n_colors=n) * (len(violins)//n)
for i in range(len(violins)):
violins[i].set_edgecolor(colors[i])
datasets = pd.read_csv("merged.csv", index_col=0);
df = datasets
df.protocol = df.protocol.astype(str)
num_cols = df['protocol'].nunique()
f, ax = plt.subplots(figsize=(18, 6))
sns.violinplot(x="time",
y="values",
hue="protocol",
data=df,
bw=.5,
scale="count",
palette="deep"
)
patch_violinplot("deep", num_cols)
sns.despine(left=True)
f.suptitle('Title', fontsize=22, fontweight='bold')
ax.set_xlabel("Time",size = 16,alpha=0.7)
ax.set_ylabel("Values",size = 16,alpha=0.7)
ax.set_xticklabels(df.qber, rotation=90)
ax.grid(True)
plt.legend(loc='upper right')
plt.grid(linestyle='--', alpha=0.7)
fig = ax.get_figure()
fig.savefig('time_v.pdf', bbox_inches='tight')
The patch_violin function came from here.
It seems like some of the methods that work for matplotlib 2D might not be working for matplotlib 3D. I'm not sure.
I'd like to remove the tick marks from all axes, and extend the edge color from the bottom and sides to the top as well. The farthest I have gotten is being able to draw the ticks as white, which looks bad as they are rendered on top of the edge lines.
Below is a big chunk of self-contained code that results in the following image. Any help is much appreciated!
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib import animation
from mpl_toolkits.mplot3d import Axes3D
mpl.rcParams['ytick.color'] = 'white'
#mpl.rcParams['ytick.left'] = False
sample = np.random.random_integers(low=1,high=5, size=(10,3))
# Create a figure and a 3D Axes
fig = plt.figure(figsize=(5,5))
ax = Axes3D(fig)
#ax.w_xaxis.set_tick_params(color='white')
#ax.axes.tick_params
ax.axes.tick_params(bottom=False, color='blue')
##['size', 'width', 'color', 'tickdir', 'pad', 'labelsize',
##'labelcolor', 'zorder', 'gridOn', 'tick1On', 'tick2On',
##'label1On', 'label2On', 'length', 'direction', 'left', 'bottom',
##'right', 'top', 'labelleft', 'labelbottom',
##'labelright', 'labeltop', 'labelrotation']
colors = np.mean(sample[:, :], axis=1)
ax.scatter(sample[:,0], sample[:,1], sample[:,2],
marker='o', s=20, c=colors, alpha=1)
ax.tick_params(color='red')
frame1 = plt.gca()
frame1.axes.xaxis.set_ticklabels([])
frame1.axes.yaxis.set_ticklabels([])
frame1.axes.zaxis.set_ticklabels([])
#frame1.axes.yaxis.set_tick_params(color='white')
To answer the first bit of the question, about tick removal,
it's probably easiest to just disable the tick lines:
for line in ax.xaxis.get_ticklines():
line.set_visible(False)
for line in ax.yaxis.get_ticklines():
line.set_visible(False)
for line in ax.zaxis.get_ticklines():
line.set_visible(False)
E.g.:
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib import animation
from mpl_toolkits.mplot3d import Axes3D
sample = np.random.random_integers(low=1,high=5, size=(10,3))
# Create a figure and a 3D Axes
fig = plt.figure(figsize=(5,5))
ax = Axes3D(fig)
colors = np.mean(sample[:, :], axis=1)
ax.scatter(sample[:,0], sample[:,1], sample[:,2],
marker='o', s=20, c=colors, alpha=1)
ax = plt.gca()
ax.xaxis.set_ticklabels([])
ax.yaxis.set_ticklabels([])
ax.zaxis.set_ticklabels([])
for line in ax.xaxis.get_ticklines():
line.set_visible(False)
for line in ax.yaxis.get_ticklines():
line.set_visible(False)
for line in ax.zaxis.get_ticklines():
line.set_visible(False)
For newer versions (e.g. matplotlib 3.5.1) a lot of formatting can be done via mpl_toolkits.mplot3d.axis3d._axinfo:
import numpy as np
from matplotlib import pyplot as plt
sample = np.random.randint(low=1,high=5, size=(10,3))
# Create a figure and a 3D Axes
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(projection='3d')
colors = np.mean(sample[:, :], axis=1)
ax.scatter(sample[:,0], sample[:,1], sample[:,2],
marker='o', s=20, c=colors, alpha=1)
for axis in [ax.xaxis, ax.yaxis, ax.zaxis]:
axis.set_ticklabels([])
axis._axinfo['axisline']['linewidth'] = 1
axis._axinfo['axisline']['color'] = (0, 0, 0)
axis._axinfo['grid']['linewidth'] = 0.5
axis._axinfo['grid']['linestyle'] = "-"
axis._axinfo['grid']['color'] = (0, 0, 0)
axis._axinfo['tick']['inward_factor'] = 0.0
axis._axinfo['tick']['outward_factor'] = 0.0
axis.set_pane_color((0.95, 0.95, 0.95))
plt.show()
How can I keep seaborn.despine from putting both of my y-scales onto the left side of my plot?
The best I've come up with so far is:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("white")
fig, ax = plt.subplots()
ax.plot(np.random.rand(10))
ax2 =ax.twinx()
ax2.plot(100*np.random.rand(10))
sns.despine(ax=ax, right=True, left=True)
sns.despine(ax=ax2, left=True, right=False)
But any other combination will either not despine the y-axes or put the right axis onto the left.
Output of the above: (desired output has no spines, just numbers on left and right)
I guess that's what you want then.
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("white")
fig, ax = plt.subplots()
ax.plot(np.random.rand(10))
ax2 =ax.twinx()
ax2.plot(100*np.random.rand(10))
sns.despine(ax=ax, right=True, left=True)
sns.despine(ax=ax2, left=True, right=False)
ax2.spines['right'].set_color('white')