Sitemap
Danny Ucho

Danny Ucho

Analyst and developer

Create Pictorial Stacked Chart with SVG image in plotly python

2 min readSep 10, 2024

The pictorial stacked chart is an improved variation of a column or bar chart. Use an image related to the topic, natively plotly does not implement a similar graph but here I propose an example of how to do it with SVG files from Free Icons | Font Awesome.

Press enter or click to view image in full size

Get Danny Ucho’s stories in your inbox

Join Medium for free to get updates from this writer.

import PIL
import cairosvg
import plotly.express as px
import io
import numpy as np
import pandas as pd

#Function generate color scale in array svg
def genCategoryColor(matrix,start = 0, end = 1, color_rgb=[255,0,0]):
for x in range(int(round(matrix.shape[0]*start,0)), int(round(matrix.shape[0]*end,0))):
if (np.any(matrix[x,:,:])):
for y in range(matrix.shape[1]):
if (np.any(matrix[x][y])):
if x>=matrix.shape[0]*start and x < matrix.shape[0]*end:
matrix[x][y] = [color_rgb[0],color_rgb[1],color_rgb[2],list(matrix[x][y])[-1]]
return matrix

#Function generate annotation in chart
def addAnnotation(fig,shape, start= 0, end = 1, text='Annotation'):
fig.add_annotation(
x=0,
y=shape[0]*((start+end)/2),
text=text,
showarrow=True,
xanchor="right",
ax=-50,
ay=0,
arrowsize=0.5,
)


#data example:
pc_1 = {'name':'Amazon Web Services (AWS)', 'start':0, 'end': 0.34, 'color':[255, 161, 6]}
pc_2 = {'name':'Microsoft Azure', 'start':0.34, 'end': 0.57, 'color':[6, 142, 255]}
pc_3 = {'name':'Google Cloud Platform (GCP)', 'start':0.57, 'end': 0.67, 'color':[255, 56, 7]}
pc_4 = {'name':'Otros', 'start':0.67, 'end': 1, 'color':[7, 217, 255]}
df = pd.DataFrame([pc_1,pc_2,pc_3,pc_4])

# svg icon from https://fontawesome.com/search?m=free&o=r and generate matrix
svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 336c0 79.5 64.5 144 144 144l368 0c70.7 0 128-57.3 128-128c0-61.9-44-113.6-102.4-125.4c4.1-10.7 6.4-22.4 6.4-34.6c0-53-43-96-96-96c-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32C167.6 32 96 103.6 96 192c0 2.7 .1 5.4 .2 8.1C40.2 219.8 0 273.2 0 336z"/></svg>'
im = PIL.Image.open(io.BytesIO(cairosvg.svg2png(bytestring=svg))).convert("RGBA")
matrix = np.array(im)

for index, row in df.iterrows():
matrix = genCategoryColor(matrix,row['start'],row['end'],list(row['color']))

fig = px.imshow(matrix,height=400,width=800,template='none')

for index, row in df.iterrows():
addAnnotation(fig,matrix.shape,row['start'],row['end'],str(round((row['end']-row['start'])*100,2))+'% '+row['name'])
fig.update_xaxes(title = 'Time', showticklabels=False, visible = False)
fig.update_yaxes(visible=False, type='linear', showticklabels=False)
fig.update_layout(coloraxis_showscale=False,margin=dict(l=20,r=20,b=20,t=20))
fig.show()

Use the available icons replacing the viable SVG to generate visualizations. here some examples:

Press enter or click to view image in full size

--

--