소개
이 랩에서는 Python 의 Matplotlib 을 사용하여 팩 버블 차트 (packed-bubble chart) 를 만드는 방법을 배웁니다. 팩 버블 차트는 데이터의 크기를 버블의 크기로 나타내는 차트 유형입니다. 이 차트는 항목과 관련된 단일 숫자 값인 스칼라 데이터를 표시하는 데 유용합니다.
VM 팁
VM 시작이 완료되면 왼쪽 상단을 클릭하여 Notebook 탭으로 전환하여 실습을 위해 Jupyter Notebook에 액세스하십시오.
때로는 Jupyter Notebook 이 로딩을 완료하는 데 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업의 유효성 검사는 자동화할 수 없습니다.
학습 중에 문제가 발생하면 Labby 에게 문의하십시오. 세션 후 피드백을 제공해주시면 문제를 즉시 해결해 드리겠습니다.
필요한 라이브러리 가져오기
팩 버블 차트를 생성하려면 matplotlib.pyplot 및 numpy 라이브러리를 가져와야 합니다. numpy 라이브러리는 배열에 대한 수학적 연산을 수행하는 데 사용되며, 이는 버블 크기를 계산하는 데 유용합니다.
import matplotlib.pyplot as plt
import numpy as np
데이터 정의
이 예제에서 사용할 데이터는 다양한 데스크톱 브라우저의 시장 점유율입니다. 각 버블에 대한 브라우저 이름, 시장 점유율 및 색상을 포함하는 딕셔너리 (dictionary) 로 데이터를 정의합니다.
browser_market_share = {
'browsers': ['firefox', 'chrome', 'safari', 'edge', 'ie', 'opera'],
'market_share': [8.61, 69.55, 8.36, 4.12, 2.76, 2.43],
'color': ['#5A69AF', '#579E65', '#F9C784', '#FC944A', '#F24C00', '#00B825']
}
BubbleChart 클래스 정의
BubbleChart 클래스는 팩 버블 차트를 생성하는 데 사용됩니다. 이 클래스는 버블 면적의 배열과 버블 간격 값을 입력으로 받습니다. __init__ 메서드는 버블의 초기 위치를 설정하고 최대 단계 거리 (각 버블이 단일 반복에서 이동할 수 있는 거리) 를 계산합니다.
class BubbleChart:
def __init__(self, area, bubble_spacing=0):
"""
Setup for bubble collapse.
Parameters
----------
area : array-like
Area of the bubbles.
bubble_spacing : float, default: 0
Minimal spacing between bubbles after collapsing.
Notes
-----
If "area" is sorted, the results might look weird.
"""
area = np.asarray(area)
r = np.sqrt(area / np.pi)
self.bubble_spacing = bubble_spacing
self.bubbles = np.ones((len(area), 4))
self.bubbles[:, 2] = r
self.bubbles[:, 3] = area
self.maxstep = 2 * self.bubbles[:, 2].max() + self.bubble_spacing
self.step_dist = self.maxstep / 2
## calculate initial grid layout for bubbles
length = np.ceil(np.sqrt(len(self.bubbles)))
grid = np.arange(length) * self.maxstep
gx, gy = np.meshgrid(grid, grid)
self.bubbles[:, 0] = gx.flatten()[:len(self.bubbles)]
self.bubbles[:, 1] = gy.flatten()[:len(self.bubbles)]
self.com = self.center_of_mass()
버블 이동 메서드 정의
BubbleChart 클래스는 또한 버블을 질량 중심 (center of mass) 으로 이동하고 다른 버블과의 충돌을 확인하는 메서드를 포함합니다. center_of_mass 메서드는 모든 버블의 질량 중심을 계산하고, center_distance 메서드는 버블과 질량 중심 사이의 거리를 계산합니다. outline_distance 메서드는 버블의 외곽선과 다른 버블의 외곽선 사이의 거리를 계산하고, check_collisions 메서드는 새로운 버블 위치가 다른 버블과 충돌하는지 확인합니다.
def center_of_mass(self):
return np.average(
self.bubbles[:, :2], axis=0, weights=self.bubbles[:, 3]
)
def center_distance(self, bubble, bubbles):
return np.hypot(bubble[0] - bubbles[:, 0],
bubble[1] - bubbles[:, 1])
def outline_distance(self, bubble, bubbles):
center_distance = self.center_distance(bubble, bubbles)
return center_distance - bubble[2] - \
bubbles[:, 2] - self.bubble_spacing
def check_collisions(self, bubble, bubbles):
distance = self.outline_distance(bubble, bubbles)
return len(distance[distance < 0])
버블 충돌 메서드 정의
BubbleChart 클래스는 또한 버블 충돌을 확인하고 충돌하는 버블 주변을 이동하는 메서드를 포함합니다. collides_with 메서드는 새로운 버블 위치와 다른 버블의 위치 사이의 거리를 계산합니다. 거리가 0 보다 작으면 충돌이 발생한 것이며, 이 메서드는 충돌하는 버블의 인덱스를 반환합니다. collapse 메서드는 버블을 질량 중심 (center of mass) 으로 이동시키고 충돌하는 버블 주변을 이동시키며, plot 메서드는 차트에 버블을 그립니다.
def collides_with(self, bubble, bubbles):
distance = self.outline_distance(bubble, bubbles)
idx_min = np.argmin(distance)
return idx_min if type(idx_min) == np.ndarray else [idx_min]
def collapse(self, n_iterations=50):
"""
Move bubbles to the center of mass.
Parameters
----------
n_iterations : int, default: 50
Number of moves to perform.
"""
for _i in range(n_iterations):
moves = 0
for i in range(len(self.bubbles)):
rest_bub = np.delete(self.bubbles, i, 0)
## try to move directly towards the center of mass
## direction vector from bubble to the center of mass
dir_vec = self.com - self.bubbles[i, :2]
## shorten direction vector to have length of 1
dir_vec = dir_vec / np.sqrt(dir_vec.dot(dir_vec))
## calculate new bubble position
new_point = self.bubbles[i, :2] + dir_vec * self.step_dist
new_bubble = np.append(new_point, self.bubbles[i, 2:4])
## check whether new bubble collides with other bubbles
if not self.check_collisions(new_bubble, rest_bub):
self.bubbles[i, :] = new_bubble
self.com = self.center_of_mass()
moves += 1
else:
## try to move around a bubble that you collide with
## find colliding bubble
for colliding in self.collides_with(new_bubble, rest_bub):
## calculate direction vector
dir_vec = rest_bub[colliding, :2] - self.bubbles[i, :2]
dir_vec = dir_vec / np.sqrt(dir_vec.dot(dir_vec))
## calculate orthogonal vector
orth = np.array([dir_vec[1], -dir_vec[0]])
## test which direction to go
new_point1 = (self.bubbles[i, :2] + orth *
self.step_dist)
new_point2 = (self.bubbles[i, :2] - orth *
self.step_dist)
dist1 = self.center_distance(
self.com, np.array([new_point1]))
dist2 = self.center_distance(
self.com, np.array([new_point2]))
new_point = new_point1 if dist1 < dist2 else new_point2
new_bubble = np.append(new_point, self.bubbles[i, 2:4])
if not self.check_collisions(new_bubble, rest_bub):
self.bubbles[i, :] = new_bubble
self.com = self.center_of_mass()
if moves / len(self.bubbles) < 0.1:
self.step_dist = self.step_dist / 2
def plot(self, ax, labels, colors):
"""
Draw the bubble plot.
Parameters
----------
ax : matplotlib.axes.Axes
labels : list
Labels of the bubbles.
colors : list
Colors of the bubbles.
"""
for i in range(len(self.bubbles)):
circ = plt.Circle(
self.bubbles[i, :2], self.bubbles[i, 2], color=colors[i])
ax.add_patch(circ)
ax.text(*self.bubbles[i, :2], labels[i],
horizontalalignment='center', verticalalignment='center')
BubbleChart 객체 생성 및 차트 플롯
패킹된 버블 차트를 생성하려면, BubbleChart 객체를 생성하고 collapse 메서드를 호출하여 버블을 질량 중심 (center of mass) 으로 이동시켜야 합니다. 그런 다음 matplotlib figure 를 생성하고 axes 객체를 추가할 수 있습니다. 마지막으로, plot 메서드를 호출하여 차트에 버블을 그립니다.
bubble_chart = BubbleChart(area=browser_market_share['market_share'],
bubble_spacing=0.1)
bubble_chart.collapse()
fig, ax = plt.subplots(subplot_kw=dict(aspect="equal"))
bubble_chart.plot(
ax, browser_market_share['browsers'], browser_market_share['color'])
ax.axis("off")
ax.relim()
ax.autoscale_view()
ax.set_title('Browser market share')
plt.show()
요약
이 랩에서는 Python 의 Matplotlib 을 사용하여 패킹된 버블 차트를 만드는 방법을 배웠습니다. 브라우저 이름, 시장 점유율 및 각 버블의 색상을 포함하는 딕셔너리 형태로 데이터를 정의했습니다. 그런 다음 BubbleChart 클래스를 생성하여 버블의 초기 위치를 설정하고, 최대 이동 거리를 계산하고, 버블을 질량 중심 (center of mass) 으로 이동시키고, 다른 버블과의 충돌을 확인했습니다. 마지막으로, matplotlib을 사용하여 차트를 플롯했습니다.