define size of individual subplots side by side - matplotlib

I am using subplots side by side
plt.subplot(1, 2, 1)
# plot 1
plt.xlabel('MEM SET')
plt.ylabel('Memory Used')
plt.bar(inst_memory['MEMORY_SET_TYPE'], inst_memory['USED_MB'], alpha = 0.5, color = 'r')
# pol 2
plt.subplot(1, 2, 2)
plt.xlabel('MEM POOL')
plt.ylabel('Memory Used')
plt.bar(set_memory['POOL_TYPE'], set_memory['MEMORY_POOL_USED'], alpha = 0.5, color = 'g')
they have identical size - but is it possible to define the width for each subplot, so the right one could be wider as it has more entries and text would not squeeze or would it be possible to replace the bottom x-text by a number and have a legend with 1:means xx 2:means yyy

I find GridSpec helpful for subplot arrangements, see this demo at matplotlib.
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import pandas as pd
N=24
inst_memory = pd.DataFrame({'MEMORY_SET_TYPE': np.random.randint(0,3,N),
'USED_MB': np.random.randint(0,1000,N)})
set_memory = pd.DataFrame({'MEMORY_POOL_USED': np.random.randint(0,1000,N),
'POOL_TYPE': np.random.randint(0,10,N)})
fig = plt.figure()
gs = GridSpec(1, 2, width_ratios=[1, 2],wspace=0.3)
ax1 = fig.add_subplot(gs[0])
ax2 = fig.add_subplot(gs[1])
ax1.bar(inst_memory['MEMORY_SET_TYPE'], inst_memory['USED_MB'], alpha = 0.5, color = 'r')
ax2.bar(set_memory['POOL_TYPE'], set_memory['MEMORY_POOL_USED'], alpha = 0.5, color = 'g')
You may need to adjust width_ratios and wspace to get the desired layout.
Also, rotating the text in x-axis might help, some info here.

Related

How do I invert matplotlib bars at a specific point instead of when negative?

I'd like to invert the bars in this diagram when they are below 1, not when they are negative. Additionally I'd like to have even spacing between the ticks/steps on the y-axis
Here is my current code
import matplotlib.pyplot as plt
import numpy as np
labels = ['A','B','C']
Vals1 = [28.3232, 12.232, 9.6132]
Vals2 = [0.00456, 17.868, 13.453]
Vals3 = [0.0032, 1.234, 0.08214]
x = np.arange(len(labels))
width = 0.2
fig, ax = plt.subplots()
rects1 = ax.bar(x - width, Vals1, width, label='V1')
rects2 = ax.bar(x, Vals2, width, label='V2')
rects3 = ax.bar(x + width, Vals3, width, label='V3')
ax.set_xticks(x)
ax.set_xticklabels(labels)
plt.xticks(rotation=90)
ax.legend()
yScale = [0.0019531,0.0039063,0.0078125,0.015625,0.03125,0.0625,0.125,0.25,0.5,1,2,4,8,16,32]
ax.set_yticks(yScale)
plt.show()
I believe I've stumbled upon the answer, here it is for anyone else looking for the solution. Add the argument bottom='1' to ax.bar instantiation, and then flip the values in the array.
for i in range(len(Vals1)):
Vals1[i] = (1 - Vals1[i]) * -1
As you mentioned, the key is the bottom param of Axes.bar:
bottom (default: 0): The y coordinate(s) of the bars bases.
But beyond that, you can simplify your plotting code using pandas:
Put your data into a DataFrame:
import pandas as pd
df = pd.DataFrame({'V1': Vals1, 'V2': Vals2, 'V3': Vals3}, index=labels)
# V1 V2 V3
# A 28.3232 0.00456 0.00320
# B 12.2320 17.86800 1.23400
# C 9.6132 13.45300 0.08214
Then use DataFrame.sub to subtract the offset and DataFrame.plot.bar with the bottom param:
bottom = 1
ax = df.sub(bottom).plot.bar(bottom=bottom)

Align multi-line ticks in Seaborn plot

I have the following heatmap:
I've broken up the category names by each capital letter and then capitalised them. This achieves a centering effect across the labels on my x-axis by default which I'd like to replicate across my y-axis.
yticks = [re.sub("(?<=.{1})(.?)(?=[A-Z]+)", "\\1\n", label, 0, re.DOTALL).upper() for label in corr.index]
xticks = [re.sub("(?<=.{1})(.?)(?=[A-Z]+)", "\\1\n", label, 0, re.DOTALL).upper() for label in corr.columns]
fig, ax = plt.subplots(figsize=(20,15))
sns.heatmap(corr, ax=ax, annot=True, fmt="d",
cmap="Blues", annot_kws=annot_kws,
mask=mask, vmin=0, vmax=5000,
cbar_kws={"shrink": .8}, square=True,
linewidths=5)
for p in ax.texts:
myTrans = p.get_transform()
offset = mpl.transforms.ScaledTranslation(-12, 5, mpl.transforms.IdentityTransform())
p.set_transform(myTrans + offset)
plt.yticks(plt.yticks()[0], labels=yticks, rotation=0, linespacing=0.4)
plt.xticks(plt.xticks()[0], labels=xticks, rotation=0, linespacing=0.4)
where corr represents a pre-defined pandas dataframe.
I couldn't seem to find an align parameter for setting the ticks and was wondering if and how this centering could be achieved in seaborn/matplotlib?
I've adapted the seaborn correlation plot example below.
from string import ascii_letters
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme(style="white")
# Generate a large random dataset
rs = np.random.RandomState(33)
d = pd.DataFrame(data=rs.normal(size=(100, 7)),
columns=['Donald\nDuck','Mickey\nMouse','Han\nSolo',
'Luke\nSkywalker','Yoda','Santa\nClause','Ronald\nMcDonald'])
# Compute the correlation matrix
corr = d.corr()
# Generate a mask for the upper triangle
mask = np.triu(np.ones_like(corr, dtype=bool))
# Set up the matplotlib figure
f, ax = plt.subplots(figsize=(11, 9))
# Generate a custom diverging colormap
cmap = sns.diverging_palette(230, 20, as_cmap=True)
# Draw the heatmap with the mask and correct aspect ratio
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,
square=True, linewidths=.5, cbar_kws={"shrink": .5})
for i in ax.get_yticklabels():
i.set_ha('right')
i.set_rotation(0)
for i in ax.get_xticklabels():
i.set_ha('center')
Note the two for sequences above. These get the label and then set the horizontal alignment (You can also change the vertical alignment (set_va()).
The code above produces this:

How can I remove colormaps in matplotlib? [duplicate]

This question already has answers here:
Display image as grayscale using matplotlib
(9 answers)
Closed 4 years ago.
I have the following code:
fig, ax = plt.subplots()
fig.set_size_inches(10, 10, forward=True)
min_val, max_val = 0, 28
inputBild = np.round(np.reshape(inputBild, [28, 28]), 1)
plt.imshow(inputBild)
for i in range(28):
for j in range(28):
c = inputBild[j,i]
ax.text(i, j, str(c), va='center', ha='center')
ax.set_facecolor((1.0, 0.47, 0.42))
plt.savefig('/tmp/inputMitZahlOhneCmap.png', bbox_inches='tight')
inputBild is a random image of the mnist dataset.
I want to only plot the numbers but not the colormap.
How can I remove it if I didn't even specify one?
I am not sure if you want a scatter plot when you say "only plot the numbers" but looking at your usage of imshow, I think you want to hide the colorbar. Here is an example:
With color bar
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
data = np.random.rand(100, 100)
cax = ax.imshow(data)
cbar = plt.colorbar(cax) # This line includes the color bar
Without color bar
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
data = np.random.rand(100, 100)
cax = ax.imshow(data)
Deleting color bar: Method 1 (not showing initial lines of code)
data = np.random.rand(100, 100)
cax = ax.imshow(data)
cbar = plt.colorbar(cax)
cbar.remove()
Deleting color bar: Method 2 (not showing initial lines of code)
data = np.random.rand(100, 100)
cax = ax.imshow(data)
plt.colorbar(cax)
plt.delaxes(fig.axes[1]) # axes[0] correspond to the main plot.
Output Method 1 and 2

How can I set boxplot color by rainbow in matplotlib

I want to create boxplot of data in comparing, my plot looks like
how can I add color like
You can color the box following this example. Beyond that, you will need to map your data in mind to color on the "rainbow" colormap with this module. Here is an example with random test data. I map colors with means in this example.
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
# Random test data
test_data = [np.random.normal(mean, 1, 100) for mean in range(50)]
fig, axes = plt.subplots(figsize=(12, 16))
# Horizontal box plot
bplot = axes.boxplot(test_data,
vert=False, # vertical box aligmnent
patch_artist=True) # fill with color
# Fill with colors
cmap = cm.ScalarMappable(cmap='rainbow')
test_mean = [np.mean(x) for x in test_data]
for patch, color in zip(bplot['boxes'], cmap.to_rgba(test_mean)):
patch.set_facecolor(color)
plt.show()
You can use the cmap property to actually be a function, accepting values between 0 and 1, and call it "normalising" your data. Using matplotlib example on boxplots:
import matplotlib.pyplot as plt
import numpy as np
# Random test data
np.random.seed(123)
all_data = [np.random.normal(0, 5, 100) for std in range(1, 21)]
fig, ax = plt.subplots(nrows=1, figsize=(9, 4))
# rectangular box plot
bplot = ax.boxplot(all_data, 0, '', 0, patch_artist=True)
cm = plt.cm.get_cmap('rainbow')
colors = [cm(val/len(all_data)) for val in range(len(all_data))]
for patch, color in zip(bplot['boxes'], colors):
patch.set_facecolor(color)
plt.show()

only 1 colorbar for multiple pie chart using matlibplot

I have such a plot, and would like to add a the colorbar code (which color corresponds to what number) on the right hand below. I saw some example which where used for imshow not pie chart.
#!/usr/bin/env python
"""
http://matplotlib.sf.net/matplotlib.pylab.html#-pie for the docstring.
"""
from pylab import *
fracs = [33,33,33]
starting_angle = 90
axis('equal')
for item in range(9):
color_vals = [-1, 0, 1]
my_norm = matplotlib.colors.Normalize(-1, 1) # maps your data to the range [0, 1]
my_cmap = matplotlib.cm.get_cmap('RdBu') # can pick your color map
patches, texts, autotexts = pie(fracs, labels = None, autopct='%1.1f%%', startangle=90, colors=my_cmap(my_norm(color_vals)))
subplot(3,3,item+1)
fracs = [33,33,33]
starting_angle = 90
axis('equal')
patches, texts, autotexts = pie(fracs, labels = None, autopct='%1.1f%%', startangle=90, colors=my_cmap(my_norm(color_vals)))
for item in autotexts:
item.set_text("")
subplots_adjust(left=0.125, bottom=0.1, right=0.9, top=0.9, wspace=0.0, hspace=0.5)
savefig('/home/superiois/Downloads/projectx3/GRAIL/pie1.png')
show()
Also, it would be great if you tell me how to customize the size and location of colorbar code; Thanks.
Usually a legend is more appropriate for discrete values and a colorbar for continuous values. That said, its off course possible since mpl allows you to create a colorbar from scratch.
import matplotlib.pyplot as plt
import matplotlib as mpl
fracs = [33,33,33]
starting_angle = 90
fig, axs = plt.subplots(3,3, figsize=(6,6))
fig.subplots_adjust(hspace=0.1,wspace=0.0)
axs = axs.ravel()
for n in range(9):
color_vals = [-1, 0, 1]
my_norm = mpl.colors.Normalize(-1, 1) # maps your data to the range [0, 1]
my_cmap = mpl.cm.get_cmap('RdBu', len(color_vals)) # can pick your color map
patches, texts, autotexts = axs[n].pie(fracs, labels = None, autopct='%1.1f%%', startangle=90, colors=my_cmap(my_norm(color_vals)))
axs[n].set_aspect('equal')
for item in autotexts:
item.set_text("")
ax_cb = fig.add_axes([.9,.25,.03,.5])
cb = mpl.colorbar.ColorbarBase(ax_cb, cmap=my_cmap, norm=my_norm, ticks=color_vals)
cb.set_label('Some label [-]')
cb.set_ticklabels(['One', 'Two', 'Three'])
I have added custom ticklabels just to show how that would work, to get the default values simply remove the last line.