이번 포스팅에서는 Python의 Plotly 모듈을 이용해서 클리브랜드 점 그래프 (Cleveland Dot Plot in Python using Plotly) 그리는 방법을 소개하겠습니다. 

 

Cleveland and McGill (1984) 이  “Graphical Methods for Data Presentation: Full Scale Breaks, Dot Charts, and Multibased Logging.” 이라는 논문에서 막대 그래프 대비 점 그래프가 데이터 해석, 가독성에서 가지는 우수성을 소개하면서 Cleveland Dot Plot 이라고도 많이 불리는 그래프입니다.

 

예제로 사용할 데이터로, "학교(schools)" 범주형 변수의 졸업생 별 남성(men)과 여성(women)의 수입(earning) 데이터로 pandas DataFrame을 만들어보겠습니다. 

 

## making a sample pandas DataFrame
import pandas as pd

df = pd.DataFrame({
    'schools': [
        "Brown", "NYU", "Notre Dame", "Cornell", "Tufts", "Yale",
        "Dartmouth", "Chicago", "Columbia", "Duke", "Georgetown",
        "Princeton", "U.Penn", "Stanford", "MIT", "Harvard"],
    'earnings_men': [
        92, 94, 100, 107, 112, 114, 114, 118, 119, 124, 131, 137, 141, 151, 152, 165], 
    'earnings_women': [
        72, 67, 73, 80, 76, 79, 84, 78, 86, 93, 94, 90, 92, 96, 94, 112]
})



print(df)
#        schools  earnings_men  earnings_women
# 0        Brown            92              72
# 1          NYU            94              67
# 2   Notre Dame           100              73
# 3      Cornell           107              80
# 4        Tufts           112              76
# 5         Yale           114              79
# 6    Dartmouth           114              84
# 7      Chicago           118              78
# 8     Columbia           119              86
# 9         Duke           124              93
# 10  Georgetown           131              94
# 11   Princeton           137              90
# 12      U.Penn           141              92
# 13    Stanford           151              96
# 14         MIT           152              94

# 15     Harvard           165             112

 

 

Plotly 의 graph_objects 메소드를 사용해서 졸업한 학교(schools) 별 남성의 수입(earnings_men)과 여성의 수입(earnings_women) 에 대해서 점으로 마킹을 하고 수입을 텍스트로 표기 (mode="markers + text") 하여 클리브랜드 점 그래프 (Cleveland Dot Plot)을 그려보겠습니다. 

 

import plotly.graph_objects as go

fig = go.Figure()

## Dot Plot for Men
fig.add_trace(go.Scatter(
    x=df['earnings_men'],
    y=df['schools'],
    marker=dict(color="red", size=10),
    mode="markers + text",
    name="Men",
    text=df['earnings_men'],
    textposition="middle right"
))

## Dot Plot for Women
fig.add_trace(go.Scatter(
    x=df['earnings_women'],
    y=df['schools'],
    marker=dict(color="blue", size=10),
    mode="markers + text",
    name="Women",
    text=df['earnings_women'],
    textposition="middle left"
))

## title and axis title
fig.update_layout(
    title="Earnings by School and Gender",
    xaxis_title="Annual Salary (in thousands)",
    yaxis_title="School")


fig.show()

Cleveland Dot Plot in Python using Plotly

 

Plotly 그래프는 interactive mode 로서 마우스 커서를 그래프에 가져다대면 해당 점의 정보가 팝업으로 나타나서 편리하게 볼 수 있습니다. 

 

R의 ggplot2 패키지를 이용한 클리브랜드 점 그래프 (Cleveland Dot Plot in R using ggplot2) 그리는 방법은 https://rfriend.tistory.com/75 를 참고하세요. 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python 의 Plotly 모듈을 사용해서 

 

(1) 3차원 산점도 그리기 (3D Scatter Plot using Plotly)

(2) 3차원 표면도 그리기 (3D Surface Plot using Plotly) 

 

하는 방법을 소개하겠습니다 

 

 

 

(1) 3차원 산점도 그리기 (3D Scatter Plot using Plotly)

 

3차원 산점도는 x, y, z 의 3개 축을 기준으로 3차원의 공간에 산점도를 그려서 3개 변수들 간의 관계를 분석하기 위해서 사용합니다. 마커의 크기와 색깔을 달리해서 4번째 변수의 특성을 3차원 산점도에 추가해서 그릴 수도 있습니다. 

 

Scatter3D trace 는 go.Scatter3D() 함수에 의해 반환되는 그래프 객체입니다. 3차원 산점도이기 때문에 x, y, z 의 좌표값을 반드시 넣어줘야 하며, 이들 값은 리스트(List) 또는 Array 객체를 사용합니다. 

 

아래는 싸인과 코싸인 값을 이용해서 3차원 산점도를 그려본 예입니다. 

 

import plotly.graph_objs as go
import numpy as np

z = np.linspace(0, 10, 50)
x = np.cos(z)
y = np.sin(z)

trace = go.Scatter3d(
   x = x, 
   y = y, 
   z = z,
   mode = 'markers', 
   marker = dict(
      size = 12,
      color = z, 
      colorscale = 'Bluered_r'
      )
   )

layout = go.Layout(title = '3차원 산점도 (3D Scatter plot)')

fig = go.Figure(data = [trace], layout = layout)

fig.show()

3D Scatter Plot in Python using Plotly

 

 

 

(2) 3차원 표면도 그리기 (3D Surface Plot using Plotly) 

 

3차원 표면도는 위도(x, latitude), 경도(y, longitude), 고도(z, altitude) 의 3차원 데이터를 그래프로 표현한 것입니다. 이때 3차원 데이터 값을 개별 점(indivisual points)으로 표현한 대신에 표면(surface)으로 표현하여서 3차원 데이터 간의 관계를 분석할 때 사용합니다.

 

이때 위도(x, latitude), 경도(y, longitude)는 독립변수(indepedent variable)이 되고, 고도(z, altitude)는 종속변수(dependent variable) 가 됩니다. 

 

아래 예는 Plotly의 graph_objs 메소드 중에서 go.Surface() 메소드를 사용해서 3차원 표면도를 그려면 것입니다. 

 

import numpy as np
import plotly.graph_objs as go

x = np.outer(np.linspace(-2, 2, 30), np.ones(30))
y = x.copy().T # transpose
z = np.cos(x ** 2 + y ** 2)

trace = go.Surface(x = x, y = y, z =z )
data = [trace]

layout = go.Layout(title = '3차원 표면도 (3D Surface Plot)')

fig = go.Figure(data = data, layout=layout)

fig.show()

 

 

Plotly 그래프는 interactive mode 를 지원하기 때문에 마우스 커서를 그래프 위에 가져가면 해당 좌표의 정보가 팝업으로 나타납니다. 그리고 커서를 클릭해서 위-아래-좌-우 방향으로 이동하면 3차원 표면도가 방향이 돌아가기 때문에 입체적으로 3차원 표면을 관찰할 수 있는 장점이 있습니다. 

 

 

[Reference]

* Plotly - 3D Scatter and Surface Plot
 : https://www.tutorialspoint.com/plotly/plotly_3d_scatter_and_surface_plot.htm

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다 .

행복한 데이터 과학자 되세요!  :-)

 

 

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python 을 이용해서 의사결정나무 (Decision Tree) 를 시각화하는 3가지 방법을 소개하겠습니다. 

 

(1) sklearn.tree.export_text 메소드를 이용해서 의사결정나무를 텍스트로 인쇄하기 (text representation)

(2) sklearn.tree.plot_tree 메소드와 matplotlib 을 이용해서 의사결정나무 시각화

(3) sklearn.tree.export_graphviz 메소드와 graphviz 를 이용해서 의사결정나무 시각화

 

 

먼저, 예제로 사용할 iris 데이터셋과 필요한 모듈을 불어오겠습니다. 

 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 

df = pd.DataFrame({
    'x1': [1, 2, 2, 2, 2, 3, 3, 4, 5, 5], 
    'x2': [2, 2, 3, 4, 5, 4, 6, 3, 2, 5], 
    'cat': [0, 1, 1, 0, 0, 1, 0, 1, 1, 0]
})


df

# x1	x2	cat
# 0	1	2	0
# 1	2	2	1
# 2	2	3	1
# 3	2	4	0
# 4	2	5	0
# 5	3	4	1
# 6	3	6	0
# 7	4	3	1
# 8	5	2	1
# 9	5	5	0


## scatter plot
import seaborn as sns

plt.figure(figsize=(7, 7))
sns.scatterplot(x='x1', y='x2', hue='cat', style='cat', s=100, data=df)
plt.show()

scatter plot by group

 

 

 

(0) sklearn.tree 메소드를 이용해서 의사결정나무(Decision Tree) 모델 훈련하기

 

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
from sklearn import tree

## getting X, y values
X = df[['x1', 'x2']]
y = df['cat']

## initiating DecisionTreeClassifer method
dt_clf = DecisionTreeClassifier(random_state = 1004)


## fitting a decision tree classifier
dt_clf_model = dt_clf.fit(X, y)


## feature importances
dt_clf_model.feature_importances_

#array([0.43809524, 0.56190476])

 

 

 

(1) sklearn.tree.export_text 메소드를 이용해서 의사결정나무를 텍스트로 인쇄하기 (text representation)

 

의사결정나무 모델을 적합한 후에 사용자 인터페이스가 없는 애플리케이션에서 로그(log) 텍스트로 모델 적합 결과를 확인할 때 사용할 수 있습니다. 또는 의사결정나무의 적합된 룰을 SQL 로 구현하여 운영 모드로 적용하고자 할 때 아래처럼 텍스트로 인쇄를 하면 유용하게 사용할 수 있습니다. 

 

## Text Representation
dt_clf_model_text = tree.export_text(dt_clf_model)

print(dt_clf_model_text)

|--- feature_1 <= 4.50
|   |--- feature_0 <= 1.50
|   |   |--- class: 0
|   |--- feature_0 >  1.50
|   |   |--- feature_1 <= 3.50
|   |   |   |--- class: 1
|   |   |--- feature_1 >  3.50
|   |   |   |--- feature_0 <= 2.50
|   |   |   |   |--- class: 0
|   |   |   |--- feature_0 >  2.50
|   |   |   |   |--- class: 1
|--- feature_1 >  4.50
|   |--- class: 0

 

 

 

(2) sklearn.tree.plot_tree 메소드와 matplotlib 을 이용해서 의사결정나무 시각화

 

(3)번 처럼 Graphviz 를 설치하지 않아도, matplotlib 을 사용해서 간편하게 의사결정나무를 시각화 할 때 유용합니다. 편리한 대신에 (3)번 Graphviz 대비 자유도가 떨어지는 단점이 있습니다. 

 

## Plot Tree with plot_tree
fig = plt.figure(figsize=(15, 8))
_ = tree.plot_tree(dt_clf_model, 
                  feature_names=['x1', 'x2'],
                  class_names=['0', '1'],
                  filled=True)

 

 

 

(3) sklearn.tree.export_graphviz 메소드와 graphviz 를 이용해서 의사결정나무 시각화

 

Graphviz 의 시각화 기능을 fully 사용할 수 있으므로 매우 강력한 시각화 방법이라고 할 수 있습니다. 

Graphviz 설치하고 Decision Tree 시각화하기는 https://rfriend.tistory.com/382 를 참고하세요. 

DOT language 에 대해서는 https://graphviz.org/doc/info/lang.html 를 참고하세요. 

 

## Visualizing Tree using Graphviz
from sklearn import tree
import graphviz

## exporting tree in DOT format
## refer to: https://scikit-learn.org/stable/modules/generated/sklearn.tree.export_graphviz.html
tree_dot = tree.export_graphviz(
    dt_clf_model, 
    feature_names=['x1', 'x2'], 
    class_names=['0', '1'],
    filled=True
)


## draw graph using Graphviz
dt_graph = graphviz.Source(tree_dot, format='png')
dt_graph

 

decition tree visualization using graphviz

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요~!

 

 

728x90
반응형
Posted by Rfriend
,

시각화를 하다보면 기존의 그래프에 가독성을 높이기 위해 여러가지 종류의 도형을 추가해야 할 때가 있습니다.  Python  matplotlib.artist 의 Patch 클래스는 아래의 화면 캡쳐에서 보는 것처럼 Shadow, Spine, Wedge, Circle, Ellipse, Arrow, Rectangle, RegularPolygon, FancyArrowPatch, PathPatch 등의 다양한 도형을 쉽게 그릴 수 있는 클래스를 지원합니다. 

 

 

[ matplotlib artist inheritance diagrams, reference for matplotlib artists ]

 

matplotlib.artist Inheritance Diagrams and Reference for Matplotlib artists (* source: matplotlib.org)

 

이들 Reference for Matplotlib artists 중에서 이번 포스팅에서는 matplotlib의 add_patch() 함수matplotlib.patches 클래스의 다양한 artists 를 사용해서 

 

(1) matplotlib 그래프에 직사각형 추가하기 (adding a Rectangle in matplotlib's plot)

(2) matplotlib 그래프에 원 추가하기 (adding a Circle in matplotlib's plot)

(3) matplotlib 그래프에 타원 추가하기 (adding a Ellipse in matplotlib's plot)

(4) matplotlib 그래프에 다각형 추가하기 (adding a Polygon in matplotlib's plot)

(5) matplotlib 그래프에 화살표 추가하기 (adding a Arrow in matplotlib's plot)

 

하는 방법을 소개하겠습니다. 

 

 

먼저, 시각화를 위해 필요한 Python 모듈을 불러오고, 예제로 사용할 간단한 샘플 데이터셋을 만들어보겠습니다. 

 

## importing modules for visualization and data generation
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np


## generating sample datasets
np.random.seed(1004)
x1 = np.random.uniform(low=1.5, high=4.5, size=100)
y1 = np.random.uniform(low=1.5, high=2.5, size=100)
x2 = np.random.normal(loc=7, scale=0.6, size=100)
y2 = np.random.normal(loc=7, scale=0.6, size=100)
x = np.concatenate((x1, x2), axis=0)
y = np.concatenate((y1, y2), axis=0)

 

 

(1) matplotlib 그래프에 직사각형 추가하기 (adding a Rectangle in matplotlib's plot)

 

코드가 추가적인 설명이 필요 없을 정도로 간단하므로 예제 코드와 그 결과로 그려진 그래프 & 추가된 도형 위에 matplotlib.matches 클래스의 각 artist 별 매개변수를 표기해놓는 것으로 설명을 갈음하겠습니다. 

 

import matplotlib.pyplot as plt
import matplotlib.patches as patches

## plotting
fig, ax = plt.subplots(figsize=(7, 7))
ax.set_title('Adding a Rectangle in plot', fontsize=16)
ax.set_xlim(0.0, 10.0)
ax.set_ylim(0.0, 10.0)
ax.set_xlabel('X')
ax.set_ylabel('Y')

ax.plot(x, y, 'ro', alpha=0.5)

## (1) a Rectangle patch
## https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Rectangle.html
ax.add_patch(
   patches.Rectangle(
       (1.0, 1.0),      # (x, y) coordinates of left-bottom corner point
       4, 2,            # width, height
       edgecolor = 'blue',
       linestyle = 'dashed', 
       fill = True,
       facecolor = 'yellow',
   ))

plt.show()

adding a patch of a rectangle in matplotlib

 

 

 

(2) matplotlib 그래프에 원 추가하기 (adding a Circle in matplotlib's plot)

 

import matplotlib.pyplot as plt
import matplotlib.patches as patches

## plotting
fig, ax = plt.subplots(figsize=(7, 7))
ax.set_title('Adding a Circle in plot', fontsize=16)
ax.set_xlim(0.0, 10.0)
ax.set_ylim(0.0, 10.0)
ax.set_xlabel('X')
ax.set_ylabel('Y')

ax.plot(x, y, 'ro', alpha=0.5)

## (2) a Circle patch
## https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Circle.html
ax.add_patch(
   patches.Circle(
       (7.0, 7.0),      # (x, y) coordinates of center point
       radius = 2.,     # radius
       edgecolor = 'black',
       linestyle = 'dotted', 
       fill = True,
       facecolor = 'lightgray',
   ))

plt.show()

adding a patch of a circle in matplotlib

 

 

 

(3) matplotlib 그래프에 타원 추가하기 (adding a Ellipse in matplotlib's plot)

 

import matplotlib.pyplot as plt
import matplotlib.patches as patches

## plotting
fig, ax = plt.subplots(figsize=(7, 7))
ax.set_title('Adding an Ellipse in plot', fontsize=16)
ax.set_xlim(0.0, 10.0)
ax.set_ylim(0.0, 10.0)
ax.set_xlabel('X')
ax.set_ylabel('Y')

ax.plot(x, y, 'ro', alpha=0.5)

## (3) A scale-free ellipse.
## https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Ellipse.html
ax.add_patch(
   patches.Ellipse(
       xy = (5, 5), # xy xy coordinates of ellipse centre.
       width = 5,   # width Total length (diameter) of horizontal axis.
       height = 10, # height Total length (diameter) of vertical axis.
       angle = -40, # angle Rotation in degrees anti-clockwise. 0 by default
       edgecolor = 'black',
       linestyle = 'solid', 
       fill = True,
       facecolor = 'yellow',
   ))

plt.show()

adding a patch of an ellipse in matplotlib

 

 

 

(4) matplotlib 그래프에 다각형 추가하기 (adding a Polygon in matplotlib's plot)

 

다각형(Polygon)을 추가하려면 다각형의 각 꼭지점의 xy 좌표의 모음을 numpy array 형태로 입력해주면 됩니다. 그리고 closed=True 를 설정해주면 xy 좌표들의 모음의 처음 좌표와 마지막 좌표를 연결해서 다각형의 닫아주어서 완성해줍니다. 

 

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np

## plotting
fig, ax = plt.subplots(figsize=(7, 7))
ax.set_title('Adding a Polygon in plot', fontsize=16)
ax.set_xlim(0.0, 10.0)
ax.set_ylim(0.0, 10.0)
ax.set_xlabel('X')
ax.set_ylabel('Y')

ax.plot(x, y, 'ro', alpha=0.5)

## (4) a Polygon patch
## https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Polygon.html
ax.add_patch(
   patches.Polygon(
       # xy is a numpy array with shape Nx2.
       np.array([[1, 1], [5, 1], [9, 5], [9, 9], [6, 9], [1, 4]]), # xy
       closed=True,
       edgecolor = 'black',
       linestyle = 'dashdot', 
       fill = True,
       facecolor = 'lightgray',
   ))

plt.show()

adding a patch of a polygon in matplotlib

 

 

 

(5) matplotlib 그래프에 화살표 추가하기 (adding a Arrow in matplotlib's plot)

 

import matplotlib.pyplot as plt
import matplotlib.patches as patches

## plotting
fig, ax = plt.subplots(figsize=(7, 7))
ax.set_title('Adding an Arrow in plot', fontsize=16)
ax.set_xlim(0.0, 10.0)
ax.set_ylim(0.0, 10.0)
ax.set_xlabel('X')
ax.set_ylabel('Y')

ax.plot(x, y, 'ro', alpha=0.5)

## (5) a Arrow patch
## https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Arrow.html
ax.add_patch(
   patches.Arrow(
       x = 3, # x coordinate of the arrow tail.
       y = 5, # y coordinate of the arrow tail.
       dx = 0, # dx Arrow length in the x direction.
       dy = -2, # dy Arrow length in the y direction.
       # width: Scale factor for the width of the arrow. 
       width = 1, # With a default value of 1, the tail width is 0.2 and head width is 0.6.
       edgecolor = 'black',
       linestyle = 'solid', 
       fill = True,
       facecolor = 'yellow',
   ))

plt.show()

adding a patch of an arrow in matplotlib

 

 

 

[ Reference ]

* Python matplotlib's Inheritance Diagrams 

   : https://matplotlib.org/stable/api/artist_api.html#artist-api

* Reference for matplotlib artists

   : https://matplotlib.org/stable/gallery/shapes_and_collections/artist_reference.html#sphx-glr-gallery-shapes-and-collections-artist-reference-py 

* Python matplotlib's Rectangle patch
   : https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Rectangle.html

* Python matplotlib's Circle patch
   : https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Circle.html

* Python matplotlib's scale-free Ellipse
   : https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Ellipse.html

* Python matploblib's Polygon patch
   : https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Polygon.html

* Python matplotlib's Arrow patch
   : https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Arrow.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

산점도 (Scatter plot) 가 두 변수 간의 관계를 2차원(2D으로 시각화해서 볼 수 있는 그래프라면, 버블 그래프(Bubble chart)는 산점도에 버블의 크기와 색깔을 추가하여 3차원(3D) 또는 4차원(4D)의 정보를 2차원에 시각화해서 볼 수 있는 그래프입니다. 그리고 시간 축을 추가하여 애니메이션 형태의 버블 그래프를 그린다면 5차원(5D)의 시각화도 가능합니다. 

 

이번 포스팅에서는 Python의 matplotlib, seaborn, plotly, bubbly 등의 시각화 모듈을 이용해서 버블 그래프를 그리는 방법을 소개하겠습니다. 

 

(1) matplotlib 으로 버블 그래프 그리기 (Bubble chart using Matplotlib)

(2) seaborn 으로 버블 그래프 그리기 (Bubble chart using Seaborn)

(3) plotly 로 동적인 버블 그래프 그리기 (Interactive Bubble chart using Plotly)

(4) bubbly 로 시간의 흐름에 따라 변화하는 버블 그래프 그리기 (Animated Bubble chart using bubbly)

 

 

plotly 모듈에 들어있는 Gapminder  Global Indicator 데이터셋을 대상으로 버블 그래프를 그려보겠습니다. x 축에는 gpdPercap, y 축에는 lifeExp 를 사용하겠으며, pop 에 비례해서 버블의 크기를 조절하고, continent 에 따라서 버블의 색깔을 다르게 해보겠습니다. 

 

## importing modules
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import pandas as pd
import numpy as np

## getting dataset
df = px.data.gapminder()


df.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 1704 entries, 0 to 1703
# Data columns (total 8 columns):
#  #   Column     Non-Null Count  Dtype  
# ---  ------     --------------  -----  
#  0   country    1704 non-null   object 
#  1   continent  1704 non-null   object 
#  2   year       1704 non-null   int64  
#  3   lifeExp    1704 non-null   float64
#  4   pop        1704 non-null   int64  
#  5   gdpPercap  1704 non-null   float64
#  6   iso_alpha  1704 non-null   object 
#  7   iso_num    1704 non-null   int64  
# dtypes: float64(2), int64(3), object(3)
# memory usage: 106.6+ KB


df.head(3)
# 	country	continent	year	lifeExp	pop	gdpPercap	iso_alpha	iso_num
# 0	Afghanistan	Asia	1952	28.801	8425333	779.445314	AFG	4
# 1	Afghanistan	Asia	1957	30.332	9240934	820.853030	AFG	4
# 2	Afghanistan	Asia	1962	31.997	10267083	853.100710	AFG	4


df.year.max() # ==> keep year 2007
# 2007


df.gdpPercap.describe()   # right-skewed => log scaling
# count      1704.000000
# mean       7215.327081
# std        9857.454543
# min         241.165877dd
# 25%        1202.060309
# 50%        3531.846989
# 75%        9325.462346
# max      113523.132900
# Name: gdpPercap, dtype: float64

 

 

(1) matplotlib 으로 버블 그래프 그리기 (Bubble chart using Matplotlib)

 

matplotlib.pyplot.scatter() 메소드를 사용해서 산점도를 그리면서, 버블의 크기(s)와 색깔(c)을 추가로 지정해주면 됩니다. continent 별로 색깔을 다르게 지정해주었는데요, 아래의 범례(plt.legend()) 설정 방법 참고하세요. alpha=0.5 로 버블이 겹쳤을 때 파악할 수 있도록 투명도를 설정해주었습니다. 

 

x축의 gdpPercap 변수가 왼쪽으로 값이 많이 쏠려있는 형태를 띠고 있으므로 plt.xscale('log') 을 사용해서 x축을 로그 변환 (log transformation) 해주었습니다. plt.grid() 로 점선을 사용해서 그리드 선을 추가해주었습니다. 

 

## (1) Bubble chart with Matplotlib
fig = plt.figure(figsize=(16, 9))
df_2007 = df[df['year']==2007]

ax = plt.scatter(
    x = df_2007['gdpPercap'], 
    y = df_2007['lifeExp'], 
    s = df_2007['pop']/300000, 
    c = pd.Categorical(df_2007['continent']).codes, 
    cmap = "Accent", 
    alpha = 0.5, 
    edgecolors = "gray", 
    linewidth = 1);

plt.xscale('log') # log scaling
plt.xlabel("GDP per Capita")
plt.ylabel("Life Expectancy")
plt.title('Gapminder Global Indicators with Matplotlib', fontsize=16)
plt.grid(True, which='major', linestyle='--', linewidth=0.5)
## setting legend using colors in matplotlib scatter plot
plt.legend(
    handles=ax.legend_elements()[0], 
    labels=['Asia', 'Europe', 'Africa', 'Americas', 'Oceania'])

plt.show()

bubble chart using matplotlib

 

 

 

(2) seaborn 으로 버블 그래프 그리기 (Bubble chart using Seaborn)

 

위의 matplotlib 대비 seaborn.scatter() 메소드는 x축, y축, size, hue(그룹별 색깔 구분) 을 각각 지정해줄 수 있어서 비슷한데요, legend=True 로 지정해주면 size 와 hue (그룹별 색깔 구분) 에 대한 범례를 자동으로 추가해주어서 편리합니다. 

 

## (2) Bubble chart with Seaborn
fig = plt.figure(figsize=(16, 9))
df_2007 = df[df['year']==2007]

sns.scatterplot(
    data = df_2007, 
    x = "gdpPercap", 
    y = "lifeExp", 
    size = "pop", 
    hue = "continent",
    legend = True, 
    sizes = (20, 2000) ,
    alpha=0.5
)

plt.xscale('log') # log scaling
plt.xlabel("GDP per Capita")
plt.ylabel("Life Expectancy")
plt.title('Gapminder Global Indicators with Seaborn', fontsize=16)
plt.grid(True, which='major', linestyle='--', linewidth=0.5)
plt.show()

bubble chart using seaborn

 

 

 

(3) plotly 로 동적인 버블 그래프 그리기 (Interactive Bubble chart using Plotly)

 

plotly 는 위의 matplotlib, seaborn 대비 사용자가 커서를 사용해서 동적으로 버블 그래프(interactive bubble chart)를 조회할 수 있다는 점입니다. hover_name="country" 를 지정해주면 버블 위에 커서를 가져다 놓을 경우 국가 이름과 함께 x축, y축, 버블 크기, 색깔 지정 정보를 팝업 메시지로 보여줍니다. 그리고 커서로 블록을 설정해주면 해당 블록에 대해 줌인(zoom in) 해서 확대해주는 기능도 있습니다. 그 외에 첫번째 줄의 df.query("year==2007") 처럼 px.scatter() 함수 안에서 데이터의 subset 을 query 해서 쓸 수 있으며, log_x = True 를 설정하면 x축의 값을 로그 변환하도록 설정해줄 수도 있습니다. 코드가 매우 깔끔하고 그래프가 이쁜데다 동적이기까지 해서 가독성이 매우 뛰어나기 때문에 왠만하면 matplotlib 이나 seaborn 대신에 plotly 를 사용하는 것이 사용자 입장에서는 좋을 것 같아요. 

 

## (3) Bubble chart with Plotly
import plotly.express as px

fig = px.scatter(
    df.query("year==2007"), 
    x="gdpPercap", 
    y="lifeExp",
    size="pop", 
    color="continent",
    hover_name="country", 
    log_x=True, 
    title='Gapminder Global Indicators with Plotly',
    size_max=60,
    height=650)

fig.show()

 

아래의 Plotly 로 그린 버블 그래프의 버블 위에 커서를 가져가면 뜨는 캡션 정보와, 커서로 블록을 선정해서 hover 해서 zoom in 하는 모습을 화면 녹화한 것이예요. 코드 몇줄로 이게 된다는게 신기하지요?! plotly 짱! ^^

 

 

 

 

(4) bubbly 로 시간의 흐름에 따라 변화하는 버블 그래프 그리기 (Animated Bubble chart using bubbly)

 

이번에는 시간 축을 추가 (adding timestamp axis)해서 시간의 흐름에 따라서 버블 그래프가 변화하는 애니메이션을 시각화 해보겠습니다. bubbly 모듈의 bubbleplot() 메소드를 사용하며, time_column='year' 에 년도(year)를 시간 축으로 설정해주었습니다. x축은 x_column, y축은 y_column, 버블 크기는 size_column, 버블 색깔은 color_column 로 설정해주면 됩니다. x_logscale=True 로 x축 값을 로그 변환해주었으며, scale_bubble=3 으로 버블의 스케일을 지정해주었습니다. 

 

#!pip install bubbly

## (4) Animated Bubble Chart
## Using the function bubbleplot from the module bubbly(bubble charts with plotly)
## ref: https://github.com/AashitaK/bubbly

from bubbly.bubbly import bubbleplot 
from __future__ import division
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode()

figure = bubbleplot(
    dataset=df, 
    x_column='gdpPercap', 
    y_column='lifeExp', 
    bubble_column='country', 
    time_column='year', 
    size_column='pop', 
    color_column='continent', 
    x_title="GDP per Capita", 
    y_title="Life Expectancy", 
    title='Animated Gapminder Global Indicators with Bubbly',
    x_logscale=True, 
    scale_bubble=3, 
    height=650)

iplot(figure, config={'scrollzoom': True})

 

 

아래는 애니메이션 버블 차트를 실행시킨 모습을 화면 녹화한 것이예요. 왼쪽 하단의 'Play' 버튼을 누르면 애니메이션이 실행이 되면서 년도의 순서대로 버블 차트가 변화는 것을 볼 수 있습니다. 신기하지요?! ^^ bubbly 짱!! (bubbly 의 백본이 plotly 이므로 역시 plotly 짱!!)

 

 

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

Sankey Diagram 은 화살표 너비가 흐름 속도에 비례(the width of the arrows is proportional to the flow rate)하는 흐름 다이어그램의 한 유형(a type of flow diagram)입니다. Sankey Diagram은 또한 에너지 계정, 지역 또는 국가 차원의 자재 흐름 계정 및 비용 분석을 시각화할 수 있습니다. 다이어그램은 종종 재료 흐름 분석의 시각화에 사용됩니다. 


Sankey Diagram은 시스템 내의 주요 전송 또는 흐름(major transfers or flows)을 강조합니다. 그들은 흐름에 대한 가장 중요한 기여의 위치를 찾는데 도움을 줍니다. 그것들은 종종 정의된 시스템 경계 내에서 보존된 양을 보여줍니다. [1]

 

 

Python에서 Sankey Diagram 을 그리는 모듈로 HoloViews 와 plotly 가 있는데요, HoloViews 가 구문이 좀더 직관적이어서 이해하기가 쉽습니다. 

 

이번 포스팅에서는 Python의 HoloViews 모듈을 사용해서 Jupyter Notebook에서 Sankey Diagram 을 시각화하는 방법을 소개하겠습니다. [2]

 

HoloViews 모듈은 백본으로 Matplotlib 과 Bokeh 를 사용하므로, 만약 이들 모듈이 설치되어 있지 않다면 pip install 로 먼저 이들 모듈을 설치해주어야 합니다. 

 

 

## in a command line

$ pip install bokeh
$ pip install holoviews

 

Sankey elements represent flows and their quantities in proportion to one another. The data of a Sankey element defines a directed, acyclic graph, making it a specialized subclass of the Graph element. The width of the lines in a Sankey diagram represent the magnitudes of each edge. Both the edges and nodes can be defined through any valid tabular format including pandas dataframes, dictionaries/tuples of columns, NumPy arrays and lists of tuples.

The easiest way to define a Sankey element is to define a list of edges and their associated quantities:

 

Sankey 요소는 흐름과 흐름의 양을 서로 비례하여 나타냅니다. Sankey 요소의 데이터는 방향성 있는 비순환 그래프(directed, acyclic graph)를 정의하여 그래프 요소의 특수 하위 클래스로 만듭니다. Sankey Daigram 에서 선의 너비는 각 Edge의 크기를 나타냅니다. Edge와 Node 모두 pandas DataFrame, Dictionaries/Tuples of columns, NumPy Array 및 Lists of Tuples을 포함한 유효한 표 형식을 통해 정의할 수 있습니다. 이게 바로 Holoviews 가 편리하고 직관적인 이유예요. 

 

Sankey 요소를 정의하는 가장 쉬운 방법은 list of edges과 관련 수량을 정의하는 것입니다. 아래 예에서는 A, B node에서 X, Y, Z node 로의 흐름의 관계와 양을 리스트 형식으로 정의한 것입니다. [2]

 

import holoviews as hv
from holoviews import opts, dim
hv.extension('bokeh')

# defining a list of edges and their associated quantities
sankey = hv.Sankey([
    ['A', 'X', 10],
    ['A', 'Y', 20],
    ['A', 'Z', 30],
    ['B', 'X', 60],
    ['B', 'Y', 5],
    ['B', 'Z', 40]]
)

sankey.opts(width=800, height=500)

sankey diagram using holoviews module in python

 

 

 

아래의 예시는 2010년 왕립학회 정책 보고서 "The Scientific Century: securing our future prosperity"에 설명된 영국 박사과정 학생들의 진로에 대한 간단한 데이터 세트를 Sankey Diagram으로 그려본 것입니다. 우리는 정수 지수로 열거된 노드와 각 경력 단계 사이에 흐르는 백분율을 정의합니다. 마지막으로 "To"라는 레이블을 붙이는 대상 노드에 의해 값과 색상에 대한 단위를 가진 차원을 정의합니다. [2]

 

위의 예에서는 nodes의 이름을 그대로 사용하였다면, 아래의 예에서는 nodes에 대해서 enumerate() 함수를 사용해서 index 정수를 매핑해서 holoveiws Dataset 객체로 만들어 주고, 이를 edges 의 관계를 정의할 때 index 정수를 사용하였습니다. 

 

nodes = ["PhD", "Career Outside Science",  "Early Career Researcher", "Research Staff",
         "Permanent Research Staff",  "Professor",  "Non-Academic Research"]
for i, j in enumerate(nodes):
    print(i, ':', j)
    
# 0 : PhD
# 1 : Career Outside Science
# 2 : Early Career Researcher
# 3 : Research Staff
# 4 : Permanent Research Staff
# 5 : Professor
# 6 : Non-Academic Research

 

 

Label의 위치를 오른쪽으로 바꾸어 주었으며 (label_position='right'), cmap, edge_color, node_color 로 edge와 node 의 색깔도 다르게 설정해주었습니다. 색깔이 다르니 가독성이 한결 좋아졌습니다. 

 

## the edges are expressed as integer node indexes and labels are provided separately.
## We can explicitly define the set of nodes as a Dataset of indexes and labels as key 
## and value dimensions respectively.
nodes = ["PhD", "Career Outside Science",  "Early Career Researcher", "Research Staff",
         "Permanent Research Staff",  "Professor",  "Non-Academic Research"]
nodes = hv.Dataset(enumerate(nodes), 'index', 'label')

edges = [
    (0, 1, 53), 
    (0, 2, 47), 
    (2, 6, 17), 
    (2, 3, 30), 
    (3, 1, 22.5), 
    (3, 4, 3.5), 
    (3, 6, 4.), 
    (4, 5, 0.45)   
]

value_dim = hv.Dimension('Percentage', unit='%')
careers = hv.Sankey((edges, nodes), ['From', 'To'], vdims=value_dim)

careers.opts(
    opts.Sankey(labels='label', 
                label_position='right', # adjust the label_position from "right" to "left"
                width=900, height=500, 
                cmap='Set1',
                edge_color=dim('To').str(), # setting edge color
                node_color=dim('index').str()) # setting node color
)

sankey diagram using holoviews in python

 

 

 

Interactive Diagram 이어서 커서를 가져다대면 아래의 화면 캡쳐와 같이 해당 Edge 가 하이라이드 되며 해당 Edge의 From note, To note, Percentage 등의 캡션 정보를 팝업으로 볼 수 있습니다.  (아래는 화면 캡쳐이므로 Interactive 기능 없음. Jupyter Notebook에서 실행해야지 Interactive 기능 사용 가능함)

 

 

[ Reference ]

 

[1] Introduction to Sankey Diagram: https://en.wikipedia.org/wiki/Sankey_diagram

[2] Sankey Element using HoloViews: https://holoviews.org/reference/elements/bokeh/Sankey.html

[3] R로 Sankey Diagram 시각화 하기: https://rfriend.tistory.com/220

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python의 numpy 2D 행렬에서 행 기준, 열기준 백분율을 구하여 히트맵을 그리는 방법을 소개하겠습니다. 

 

(1) numpy 2D array 의 행 기준 백분율을 구해서 히트맵 그리기

     (Plotting the heatmap of percentages by row in numpy 2D array)

(2) numpy 2D array 의 열 기준 백분율을 구해서 히트맵 그리기 

     (Plotting the heatmap of percentages by column in numpy 2D array)

 

 

먼저, 예제로 사용할 numpy 2D array 를 0~4 사이의 정수 난수를 생성해서 만들어보겠습니다. 

 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

## creating a sample dataset of numpy 2D array
np.random.seed(1004)
mat = np.random.randint(low=0, high=5, size=(5, 5))

print(mat)
# [[2 3 3 4 1]
#  [2 0 0 4 4]
#  [0 2 4 2 3]
#  [3 0 4 3 0]
#  [0 2 4 1 4]]

 

 

(1) numpy 2D array 의 행 기준 백분율을 구해서 히트맵 그리기

     (Plotting the heatmap of percentages by row in numpy 2D array)

 

 

numpy 2D array 에서 행 기준 백분율을 구하기 위해서는 행 기준의 합(summation by row, sum(axis=1, keepdims=True)) 이 필요합니다.  

 

이때 mat.sum(axis=1, keepdims=True) 처럼 keepdims=True 옵션을 표기해줌으로써 shape(5, 1) 의 각 행별 합계를 구할 수 있습니다. 만약 keepdims 옵션을 명기하지 않을 경우 디폴트로서 keepdims=False (by default) 가 적용이 되어서 shape(5,)  의 array([13, 10, 11, 10, 11]) 의 계산 결과가 나오며, 이걸로 나누어 주면 행 기준 백분율이 아니라 element-wise 나눗셈이 되어서 전혀 엉뚱한 계산결과가 나오므로 주의가 필요합니다. 

 

## (1) plotting heatmap of numpy percentages along axis 1 in 2D array

## row sums in matrix using 'keepdims=True' option
row_sum = mat.sum(axis=1, keepdims=True)

print(row_sum)
# [[13]
#  [10]
#  [11]
#  [10]
#  [11]]


## when 'keepdims=False' (by default)
mat.sum(axis=1)
# array([13, 10, 11, 10, 11])

 

 

 

위에서 구한 shape (5, 1) 의 행 기준 합계  row_sum 행렬로 원래의 2D array 행렬 mat  을 나누어주면, numpy 2D array에서 행 기준의 백분율을 구할 수 있습니다. np.round(x, decimals=2) 함수를 사용해서 백분율 계산 결과를 소수점 2째 자리까지만 나오도록 반올림을 해주었습니다. 

 

## calculating row percentage in matrix
mat_row_pct = mat / row_sum

## Round array elements to the given number of decimals
mat_row_pct = np.round(mat_row_pct, decimals=2)

print(mat_row_pct)
# [[0.15 0.23 0.23 0.31 0.08]
#  [0.2  0.   0.   0.4  0.4 ]
#  [0.   0.18 0.36 0.18 0.27]
#  [0.3  0.   0.4  0.3  0.  ]
#  [0.   0.18 0.36 0.09 0.36]]

 

 

 

이제 matplotlib 의 matshow() 함수와 colormap 을 사용해서, 위에서 구한 행 기준 백분율에 대해 히트맵을 그려보겠습니다. colormap 으로는 순차적으로 파란색이 진해지(sequential colormaps)는 camp='Blues' 를 사용하였습니다. 그리고 해석을 편리하게 할 수 있도록 plt.colorbar() 함수를 사용해서 칼라의 강도별 백분율을 legend colorbar 를 만들어주었습니다. 아래에 히트맵을 보면 한눈에 행 기준의 백분율이 어디 셀이 높고 어디 셀이 낮은지 한눈에 금방 알아볼 수 있습니다. 

 

## plotting the heatmap of matrix row percentage (axis=1) using colormaps
## ref: https://matplotlib.org/stable/tutorials/colors/colormaps.html

plt.rcParams['figure.figsize'] = (8, 8) # figure size
plt.matshow(mat_row_pct, cmap='Blues') # sequential colormaps
plt.title('Heatmap of row percentage in matrix', fontsize=16)
plt.colorbar(label='percentages along axis 1') # colorbar legend
plt.show()

heatmap of row percentage in numpy 2D array

 

 

 

 

(2) numpy 2D array 의 열 기준 백분율을 구해서 히트맵 그리기 

     (Plotting the heatmap of percentages by column in numpy 2D array)

 

이번에는 mat.sum(axis=0, keepdims=True)  로 numpy 2D array에서 열 기준으로 백분율(percentages by column in numpy 2D array)을 구해보겠습니다. 앞에서와는 다르게 열 기준 합을 구할 때는 axis = 0 을 사용하였습니다. 

(열 기준 백분율을 구할 때는 keepdims=False 로 해도 결과는 동일합니다.)

 

## (2) plotting heatmap of numpy percentages along axis 0 in 2D array
## row sums in matrix
print(mat)
# [[2 3 3 4 1]
#  [2 0 0 4 4]
#  [0 2 4 2 3]
#  [3 0 4 3 0]
#  [0 2 4 1 4]]

col_sum = mat.sum(axis=0, keepdims=True)

print(col_sum)
# [[ 7  7 15 14 12]]

 

 

 

이제 위에서 구한 열 기준 합으로 원래의 2D array 를 나누어주어서 열 기준 백분율을 구하겠습니다. 그리고 np.round(array, decimals=2) 함수를 사용해서 백분율 행렬의 원소 값을 소수점 2째 자리까지만 나오도록 반올림 해보겠습니다. 

 

## calculating row percentage in matrix
mat_col_pct = mat / col_sum

## Round array elements to the given number of decimals
mat_col_pct = np.round(mat_col_pct, decimals=2)

print(mat_col_pct)
# [[0.29 0.43 0.2  0.29 0.08]
#  [0.29 0.   0.   0.29 0.33]
#  [0.   0.29 0.27 0.14 0.25]
#  [0.43 0.   0.27 0.21 0.  ]
#  [0.   0.29 0.27 0.07 0.33]]

 

 

 

2D array 에서 열 기준 백분율이 준비가 되었으니 matplotlib의 plt.matshow() 함수에 순차적으로 빨간색의 강도가 진해지는 colormap 으로서 cmap='Reds' 를 사용하여 히트맵을 그려보겠습니다. 

 

## plotting the heatmap of matrix column percentage (axis=0) using colormaps
## ref: https://matplotlib.org/stable/tutorials/colors/colormaps.html
plt.rcParams['figure.figsize'] = (8, 8)
plt.matshow(mat_col_pct, cmap='Reds') # sequential colormaps
plt.title('Heatmap of row percentage in matrix', fontsize=16)
plt.colorbar(label='percentages along axis 0') # colorbar legend
plt.show()

colormap of percentages by column in numpy 2D array

 

 

[Reference]

* choosing colormaps in matplotlib: https://matplotlib.org/stable/tutorials/colors/colormaps.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python의 pandas DataFrame을 대사응로 matplotlib 그래프를 그렸을 때, X축 범주형 항목의 순서(changing the order of x-axis ticks in python matplotlib plot)를 변경하는 방법을 소개하겠습니다. 

 

(1) pandas DataFrame의 x 축으로 사용되는 범주형 값을 loc 를 사용해 재정렬하기

(2) index 가 재정렬된 pandas.DataFrame에 대해서 matplotlib 으로 그래프 그리기

 

changing the order of x-axis ticks in matplotlib plot

 

먼저, 예제로 사용할 간단한 pandas DataFrame을 만들어 보겠습니다. 요일(weekday dates) 별 값(value) 으로 구성된 DataFrame에 대해서 groupby() 연산자를 사용해서 요일별 값의 합을 집계(aggregation by weekday) 한 DataFrame을 만들었습니다. 

 

import pandas as pd
import matplotlib.pyplot as plt

## making a sample pandas DataFrmae
df = pd.DataFrame({
    'weekday': ['Monday', 'Saturday', 'Tuesday', 'Sunday', 'Wednesday', 'Thursday', 
                'Friday', 'Saturday', 'Sunday', 'Friday', 'Tuesday'], 
    'value': [2, 3, 4, 2, 6, 7, 5, 2, 1, 6, 4]
})

print(df)
#       weekday  value
# 0      Monday      2
# 1    Saturday      3
# 2     Tuesday      4
# 3      Sunday      2
# 4   Wednesday      6
# 5    Thursday      7
# 6      Friday      5
# 7    Saturday      2
# 8      Sunday      1
# 9      Friday      6
# 10    Tuesday      4


## aggregation of value by weekday --> this will be used for visualization
df_agg = df.groupby('weekday').sum('value')
print(df_agg)
#            value
# weekday         
# Friday        11
# Monday         2
# Saturday       5
# Sunday         3
# Thursday       7
# Tuesday        8
# Wednesday      6

 

 

 

(1) pandas DataFrame의 x 축으로 사용되는 범주형 값을 loc 를 사용해 재정렬하기

 

위에서 df.groupby('weekday').sum('value') 로 집계한 df_agg DataFrame의 결과를 보면, 알파벳(alphabet) 순서대로 요일의 순서("Friday", "Monday", "Satruday", "Sunday", "Thursday", "Tuesday", "Wednesday")가 정해져서 집계가 되었습니다. 이 DataFrame에 대해 matplotlib 으로 막대그래프를 그리면 아래와 같이 요일이 알파벳 순서대로 정렬이 된 상태에서 그래프가 그려집니다. 

 

plt.figure(figsize=(12, 8))
plt.bar(df_agg.index, df_agg.value)
plt.title("Bar plot without reordering x-axis label", fontsize=20)
plt.xlabel("Weekday", fontsize=18)
plt.xticks(fontsize=16)
plt.show()

matplotlib: before changing the order of x-axis label

 

 

(2) index 가 재정렬된 pandas.DataFrame에 대해서 matplotlib 으로 그래프 그리기
       (matplotlib 그래프의 x-axis 의 ticks 순서 바꾸기)

 

요일의 순서가 우리가 일상적으로 사용하는 순서와는 다르기 때문에 눈에 잘 안들어오고 거슬립니다. 이럴 때는 pandas DataFrame의 index 순서를 먼저 바꾸어주고, 순서가 재정렬된 후의 DataFrame에 대해서 matplotlib 으로 그래프를 그려주면 됩니다.

 

아래 예제에서는 요일(weekday)을 알파벳 순서가 아니라, 우리가 일상적으로 사용하는 ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") 의 순서로 DataFrame의  index 를 loc 를 사용해서 바꾸어 준후에, matplotlib 막대그래프(bar graph)를 그려보았습니다. 

 

matplotlib의 X 축 레이블의 크기 

## changing the order of x-axis label using loc
weekday_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
df_agg = df_agg.loc[weekday_order]

print(df_agg)
#            value
# weekday         
# Monday         2
# Tuesday        8
# Wednesday      6
# Thursday       7
# Friday        11
# Saturday       5
# Sunday         3


## box-plot after changing the order of x-axis ticks
plt.figure(figsize=(12, 8))
plt.bar(df_agg.index, df_agg.value)
plt.title("Bar plot after reordering x-axis label", fontsize=20)
plt.xlabel("Weekday", fontsize=18)
plt.xticks(fontsize=16)
plt.show()

matplotlib: after changing the order of x-axis label

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python matplotlib 모듈을 사용해서 그래프를 그렸을 때 범례를 추가(adding a legend on the Axes)하는 4가지 방법을 소개하겠습니다. 그리고 범례의 위치, 범례 글자 크기, 범례 배경색, 범례 테두리 색, 범례 그림자 등을 설정하는 방법을 소개하겠습니다. 

 

(1) 범례 추가하기 (adding a legend on the Axes)

    : legend(), legend(handles, labels), legend(handles=handles), legend(labels)

(2) 범례 스타일 설정하기
    : location, fontsize, facecolor, edgecolor, shadow

 

 

(1) 범례 추가하기 (adding a legend on the Axes)

 

matplotlib 으로 그래프를 그린 후 범례를 추가하는 방법에는 (1-1) legend(), (1-2) line.set_label(), (1-3) legend(handles, labels), (1-4) legend(handles=handles) 의 4가지 방법이 있습니다. 이중에서 그래프를 그릴 때 label 을 입력해주고, 이어서 ax.legend() 나 plt.legend() 를 실행해서 자동으로 범례를 만드는 방법이 가장 쉽습니다. 차례대로 4가지 방법을 소개하겠습니다.  결과는 모두 동일하므로 범례가 추가된 그래프는 (1-1)번에만 소개합니다. 

 

먼저, 아래의 2개 방법은 자동으로 범례를 탐지해서 범례를 생성해주는 예제입니다. 

 

(1-1) ax.plot(label='text...') --> ax.legend() 또는 plt.legend()

 

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(1)
x = np.arange(100)
y1 = np.random.normal(0, 1, 100)
y2 = np.random.normal(0, 1, 100).cumsum()

## 1. Automatic detection of elements to be shown in the legend
## 1-1. label
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

## labels: A list of labels to show next to the artists. 
ax.plot(x, y1, 'b-', label='Company 1')
ax.plot(x, y2, 'r--', label='Company 2')
ax.legend()
plt.show()

matplotlib legend

 

 

(1-2) line.set_label('text...') --> ax.legend()

 

## 1-2. line.set_label()

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

line, = ax.plot(x, y1, 'b-')
line.set_label('Company 1')

line, = ax.plot(x, y2, 'r--')
line.set_label('Company 2')

ax.legend()
plt.show()

 

 

위의 두 방법은 범례를 자동 탐지해서 생성해줬다면, 아래의 방법부터는 명시적으로 범례의 handles (선 모양과 색깔 등) 와 labels (범례 이름)를 지정해줍니다.

 

(1-3) ax.legend(handles, labels)

 

## 2. Explicitly listing the artists and labels in the legend
## to pass an iterable of legend artists followed by an iterable of legend labels respectively
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

line1, = ax.plot(x, y1, 'b-')
line2, = ax.plot(x, y2, 'r--')

ax.legend([line1, line2], ['Company 1', 'Company 2'])
plt.show()

 

 

 

(1-4) ax.legend(handles=handles)

 

## 3. Explicitly listing the artists in the legend
## the labels are taken from the artists' label properties.
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

line1, = ax.plot(x, y1, 'b-', label='Company 1')
line2, = ax.plot(x, y2, 'r--', label='Company 2')

## handles: A list of Artists (lines, patches) to be added to the legend. 
ax.legend(handles=[line1, line2])
plt.show()

 

 

 

(2) 범례 스타일 설정하기
    : location, fontsize, facecolor, edgecolor, shadow

 

범례의 위치(location) 을 지정하려면 loc 매개변수에 location strings 인 'best', 'upper right', 'upper left', 'lower left', 'lower right', 'right', 'center left', 'center right', 'lower center', 'upper center', 'center' 중에서 하나를 선택해서 입력해주면 됩니다. 기본설정값은 loc='best' 로서 컴퓨터가 알아서 가장 적절한 여백을 가지는 위치에 범례를 생성해주는데요, 나름 똑똑하게 잘 위치를 선택해서 범례를 추가해줍니다. 

 

그밖에 범례의 폰트 크기(fontsize), 범례의 배경 색깔(facecolor, 기본설정값은 'white'), 범례의 테두리선 색깔(edgecolor), 범례 상자의 그림자 여부(shadow, 기본설정값은 'False') 등도 사용자가 직접 지정해줄 수 있습니다. (굳이 범례의 스타일을 꾸미는데 시간과 노력을 많이 쏟을 이유는 없을 것 같기는 합니다만....^^;)

 

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

ax.plot(x, y1, 'b-', label='Company 1')
ax.plot(x, y2, 'r--', label='Company 2')
ax.legend(
    ## location strings
    ## : 'best', 'upper right', 'upper left', 'lower left', 'lower right'
    ##   'right', 'center left', 'center right', 'lower center', 'upper center', 'center'
    loc='center left', # default: loc='best'
    ## fontsize
    ## # 'xx-small','x-small','small','medium','x-large','xx-large'
    fontsize='large', 
    facecolor='yellow', # background color
    edgecolor='black',
    shadow=True) # shadow behind the legend if True

ax.set_title('Adding a Legend with color and shadow', fontsize=18)
plt.show()

matplotlib adding a legend with color and shadow at center left location

 

 

[ Reference ]

* matplotlib.pyplot.legend() : https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요. :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python matplotlib 모듈로 그래프를 그릴 때,  

 

(1) 눈금 설정하기 : set_xticks(), set_yticks()

(2) 눈금 이름 설정하기 : set_xticklabels(), set_yticklabels()

(3) 축 이름 설정하기 : set_xlabel(), set_ylabel()

(4) 제목 설정하기 : set_title()

 

하는 방법을 소개하겠습니다. 

 

 

먼저, numpy 모듈을 사용해서 표준정규분포 X~N(0, 1) 로부터 난수 100개를 생성해서 matplotlib의 기본 설정으로 선 그래프를 그려보겠습니다. matplotlib의 Figure 객체를 만들고, fig.add_subplot(1, 1, 1) 로 하위 플롯을 하나 만든 다음에 선 그래프를 그렸습니다. 

 

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

np.random.seed(1)
x=np.arange(100)
y=np.random.normal(0, 1, 100)

## plot with default setting
ax.plot(x, y)
plt.show()

 

 

(1) 눈금 설정하기 : set_xticks(), set_yticks()

 

X축의 눈금을 [0, 50, 100] 으로 설정하고, Y축의 눈금은 [-2, 0, 2] 로 설정해보겠습니다. 

 

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

ax.plot(x, y)

## setting xticks, yticks
ax.set_xticks([0, 50, 100])
ax.set_yticks([-2, 0, 2])

plt.show()

matplotlib.pyplot : ax.set_xticks(), ax.set_yticks()

 

 

 

(2) 눈금 이름 설정하기 : set_xticklabels(), set_yticklabels()

 

X축과 Y축에 눈금이름(xticklabel, yticklabel)을 설정해줄 수도 있습니다. 이때 set_xticks(), set_yticks() 메소드로 눈금의 위치를 먼저 설정해주고, 이어서 같은 개수의 눈금 이름을 가지고 set_xticklabels(), set_yticklabels() 메소드로 눈금 이름을 설정해주면 됩니다. 

 

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

ax.plot(x, y)

## setting xticks, yticks with labels
ax.set_xticks([0, 50, 100])
ax.set_yticks([-2, 0, 2])
ax.set_xticklabels(['start', 'middel', 'end'], fontsize=12)
ax.set_yticklabels(['low', 'zero', 'high'], fontsize=12)

plt.show()

 

 

 

(3) 축 이름 설정하기 : set_xlabel(), set_ylabel()

 

set_xlabel(), set_ylabel() 메소드로 축 이름(xlabel, ylabel)을 설정해 줄 때 fontsize 매개변수를 사용해서 글자 크기를 조정할 수 있습니다. 

 

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

ax.plot(x, y)

## setting xticks, yticks with labels
ax.set_xticks([0, 50, 100])
ax.set_yticks([-2, 0, 2])
ax.set_xticklabels(['start', 'middel', 'end'], fontsize=12)
ax.set_yticklabels(['low', 'zero', 'high'], fontsize=12)

## setting xlabel, ylabel
ax.set_xlabel('Steps', fontsize=16)
ax.set_ylabel('Value', fontsize=16)

plt.show()

 

 

 

(4) 제목 설정하기 : set_title()

 

제목의 텍스트, 폰트 크기(fontsize), 위치(loc={'center', 'left', 'right'}) 를 설정해 줄 수 있습니다. 

 

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(1, 1, 1)

ax.plot(x, y)

## setting xticks, yticks with labels
ax.set_xticks([0, 50, 100])
ax.set_yticks([-2, 0, 2])
ax.set_xticklabels(['start', 'middel', 'end'], fontsize=12)
ax.set_yticklabels(['low', 'zero', 'high'], fontsize=12)

## xlabel, ylabel
ax.set_xlabel('Steps', fontsize=16)
ax.set_ylabel('Value', fontsize=16)

# title
ax.set_title('Plo with ticks and labels', 
             fontsize=20, 
             loc='left') # 'center', 'right'

plt.show()

matplotlib: setting title, xlabel, xticks, xticklabels

 

 

 

[ Reference ]

* ax.set_xticks(): https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xticks.html

* ax.set_xticklabels(): https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xticklabels.html

* ax.set_xlabel(): https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlabel.html

* ax.set_title(): https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.set_title.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,