Display a value in bar plot - python-3.x

I generated this plot and I cannot display a value properly for each bar. Here is my bar plot:
This is my code for creating the above plot:
X_perc = [10, 7, 3, 5, 5]
cols = ['3.1-4.14', '4.14-5.18', '6.22-7.26', '7.26-8.3', '5.18-6.22']
data = np.array([[10, 7, 5, 5, 3],])
fig, ax=plt.subplots()
for i, (name, v) in enumerate(zip(cols, X_perc)):
bottom=np.sum(data[:,0:i], axis=1)
ax.bar(1,data[:,i], bottom=bottom, label="{}".format(name))
ax.text(0.7, (v*i)/v * i + v + i, str(v), fontweight='bold')
plt.legend(framealpha=1)
plt.axis([-10, 10, 0, 31])
plt.tick_params(
axis='x',
which='both',
bottom=False,
top=False,
labelbottom=False)

You can use a cumulative sum of positions to annotate your stacked bars
positions = np.cumsum(data)
fig, ax=plt.subplots()
for i, (name, v) in enumerate(zip(cols, X_perc)):
bottom=np.sum(data[:,0:i], axis=1)
ax.bar(1,data[:,i], bottom=bottom, label="{}".format(name))
ax.text(0.7, positions[i], str(v), fontweight='bold') # Use it here

Related

Is there some way can add label in legend in plot by one step?

My legend now shows,
I want to add my label in legend, from 0 to 7, but I don't want to add a for-loop in my code and correct each label step by step, my code like that,
fig, ax = plt.subplots()
ax.set_title('Clusters by OPTICS in 2D space after PCA')
ax.set_xlabel('First Component')
ax.set_ylabel('Second Component')
points = ax.scatter(
pca_2_spec[:,0],
pca_2_spec[:,1],
s = 7,
marker='o',
c = pred_pca_2_spec,
cmap= 'rainbow')
ax.legend(*points.legend_elements(), title = 'cluster')
plt.show()
Assuming pred_pca_2_spec is some np.array with values [0, 5, 10, 15, 20, 30, 35] to change the values of these to be in the range 0-7, simply divide (each element) by 5.
Sample Data:
import numpy as np
from matplotlib import pyplot as plt
np.random.seed(54)
pca_2_spec = np.random.randint(-100, 300, (100, 2))
pred_pca_2_spec = np.random.choice([0, 5, 10, 15, 20, 25, 30, 35], 100)
Plotting Code:
fig, ax = plt.subplots()
ax.set_title('Clusters by OPTICS in 2D space after PCA')
ax.set_xlabel('First Component')
ax.set_ylabel('Second Component')
points = ax.scatter(
pca_2_spec[:, 0],
pca_2_spec[:, 1],
s=7,
marker='o',
c=pred_pca_2_spec / 5, # Divide By 5
cmap='rainbow')
ax.legend(*points.legend_elements(), title='cluster')
plt.show()

How to autoscale y-axis for bargraph in matplotlib?

I need to autoscale the y-axis on my bargraph in matplotlib in order to display the small differences in values. The reason why it needs to be autoscaled instead of having a fixed limit is because the values will change depending on what the user inputs. I've tried yscale log, but that doesn't work for negative values. I've tried symlog, but the graph stays the same. This is my current code:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = range(700, 710, 1)
fig, ax = plt.subplots()
ax.bar(x, y)
plt.show()
Plots are automatically scaled for the full range of the data provided to the API.
For a bar plot, the best option to display the differences in the values of the bars, is probably to set the ylim for vertical bars or xlim for horizontal bars.
negative data
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = range(-700, -750, -5)
fig, ax = plt.subplots(figsize=(7, 5))
ax.bar(x, y)
plt.ylim(min(y), max(y))
positive data
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = range(700, 750, 5)
fig, ax = plt.subplots(figsize=(7, 5))
ax.bar(x, y)
plt.ylim(min(y), max(y))
mixed data
If the data has a wide range of positive and negative values, there's probably not a good option, as you've noted symlog doesn't help the issue.
The best option may be to plot the positive and negative data separately.
Creating a mask does't work with a list, so convert the lists to numpy arrays.
import numpy as np
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [700, -700, 710, -710, 720, -720, 730, -730, 740, -740]
x = np.array(x)
y = np.array(y)
mask = y >= 0 # positive mask
pos_y = y[mask] # get the positive values
neg_y = y[~mask] # get the negative values; ~ is not
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(7, 5))
ax1.bar(x[mask], pos_y) # also mask x to plot the bar at the correct x-tick
ax1.set_title('Positive Values')
ax1.set_ylim(min(pos_y), max(pos_y))
ax1.set_xticks(range(0, 12)) # buffer the number of x-ticks, so the x-ticks of the two plots align.
ax2.bar(x[~mask], neg_y)
ax2.set_title('Negative Values')
ax2.set_ylim(min(neg_y), max(neg_y))
ax2.set_xticks(range(0, 12))
plt.tight_layout() # better spacing between the two plots

Adding one colorbar for hist2d subplots and make them adjacent

I am struggling with tweaking a plot, I have been working on.
I am facing to two problems:
The plots should be adjacent and with 0 wspace and hspace. I set both values to zero but still there are some spaces between the plots.
I would like to have one colorbar for all the subplots (they all the same range). Right now, the code adds a colorbar to the last subplot as i understand that it needs the third return value of hist2D.
Here is my code so far:
def plot_panel(pannel_plot):
fig, ax = plt.subplots(3, 2, figsize=(7, 7), gridspec_kw={'hspace': 0.0, 'wspace': 0.0}, sharex=True, sharey=True)
fig.subplots_adjust(wspace=0.0)
ax = ax.flatten()
xmin = 0
ymin = 0
xmax = 0.19
ymax = 0.19
hist2_num = 0
h =[]
for i, j in zip(pannel_plot['x'].values(), pannel_plot['y'].values()):
h = ax[hist2_num].hist2d(i, j, bins=50, norm=LogNorm(vmin=1, vmax=5000), range=[[xmin, xmax], [ymin, ymax]])
ax[hist2_num].set_aspect('equal', 'box')
ax[hist2_num].tick_params(axis='both', top=False, bottom=True, left=True, right=False,
labelsize=10, direction='in')
ax[hist2_num].set_xticks(np.arange(xmin, xmax, 0.07))
ax[hist2_num].set_yticks(np.arange(ymin, ymax, 0.07))
hist2_num += 1
fig.colorbar(h[3], orientation='vertical', fraction=.1)
plt.show()
And the corrsiponding result:
Result
I would be glad for any heads up that i am missing!
You can use ImageGrid, which was designed to make this kind of things easier
data = np.vstack([
np.random.multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
np.random.multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
])
from mpl_toolkits.axes_grid1 import ImageGrid
fig = plt.figure(figsize=(4, 6))
grid = ImageGrid(fig, 111, # similar to subplot(111)
nrows_ncols=(3, 2), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
cbar_mode="single",
cbar_location="right",
cbar_pad=0.1
)
for ax in grid:
h = ax.hist2d(data[:, 0], data[:, 1], bins=100)
fig.colorbar(h[3], cax=grid.cbar_axes[0], orientation='vertical')
or
data = np.vstack([
np.random.multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
np.random.multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
])
from mpl_toolkits.axes_grid1 import ImageGrid
fig = plt.figure(figsize=(4, 6))
grid = ImageGrid(fig, 111, # similar to subplot(111)
nrows_ncols=(3, 2), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
cbar_mode="single",
cbar_location="top",
cbar_pad=0.1
)
for ax in grid:
h = ax.hist2d(data[:, 0], data[:, 1], bins=100)
fig.colorbar(h[3], cax=grid.cbar_axes[0], orientation='horizontal')
grid.cbar_axes[0].xaxis.set_ticks_position('top')

How to adjust subplots spacing and to place y labels in matplotlib?

I have to use matplotlib to produce the following layout.
fig = plt.figure(figsize=(15,9))
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 0], 1, 1 )
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 1], 1, 1 )
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 2], 1, 3 )
I'd like to add some space between second and third columns to place a common ylabel indicated by the red marker. I got stuck at this point. Anyone can give me some guidance? Thank you!
If your label is not long, you can simply add it to the middle graph and use tight_layout to format it:
fig = plt.figure(figsize=(15,9))
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 0], 1, 1 )
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 1], 1, 1 )
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 2], 1, 3 )
if i == 1:
ax.set_ylabel("label for all")
plt.tight_layout()
plt.show()
This will not work for very long labels, though, because tight_layout will misinterpret the height of the middle row. In this case, we can simply replace the text with the longer version afterwards:
fig = plt.figure(figsize=(15,9))
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 0], 1, 1 )
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 1], 1, 1 )
for i in range(3):
ax = plt.subplot2grid((3, 5), [i, 2], 1, 3 )
if i == 1:
mylabel = ax.set_ylabel("dummy")
plt.tight_layout()
mylabel.set_text("not a dummy any more but a very very very loooooooooooooooooong label")
plt.show()
Sample output:

Matplotlib: Polar radius label padding

Hi: Could you help me evenly space the radius labels around my polar plot? I want to be able to adjust the padding for each axis label individually.
I know how to adjust the padding for all the labels together, but I don't want to do that because it doesn't evenly space them from the plot (e.g. add padding to New Zealand and Finland but don't add padding to China or Canada).
I appreciate any help you can give me.
Here is an image for my plot and the code:
import numpy as np
import pylab as pl
import matplotlib.pyplot as py
class Radar(object):
def __init__(self, fig, titles, labels, rect=None):
if rect is None:
rect = [0.05, 0.05, 0.95, 0.95]
self.n = len(titles)
self.angles = [a if a <=360. else a - 360. for a in np.arange(90, 90+360, 360.0/self.n)]
self.axes = [fig.add_axes(rect, projection="polar", label="axes%d" % i)
for i in range(self.n)]
self.ax = self.axes[0]
self.ax.set_thetagrids(self.angles, labels=titles,
fontsize=13, weight="normal", color="black")
for ax in self.axes[1:]:
ax.patch.set_visible(False)
ax.grid("off")
ax.xaxis.set_visible(False)
self.ax.yaxis.grid(False)
for ax, angle, label in zip(self.axes, self.angles, labels):
ax.set_rgrids(range(1, 7), labels=label, angle=angle, fontsize=12)
ax.spines["polar"].set_visible(False)
ax.set_ylim(0, 6)
ax.xaxis.grid(True,color='black',linestyle='-')
pos=ax.get_rlabel_position()
ax.set_rlabel_position(pos+3)
def plot(self, values, *args, **kw):
angle = np.deg2rad(np.r_[self.angles, self.angles[0]])
values = np.r_[values, values[0]]
self.ax.plot(angle, values, *args, **kw)
fig = pl.figure(figsize=(20, 20))
titles = [
"Canada", "Australia", "New\nZealand", "Japan",
"China", "USA", "Mexico", "Finland", "Doha"
]
labels = [
list("abcde"), list("12345"), list("uvwxy"),
[" ", " ", "$156", "$158", "$160"],
list("jklmn"), list("asdfg"), list("qwert"),
[" ", "4.3", "4.4", "4.5", "4.6"], list("abcde")
]
radar = Radar(fig, titles, labels)
radar.plot([1, 3, 2, 5, 4, 5, 3, 3, 2], "--", lw=1, color="b", alpha=.5, label="USA 2014")
radar.plot([2.3, 2, 3, 3, 2, 3, 2, 4, 2],"-", lw=1, color="r", alpha=.5, label="2014")
radar.plot([3, 4, 3, 4, 2, 2, 1, 3, 2], "-", lw=1, color="g", alpha=.5, label="2013")
radar.plot([4.5, 5, 4, 5, 3, 3, 4, 4, 2], "-", lw=1, color="y", alpha=.5, label="2012")
radar.ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.10),
fancybox=True, shadow=True, ncol=4)
py.text(0.5, 1.15, "Seattle, WA\n", weight="bold", fontsize=22,
transform=py.gca().transAxes, ha='center')
py.text(0.5, 1.15, "Market Data from 2012 to 2014", fontsize=14,
transform=py.gca().transAxes, ha='center')
fig = py.gcf()
fig.set_size_inches(6, 10, forward=True)
fig.savefig('test2png.png', dpi=100, bbox_inches="tight", pad_inches=1)

Resources