📅  最后修改于: 2023-12-03 15:06:51.249000             🧑  作者: Mango
Squarify是Python中一个非常好用的可视化库,通过它我们可以方便地创建各种图形,包括树形图。 在本文中,我们将介绍使用Squarify创建树形图的过程,并提供Python代码示例。
在开始之前,请确保您已经安装了Squarify。 如果没有,请使用以下命令安装:
pip install squarify
在创建树形图之前,我们需要准备好数据,并将其存储在Python列表中。 每个节点应该是一个字典,包含以下键:
{
"name": 节点名称(字符串),
"parent": 父节点名称(字符串),如果没有父节点则填None,
"value": 节点值(浮点数)
}
例如,下面是我们将在本教程中使用的样本数据:
data = [
{"name": "Root", "parent": "", "value": 10},
{"name": "A", "parent": "Root", "value": 5},
{"name": "B", "parent": "Root", "value": 5},
{"name": "C", "parent": "A", "value": 2},
{"name": "D", "parent": "A", "value": 3},
{"name": "E", "parent": "B", "value": 1},
{"name": "F", "parent": "B", "value": 4},
{"name": "G", "parent": "E", "value": 1},
{"name": "H", "parent": "F", "value": 3},
{"name": "I", "parent": "F", "value": 1},
{"name": "J", "parent": "H", "value": 2},
{"name": "K", "parent": "H", "value": 1},
{"name": "L", "parent": "I", "value": 1},
{"name": "M", "parent": "I", "value": 1}
]
一旦我们准备好数据,我们就可以开始创建树形图了。 下面是使用Squarify创建树形图的基本步骤:
import squarify
nodes = {}
for d in data:
name = d['name']
parent = d['parent']
value = d['value']
if name not in nodes:
nodes[name] = {'value': 0}
nodes[name]['value'] += value
if parent not in nodes:
nodes[parent] = {'children': []}
nodes[parent]['children'].append(name)
def position(node, top, left, bottom, right, coordinates):
if 'children' in nodes[node]:
child_values = [nodes[child]['value'] for child in nodes[node]['children']]
total_child_value = sum(child_values)
child_ratio = [child_value/total_child_value for child_value in child_values]
child_bottom = [top + (bottom - top)*sum(child_ratio[:i+1]) for i in range(len(child_ratio))]
for idx, child in enumerate(nodes[node]['children']):
child_left = left + (right - left)*sum([child_ratio[i]/2 for i in range(idx)])
child_right = left + (right - left)*sum([child_ratio[i]/2 for i in range(idx+1)])
coordinates[child] = (top, child_left, child_bottom[idx], child_right)
position(child, *coordinates[child], coordinates)
else:
coordinates[node] = (top, left, bottom, right)
coordinates = {'Root': (0,0,100,100)}
position('Root', 0, 0, 100, 100, coordinates)
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(111, aspect="equal")
ax.axis("off")
for node in nodes:
top, left, bottom, right = coordinates[node]
if 'children' in nodes[node]:
ax.add_patch(plt.Rectangle((left,top),right-left,bottom-top,linewidth=1,edgecolor='black',facecolor='none'))
else:
ax.add_patch(plt.Rectangle((left,top),right-left,bottom-top,linewidth=1,edgecolor='black',facecolor='grey'))
x = left + (right - left) / 2
y = top + (bottom - top) / 2
ax.text(x, y, node, ha="center", va="center", color="white" if 'children' in nodes[node] else "black")
plt.show()
import squarify
import matplotlib.pyplot as plt
data = [
{"name": "Root", "parent": "", "value": 10},
{"name": "A", "parent": "Root", "value": 5},
{"name": "B", "parent": "Root", "value": 5},
{"name": "C", "parent": "A", "value": 2},
{"name": "D", "parent": "A", "value": 3},
{"name": "E", "parent": "B", "value": 1},
{"name": "F", "parent": "B", "value": 4},
{"name": "G", "parent": "E", "value": 1},
{"name": "H", "parent": "F", "value": 3},
{"name": "I", "parent": "F", "value": 1},
{"name": "J", "parent": "H", "value": 2},
{"name": "K", "parent": "H", "value": 1},
{"name": "L", "parent": "I", "value": 1},
{"name": "M", "parent": "I", "value": 1}
]
nodes = {}
for d in data:
name = d['name']
parent = d['parent']
value = d['value']
if name not in nodes:
nodes[name] = {'value': 0}
nodes[name]['value'] += value
if parent not in nodes:
nodes[parent] = {'children': []}
nodes[parent]['children'].append(name)
def position(node, top, left, bottom, right, coordinates):
if 'children' in nodes[node]:
child_values = [nodes[child]['value'] for child in nodes[node]['children']]
total_child_value = sum(child_values)
child_ratio = [child_value/total_child_value for child_value in child_values]
child_bottom = [top + (bottom - top)*sum(child_ratio[:i+1]) for i in range(len(child_ratio))]
for idx, child in enumerate(nodes[node]['children']):
child_left = left + (right - left)*sum([child_ratio[i]/2 for i in range(idx)])
child_right = left + (right - left)*sum([child_ratio[i]/2 for i in range(idx+1)])
coordinates[child] = (top, child_left, child_bottom[idx], child_right)
position(child, *coordinates[child], coordinates)
else:
coordinates[node] = (top, left, bottom, right)
coordinates = {'Root': (0,0,100,100)}
position('Root', 0, 0, 100, 100, coordinates)
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(111, aspect="equal")
ax.axis("off")
for node in nodes:
top, left, bottom, right = coordinates[node]
if 'children' in nodes[node]:
ax.add_patch(plt.Rectangle((left,top),right-left,bottom-top,linewidth=1,edgecolor='black',facecolor='none'))
else:
ax.add_patch(plt.Rectangle((left,top),right-left,bottom-top,linewidth=1,edgecolor='black',facecolor='grey'))
x = left + (right - left) / 2
y = top + (bottom - top) / 2
ax.text(x, y, node, ha="center", va="center", color="white" if 'children' in nodes[node] else "black")
plt.show()