This is the current output of my code at the moment.
I have this the code:
rb=0
gb=80
bb=141
color_bar=rgb_to_hex(rb, gb, bb)
rl=237
gl=125
bl=49
color_line=rgb_to_hex(rl, gl, bl)
rbra=255
gbra=255
bbra=255
color_text_table=rgb_to_hex(rbra,gbra,bbra)
#Tamanho da letra e espessura linha fontsize=18 linewidth=5
#configuração tamanho da imagem plt.rcParams['figure.figsize']=(20,10)
#Alterar cor da frame do gráfico ou outros parametros plt.rc('axes',edgecolor=color_bar, lw=linewidth-2.5)
#Criar Gráfico de Barras
width_bar=0.35
lim_sup=grouped\['OID_MEM_ID'\].max()+(grouped\['OID_MEM_ID'\].max()-grouped\['OID_MEM_ID'\].min())\*2
ax = grouped.plot('Mês Ano','OID_MEM_ID',
color=color_bar,
kind ='bar',
fontsize=fontsize+2,
legend=False,
width=width_bar,
ylim=(0,lim_sup))
#Retirar valores y do gráfico ax.axes.yaxis.set_ticklabels([])
I expect this output
What can I do to improve my solution?
We can use a combination of matplotlib
's mcolors
, Polygon
, and Bbox
to put together a gradient bar plot:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.patches import Polygon
from matplotlib.transforms import Bbox
y = np.random.random(4)*0.01
fill_color = [0, 0.25, 0.75]
box_width = 0.35
box_floor = 0
box_alpha = 1.0
ax = plt.subplot(1, 1, 1)
rgb = mcolors.colorConverter.to_rgb(fill_color)
box_color = np.zeros((100, 1, 4), dtype=float)
box_color[:, :, :3] = rgb
box_color[:, :, -1] = np.linspace(0, box_alpha, 100)[:, None]
for _x in range(len(y)):
im = ax.imshow(box_color, aspect='auto', extent=[_x - box_width + 1, _x + box_width + 1, box_floor, y[_x]], origin='lower')
xy = np.vstack([[_x - box_width + 1, box_floor], Bbox.from_bounds(_x - box_width + 1, _x + box_width + 1, box_floor, y[_x]), [_x + box_width + 1, box_floor], [_x - box_width + 1, box_floor]])
clip_path = Polygon(xy, facecolor='none', edgecolor='none', closed=True)
ax.add_patch(clip_path)
im.set_clip_path(clip_path)
ax.plot(np.arange(1, len(y) + 1, 1), y[::-1], ls='-', lw=1.5, color=[1, 0.5, 0])
ax.set_ylim(0, y.max() + (0.1*y.max()))
ax.set_xlim(-box_width, len(y) + box_width + 1)
plt.show()
Outputs:
However, it doesn't scale out well beyond the tenths place (0.1
) so for data with larger numbers we'd have to use something like rescale_y
and also adjust the yticklabels
:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.patches import Polygon
from matplotlib.transforms import Bbox
_y = np.random.random(4)*1000
def rescale_y(_y, _exp=0):
while max(_y) > 0.1:
_exp += 1
_y*=0.1
return _y, _exp
y, _exp = rescale_y(_y)
fill_color = [0, 0.25, 0.75]
box_width = 0.35
box_floor = 0
box_alpha = 1.0
ax = plt.subplot(1, 1, 1)
rgb = mcolors.colorConverter.to_rgb(fill_color)
box_color = np.zeros((100, 1, 4), dtype=float)
box_color[:, :, :3] = rgb
box_color[:, :, -1] = np.linspace(0, box_alpha, 100)[:, None]
for _x in range(len(y)):
im = ax.imshow(box_color, aspect='auto', extent=[_x - box_width + 1, _x + box_width + 1, box_floor, y[_x]], origin='lower')
xy = np.vstack([[_x - box_width + 1, box_floor], Bbox.from_bounds(_x - box_width + 1, _x + box_width + 1, box_floor, y[_x]), [_x + box_width + 1, box_floor], [_x - box_width + 1, box_floor]])
clip_path = Polygon(xy, facecolor='none', edgecolor='none', closed=True)
ax.add_patch(clip_path)
im.set_clip_path(clip_path)
ax.plot(np.arange(1, len(y) + 1, 1), y[::-1], ls='-', lw=1.5, color=[1, 0.5, 0])
ax.set_ylim(0, y.max() + (0.1*y.max()))
if _exp:
ax.set_yticklabels([str(round(_tick*(10**(_exp)))) for _tick in ax.get_yticks()])
ax.set_xlim(-box_width, len(y) + box_width + 1)
plt.show()
Outputs:
Otherwise...
If we want different fill_colors
for each bar in our plot:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.patches import Polygon
from matplotlib.transforms import Bbox
_y = np.random.random(4)*1000
def rescale_y(_y, _exp=0):
while max(_y) > 0.1:
_exp += 1
_y*=0.1
return _y, _exp
y, _exp = rescale_y(_y)
fill_colors = [[0, 0.25, 0.75], [1, 0, 0], [0, 1, 0], [1, 1, 0]]
box_width = 0.35
box_floor = 0
box_alpha = 1.0
ax = plt.subplot(1, 1, 1)
for _x in range(len(y)):
rgb = mcolors.colorConverter.to_rgb(fill_colors[_x])
box_color = np.zeros((100, 1, 4), dtype=float)
box_color[:, :, :3] = rgb
box_color[:, :, -1] = np.linspace(0, box_alpha, 100)[:, None]
im = ax.imshow(box_color, aspect='auto', extent=[_x - box_width + 1, _x + box_width + 1, box_floor, y[_x]], origin='lower')
xy = np.vstack([[_x - box_width + 1, box_floor], Bbox.from_bounds(_x - box_width + 1, _x + box_width + 1, box_floor, y[_x]), [_x + box_width + 1, box_floor], [_x - box_width + 1, box_floor]])
clip_path = Polygon(xy, facecolor='none', edgecolor='none', closed=True)
ax.add_patch(clip_path)
im.set_clip_path(clip_path)
ax.plot(np.arange(1, len(y) + 1, 1), y[::-1], ls='-', lw=1.5, color=[1, 0.5, 0])
ax.set_ylim(0, y.max() + (0.1*y.max()))
if _exp:
ax.set_yticklabels([str(round(_tick*(10**(_exp)))) for _tick in ax.get_yticks()])
ax.set_xlim(-box_width, len(y) + box_width + 1)
plt.show()
Outputs: