Data Visualization with Plotly- Waffle Chart and hover customization

Abhinav Kumar
7 min readFeb 24, 2023

--

Waffle Chart

A waffle chart is a data visualization technique that uses a grid-like structure to represent data. The chart is made up of squares or rectangles, and each square or rectangle represents a portion of the data being displayed. The size of each square or rectangle can be used to represent the magnitude of the data it represents, or it can be used to represent a fixed value.

Waffle charts are often used to display proportions or percentages, and they can be a useful alternative to pie charts or bar charts. When used effectively, waffle charts can help to make complex data more accessible and easier to understand.

About Visualization

The visualization displays the popularity of each day of the year as a person’s birthday. The visualization is based on data from the National Center for Health Statistics and covers the period from 2000 to 2014.

Data Preparation

Alright, let’s get this party started with some data preparation! We’re going to use data that has columns for year, month, date, and number of births on that date. To really spice things up, we’re going to pivot this data between month and date and take the average of births for each combination.

df = pd.read_csv("https://raw.githubusercontent.com/Abhinavk910/Data-Visualization/main/apps/Makeover_Mondays/Week_26_Birthday_usa/US_births_2000-2014_SSA.csv")

df = df.loc[:, ['month', 'date_of_month', 'births']]
heat_map_data = df.pivot_table(index='month', columns='date_of_month',
values = 'births')
z = heat_map_data.to_numpy()

Get ready for some serious data deliciousness, because we’re about to whip up a waffle chart in Plotly using just three lines of code! That’s right, this chart is going to be so sweet and savory, you’ll be drooling over your keyboard.

import plotly.graph_objects as go

fig = go.Figure(go.Heatmap(
x=[i for i in range(1, 32)], y=[i for i in range(1, 13)], z=z,
xgap=1, ygap=1
))

fig.show()

Alright, we’ve got a waffle chart on our hands, but let’s be real: the colors are about as exciting as plain oatmeal. And don’t even get me started on that two-way color bar. It’s time to put some pizzazz in this chart and make it pop like a disco ball.

We’re going to PINK THE WAFFLE UP! That’s right, we’re going to add some vibrant pink hues to our chart and make it the talk of the town. Get ready to make your colleagues’ jaws drop with envy when they see your bright and bold waffle chart. It’s time to get funky with some color and create a chart that’s as fun as it is informative. Let’s do this!

fig = go.Figure(go.Heatmap(
x=[i for i in range(1, 32)], y=[i for i in range(1, 13)], z=z,
xgap=1, ygap=1,
colorscale=[[0.0, '#FFF7F3'],
[0.5, "#FDE0DD"],
[0.61, "#FCC5C0"],
[0.71, "#FA9FB5"],
[0.81, "#F768A1"],
[0.85, "#DD3497"],
[0.91, "#AE017E"],
[0.95, "#7A0177"],
[1.0, "#49006A"]],
))

It’s time to take our chart to the next level and give it some serious style. We’ll ditch those drab background colors and replace them with something that’ll make our data shine. And as for those tick values, we’ll give them a makeover so they’re as easy on the eyes as they are informative.

fig.update_yaxes(
autorange="reversed",
tickvals=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12],
ticktext=['Jan. ', 'Feb. ', 'March ', 'April ', 'May ', 'June ',
'July ', 'Aug. ', 'Sep. ', 'Oct. ', 'Nov. ', 'Dec. '],
showgrid=False, zeroline=False, fixedrange=True, showline=False,
showdividers=False, showticklabels=True)

fig.update_xaxes(
side='top',
nticks=30,
tickvals=[i for i in range(1, 32)],
ticktext=[i for i in range(1, 32)],
showgrid=False, zeroline=False, fixedrange=True, showline=False,
ticks="outside", ticklen=5, tickcolor='#fff',
showdividers=False, showticklabels=True)

fig.update_layout(
plot_bgcolor="#fff",
font=dict(color='#999999'),
height=500, width = 1100,
margin=dict(t=150, l=10, r=10, b=10, pad=0)
)

Well folks, we’re almost there! Our waffle chart is looking better than ever, but there’s just one thing missing: a color bar that really pops. And let’s face it, the color bar sitting beside the waffle is about as exciting as watching paint dry.

So, let’s shake things up a bit and put that color bar at the top where it belongs. And while we’re at it, let’s add some serious pizzazz to it. We’re talking rainbows, unicorns, and all things sparkly. Okay, maybe not unicorns, but you get the idea.

Get ready for a chart that’s so dazzling, it’ll make your colleagues’ eyes water. We’re talking a color bar that’s as bold as it is beautiful, and a waffle chart that’s simply scrumptious. So, let’s get to it and create a visualization that will have everyone talking!

#For calculating min and max value in pivot, so that will use in tickvals
minMax = pd.melt(heat_map_data.reset_index(), id_vars='month')

fig.update_traces(colorbar_orientation='h',
colorbar_len=0.26,
colorbar_thickness=15,
colorbar_title='U.S Average Daily Birth: 2000-2014',
colorbar=dict(titleside='top',titlefont=dict(size=14,family='Arial')),
colorbar_xanchor='right',
colorbar_xpad=0,colorbar_x=1,
colorbar_y=1.01,
colorbar_tickvals=np.linspace(dd.value.min(), dd.value.max(),8+1),
colorbar_ticktext = ["", '<7K', '','', '9K','', '', '<12K'],
colorbar_ticklen=30,
colorbar_ticks='inside',
colorbar_tickcolor='#fff',
colorbar_tickwidth=1,
colorbar_tickangle=0,
colorbar_tickfont=dict(family="Courier New, monospace",
size=11,
color="#A5A5A5"))

Well, well, well, we did it! We managed to create an awesome colorbar that’s as dazzling as a disco ball. Sure, it took a bit of code to get there, but hey, no pain, no gain.

But you know what? Every good chart deserves a good heading. And since we’re already masters of coding, why not add some HTML into the mix? That’s right, we’re going to use some fancy-pants HTML code to give our chart a killer heading that’s as informative as it is stylish.

fig.update_layout(
title='<b><Span style="color:#787878;font-size:22px;">HOW POPULAR IS YOUR BIRTHDAY?</span></b>' +
'<i><Span style="color:#A5A5A5;font-size:13px;"><br>Two decades of American Birthdays, averaged by month and day</span>',
title_x=0.1,
title_y=0.8,
)

Hover Data Customization

Alright folks, we’ve spiced up the outer part of our chart and it’s looking mighty fine. But what about the inner beauty? What about the juicy details we get when we hover over each waffle square?

Oh boy, talk about an eyesore! Seeing x=10, y=Aug, and z with 4 decimal places is enough to make anyone cringe. But fear not, we can fix this.

It’s time to give our chart the makeover it deserves. We’ll make sure that x, y, and z are displayed in a way that’s clear, concise, and easy on the eyes. No more squinting or headaches from trying to decipher complicated data.

#Ranking day of a year based on mean number of births. 
ff = df.groupby(['month', 'date_of_month']).agg({'births': 'mean'}).reset_index()
ff['rank'] = ff.births.rank(method = 'first', ascending = 0).astype(int)

#Calculating Concieve Date
df['birth_date'] = pd.to_datetime(df.year*10000+df.month*100+df.date_of_month,format='%Y%m%d')
df['concieve_date'] = df.birth_date - datetime.timedelta(266)
df['concieve_date'] = df.concieve_date.apply(lambda x: x.strftime("%d/%b"))

#To get st and th after rank correctly
ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(n//10%10!=1)*(n%10<4)*n%10::4])

x = [i for i in range(1, 32)]
y = [i for i in range(1, 13)]
month_name = ['Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

hovertext = list()
for yi, yy in enumerate(y):
hovertext.append(list())
for xi, xx in enumerate(x):
try:
hovertext[-1].append('This date,<br><b>{}/{}</b>, had<br><b>{:,}</b><br />birth on<br>average. It<br>rank<br><b>{}</b>. The<br>conception<br>date* is<br><b>{}</b>.'.format(
xx, month_name[yy-1], int(z[yi][xi]), ordinal(ff[(ff.month == yy) & (ff.date_of_month == xx)]['rank'].unique()[0]), df[(df.month == yy) & (df.date_of_month == xx)]['concieve_date'].unique()[0]))
except:
hovertext[-1].append('')


#Adding text and hovertemplate this time in the go.Heatmap
fig = go.Figure(go.Heatmap(
x=[i for i in range(1, 32)], y=[i for i in range(1, 13)], z=z,
xgap=1, ygap=1,
colorscale=[[0.0, '#FFF7F3'],
[0.5, "#FDE0DD"],
[0.61, "#FCC5C0"],
[0.71, "#FA9FB5"],
[0.81, "#F768A1"],
[0.85, "#DD3497"],
[0.91, "#AE017E"],
[0.95, "#7A0177"],
[1.0, "#49006A"]],
text=hovertext,
hovertemplate='%{text}<extra></extra>'
))

fig.update_layout(
hoverlabel=dict(
bgcolor="white",
font_size=13,
font_family="Rockwell"
))

Well folks, there you have it! We’ve successfully created a waffle chart that’s as beautiful as it is informative. We’ve added some serious pizzazz to our color bar, given our chart a killer HTML heading, and made sure that our hover info boxes are packed with all the juicy details we need.

If you enjoyed this chart, then be sure to check out some of my previous creations, like my awesome bar chart and spine chart. Trust me, you won’t be disappointed!

And hey, if you liked what you saw here, why not follow me for more updates? I mean, who doesn’t love a good data visualization? We’ll explore the depths of charts, graphs, and plots together, and make sure that your next presentation is as engaging as it is informative.

Hit that follow button and let’s embark on a journey to data visualization bliss. I promise, it’ll be more fun than watching paint dry. And who knows, you might just learn a thing or two along the way. Let’s do this, amigos!

--

--

Abhinav Kumar
Abhinav Kumar

Written by Abhinav Kumar

Data enthusiast deeply passionate about power of data. Sifting through datasets and bringing insights to life through visualization is my idea of a good time.

No responses yet