Circle Packing using Circlify
Data Visualization
As mentioned in the instructions, all materials can be open in Colab
as Jupyter notebooks. In this way users can run the code in the cloud. It is highly recommanded to follow the tutorials in the right order.
This notebook aims to introduce users some practical skills on generating a circle packing chart.
Presumptions:
Not applicable.
! pip install circlify
from pprint import pprint as pp
import circlify as circ
surname = """
王 李 張 趙 劉 陳 楊 吳 黃 朱 孫 郭 胡 呂 高 宋 徐 程 林 鄭 范 何 韓 曹 馬 許 田 馮 杜 周 曾 汪 蘇 董 方 蔡 梁 石 謝 賈 薛 彭 崔 唐 潘 鄧 任 史 錢 侯 魏 羅 葉 沈 孟 姚 傅 丁 章 蕭 蔣 盧 陸 袁 江 晁 譚 邵 歐陽 孔 俞 尹 廖 閻 洪 夏 雷 葛 文 柳 陶 毛 丘 龔 康 蒲 邢 郝 龐 安 裴 折 施 游 金 鄒 湯 虞 嚴 鍾
"""
import re
surname = list(re.sub("\s+", "", surname.strip()))
surname[:5]
surname.reverse()
len(surname)
import pandas as pd
import numpy as np
df = pd.DataFrame({
'surname': surname,
'weight': 5*np.arange(1,102)
})
import circlify
# compute circle positions:
circles = circlify.circlify(
df['weight'].tolist(),
target_enclosure=circlify.Circle(x=0, y=0, r=1),
show_enclosure=False
)
len(df.weight)
import math
import numpy as np
x = np.array([cir.x for cir in circles])
y = np.array([cir.y for cir in circles])
r = np.array([cir.r for cir in circles])
bubble_df = pd.DataFrame({
'x': x,
'y': y,
'r': r,
'l': df.sort_values('weight').surname.values,
's': (math.pi)*(r**2)
})
!wget -O TaipeiSansTCBeta-Regular.ttf https://drive.google.com/uc?id=1eGAsTN1HBpJAkeVM57_C7ccp7hbgSz3_&export=download
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.font_manager import fontManager
fontManager.addfont('TaipeiSansTCBeta-Regular.ttf')
mpl.rc('font', family='Taipei Sans TC Beta')
import circlify
import numpy as np
import random
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.colors import ListedColormap
palette = ["#CD5C5C","#F08080","#E9967A","#FFA07A","#C04000","#FF5F1F","#B22222","#660000","#C21E56"]
# Create just a figure and only one subplot
fig, ax = plt.subplots(figsize=(10,10))
# Title
ax.set_title('宋朝人口姓氏期望分佈', fontsize=26)
# Remove axes
ax.axis('off')
# Find axis boundaries
lim = max(
max(
abs(circle.x) + circle.r,
abs(circle.y) + circle.r,
)
for circle in circles
)
plt.xlim(-lim, lim)
plt.ylim(-lim, lim)
# list of labels
labels = df.sort_values('weight').surname.values
# print circles
for circle, label in zip(circles, labels):
x, y, r = circle
ax.add_patch(plt.Circle((x, y), r, alpha=0.6, linewidth=1, facecolor=random.choice(palette), edgecolor="white"))
plt.annotate(
label,
(x,y) ,
va='center',
ha='center',
fontsize=300*r,
color="black"
)
bubble_df["rank"] = bubble_df.sort_values(by="r", ascending=False).index
bubble_df.head()
font_size = 250*bubble_df.r.values
import plotly.express as px
fig = px.scatter(bubble_df, x="x", y="y", custom_data=["l","rank"], color="x", width=800, height=700,
size="s", hover_name="l", size_max=45, text="l")
fig.update(layout_coloraxis_showscale=False)
fig.update_traces(
hovertemplate="<br>".join([
"Surname: %{customdata[0]}",
"Ranking: %{customdata[1]}"
])
)
fig.update_layout(showlegend=False)
fig.update_xaxes(visible=False)
fig.update_yaxes(visible=False)
fig.update_yaxes(
scaleanchor = "x",
scaleratio = 0.95,
)
fig.update_layout({
'plot_bgcolor': 'rgba(0, 0, 0, 0)',
'paper_bgcolor': 'rgba(0, 0, 0, 0)',
})
fig.update_layout(
title={
'text': "<b>宋朝人口姓氏期望分佈</b>",
'y':0.97,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'},
font=dict(
family="Courier New, monospace",
size=18,
color="black"
)
)
fig.update_traces(textfont_size=font_size)
fig.show()
Additional information
This notebook is provided for educational purpose and feel free to report any issue on GitHub.
Author: Ka Hei, Chow
License: The code in this notebook is licensed under the Creative Commons by Attribution 4.0 license.
Last modified: December 2021