다양한 시각화 방법론

DONGJIN IM·2022년 2월 21일
0

데이터 시각화

목록 보기
4/6

Polar Coordinate

Polar Coordinate란?

  • 극 좌표계
  • (x,y) 대신 R(거리)와 각(θ\theta)를 활용해 그린 Plot
    • x=Rcos(θ)x = R*cos(\theta)
      y=Rsin(θ)y = R*sin(\theta)
  • 회전, 주기성 등을 표현하기에 적합

코드를 통한 Polar Coordinate

  • Polar Coordinate를 그리기 위한 ax 생성
    • 방법 1 : projection='polar' 파라미터 전달
    • 방법 2 : polar=True 파라미터 전달
fig = plt.figure()
ax1 = fig.add_subplot(121, projection='polar')
ax2 = fig.add_subplot(122, polar=True)
fig.tight_layout()
plt.show()
# 아래 사진을 보면 차이가 없이 생성되었음을 알 수 있음

  • Polar Coordinate의 반지름 조정
    • set_rmax(x) : Polar Coordinate 수치 최댓값을 x로 지정
    • set_rmin(x) : Polar Coordinate 시작 수치를 x로 지정
fig = plt.figure()
ax = fig.add_subplot(111, polar=True)

ax.set_rmax(2)
plt.show()

  • set_rlabel_position : 반지름 수치가 적히는 위치 각도 조정
    • 단위 : degree
  • 각도를 조정하여 원이 아닌 부채꼴 모양의 Polar Coordinate 생성 가능
    • set_thetamin(A), set_thetamax(B)
      • A ~ B degree까지의 부채꼴만 ax에 그려줌
    • 단위 : degree
fig = plt.figure()
ax = fig.add_subplot(111, polar=True)

ax.set_thetamin(45)
ax.set_thetamax(135)
plt.show()

  • scatter(), bar(), plot()을 활용하여 Polar 기본 Chart를 그릴 수 있음
    • 단, 입력값의 순서는 무조건 "theta, r" 순서로 가장 먼저 입력되어야 함

Radar plot

  • 극 좌표계 관련 Plot 중 가장 대표적인 차트
  • 별 모양으로 생겨 Star Plot으로 불리기도 함
  • 중심점을 기준으로 N개 변수 값을 표현할 수 있음
    • N을 7개 내외로 지정하는 것을 추천
  • 데이터 Quality를 표현하기에 좋음
    • 캐릭터 강함, 운동 선수 분석, 사람 성향, 비교 등에 적합
  • Radar Plot 주의점
    • 각 Feature가 독립적이며 척도가 같아야 함
      • Scale과 단위가 동일해야 함
      • 순서, 수치형 변수를 동시에 존재한다면 사용을 다시 생각해봐야 함
    • Feature 순서에 따라 다각형 면적이 달라짐
    • Feature가 많아질수록 가독성이 떨어짐

코드로 보는 Radar Plot

  • 주의할 점 : theat와 R data에 있어서 가장 첫번째 data를 복사하여 가장 마지막에 추가시켜줘야 한다.
    • 이유 : Plot을 "닫힌 그래프"로 만들기 위해서
    • 만약 위 과정을 거치지 않으면, 마지막 점과 첫번째 점이 연결되지 않는다.
  • Default Radar Plot 그리기
    • ax.plot : theta와 R을 활용하여 그래프를 그림
    • ax.fill : theta와 R로 그래프를 그리고 내부에 색을 칠함
      • 외부를 연결한 선은 그려지지 않음
    • theta : 수치 R을 어디에 표현할 것인가
      R : 측정치. 캐릭터의 강함이나 능력 수치 등
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')

values.append(values[0])
theta = theta.tolist() + [theta[0]]

ax.plot(theta, values)
ax.fill(theta, values, alpha=0.5)

plt.show()
  • Radar Plot ticklabels 변경
    • set_thetagrids 활용
    • ax.set_thetagrids[{각도 List}, {이름 List}]
      • {각도 List}[index]에 쓰여져 있는 ticklabel 값을 {이름 List}[index] 값으로 바꿔줌
fig = plt.figure(figsize=(4, 4))
ax = fig.add_subplot(111, projection='polar')
stats = ["HP", "Attack", "Defense", "Sp. Atk", "Sp. Def", "Speed"]

values = pokemon.iloc[0][stats].to_list()
values.append(values[0])

ax.plot(theta, values)
ax.fill(theta, values, alpha=0.5)

ax.set_thetagrids([n*60 for n in range(6)], stats)
"""
n = 0일때만 고려해보자.
먼저, 첫번째 Parameter는 0도가 될 것이다. 또 stats에는 HP가 뽑힐 것이다
(stats[0]을 Select 해야하기 때문에)
따라서, 아래 그림처럼 원래 0도라는 수치가 써 있어야 하는 곳에 HP가 적혀 있음을
알 수 있다
"""
plt.show()

  • set_theta_offset(x) : Polar Coordinate 시작 각도를 x로 바꾸는 메서드
    • x 단위 : Radian
      • Degree가 아니다. 주의! np.pi를 활용해야 함

Pie Charts

Pie chart란?

  • 원을 부채꼴로 분할하여 표현하는 통계 차트
  • 전체를 백분위로 나타낼 때 유용함
  • 실험 결과나 Data 파악을 위해 좋은 Chart는 아니지만 인포그래픽을 위해 많이 활용하는 Chart
    • 인포그래픽 : 정보를 빠르고 분명하게 표현하기 위해 데이터를 시각적으로 표현한 것
    • 즉, 다른 사람에게 보여주기 위해 Data를 시각화한 Chart
  • 실험 데이터 파악을 위해 활용하기에는 어렵고, 유용성이 떨어짐
    • Bar Plot이 더 유용함
    • 굳이 활용하고 싶으면, Bar Plot과 병행하여 사용하는 것을 추천
    • 이유 : 각도가 길이보다 비교하기 어려움
  • 활용하는 것을 추천하지는 않음

코드로 보는 pie Chart

  • Default Pie Chart
    • labels를 통해 각 Part에 대한 Label을 붙여줄 수 있음
    • data[index]에 매칭되는 Label은 label[index]이다
<설명>
Pie Chart는 각도를 활용. 따라서, data를 모두 더하여 T라는 값이 나왔다면, 
360 / T 값을 모든 List에 곱해준 만큼의 각도를 차지하는 것으로 생각하면 된다

아래 예시에서는 모두 더하면 360이므로, 360 / 360 = 1만큼을
모든 List에 곱해줘 Pie Chart를 그린다. 각각 60도, 90도, 45도, 165도
의 공간을 Pie Chart에서 차지하게 그려야 함을 알 수 있다.
labels = ['A', 'B', 'C', 'D']
data = np.array([60, 90, 45, 165])

ax.pie(data, labels)
  • pie() Parameter

    • startangle=x : Pie Chart를 x도에서 그리기 시작함
      • 단위 : Degree
    • explode
      • List로 값을 전달
      • 0이 아닌 숫자가 입력된 index의 수치만큼 해당 Pie 부분이 원 중심에서 떨어짐
    explode_list = [0,0,0.2,0]
    
    ax.pie(data, explode=explode_list, labels=labels, startangle=90)

    • shadow : True로 설정될 경우, 그림자가 구현됨
    • autopct : Pie Chart에 (해당 Pie가 차지하고 있는) 수치를 표현함
      • '%X%'에서 X부분에 내가 원하는 형식의 formatting 입력시킴
    ax.pie(data, labels=labels, explode=explode_list, startangle=90,
              shadow=True, autopct='%1.1f%%')
              
    # 소수점 1자리 수까지 표현하며, 마지막에 %라는 수치를 붙여 표현하도록 Formatting

    • labeldistance : label과 Pie Chart와의 거리 지정
    • rotatelabels
      • 단위 : Degree
      • 중심점을 기준으로 label을 x만큼 회전시키는 것이지만, 추천하지는 않는 Parameter
    • counterclock : False로 지정할 경우 Start Point부터 시계 방향으로 순서대로 그림
      • Default : True. 즉 반시계 방향으로 그리는 것이 Default
    • radius : Pie Chart 반지름
    for size, ax in zip([1, 0.8, 0.5], axes):
        ax.pie(data, labels=labels, explode=explode_list, startangle=90, 
                                                              radius=size)

    • pctdistance : 반지름의 길이를 1이라고 생각하여, 어느 위치에 Pie Chart 수치를 기입할지 정함
    • textprops : Dict type Data로 Pie Chart Text에 대해 설정
      • textprops={'color':'w'} : Pie Chart의 Text Color를 하얀색으로 지정

Donut Chart

  • 중간이 비어있는 Pie Chart
  • Presentation적으로는 좋지만, 데이터 비교 등을 위해서는 좋지 않음
  • Pie Chart 중간에 원을 그리는 방식으로 구현 가능
centre_circle = plt.Circle((0,0),0.70,fc='white')
ax.add_artist(centre_circle)

Sunburst chart

Sunburst chart란?

  • 계층 구조 Data를 표시하는 데 적합한 Chart
  • 하나의 고리 또는 원이 계층 구조의 Level을 나타냄
    • 안쪽에 있는 원일 수록 계층 구조 Level이 높음을 나타냄
    • 안쪽에 있을 수록 더 큰 범위의 Grouping을 위한 기준
      • (ex) 선수별 골 모음을 Sunburst Chart로 그리고 싶을 때, 공격수는 가장 안쪽 원에 존재할 것이며, 공격수에 포함된 A, B, C 선수는 바깥쪽 원에 존재할 것이다.
  • Sunburst chart 그림 예시
    • DESK가 케인, 손흥민, 알리, 에릭센을 포함하는 구조를 가지고 있음
  • 구현 난이도에 비해 화려함
  • 가독성이 떨어지고, 유용성이 없음
    • Treemap 활용을 추천

다양한 시각화 라이브러리

Missingno

  • 결측치를 체크하기 위한 시각화 라이브러리
    • 정렬을 활용하여 NULL 정보에 대한 분포 확인이 가능
  • 결측치를 matrix로 나타내어 흰 부분으로 표시해줌

코드를 활용한 Missingno

  • missingno 설치 : pip install missingno
  • aias : 주로 msno로 많이 설정
    • import missingno as msno
  • Matrix를 통해 결측치 확인
msno.matrix({data})

  • 정렬을 활용하여 결측치 파악
    • sort Parameter 활용
msno.matrix({data}, sort='descending')
# 내림차순 정렬
# 오름차순 정렬을 위해서는 sort = 'ascending'으로 설정해주면 된다.
위 사진을 보면 row당 결측치의 수가 모두 다름을 볼 수 있다.
그런데, 위와 같은 사진으로 보면 어떤 Data가 어느 정도의 결측치를 가지고 있는지 
한눈에 파악하기가 어렵다.
따라서, 결측치의 수를 기준으로 정렬을 수행하는 것이다.
이 경우, Row(1개 Data)가 가진 최대 결측치 개수와 최소 결측치 개수를 알 수 있으며,
Column 중 결측치가 많은 것들에 대해서도 파악하기 쉬우므로, 
꼭 이 방법을 활용하는 것을 추천한다.

  • mano.bar({Data})
    • Feature마다의 결측치 개수를 Bar Plot을 통해 구할 수 있음
    • 결측치 개수를 표현하지는 않고, 결측치가 아닌 데이터 개수를 Bar Plot으로 그림

TreeMap

  • 계층적 데이터의 대표적인 시각화 방법
    • 데이터 포함 여부를 보여주기 좋음
  • 사각형을 분할하는 타일링 알고리즘에 따라 형태가 다양함
  • Python에서 구현할 수 있는 방법
    • squarify
    • Plotly의 Treemap 활용
  • 계층이 깊어질수록 사각형이 작아져 글씨 넣기가 어려움
    • Interactive Visualization이 가능한 라이브러리를 활용하는 것이 좋음(Plotly 등)

코드를 활용한 TreeMap(Squarify 활용)

  • squarify 설치 : pip install squarify
  • TreeMap 그리기
    • squarify.plot({Value List})
    • Value List의 수치 비율에 따라 사각형 너비를 할당해 줘 그림
values = [100, 200, 300, 400]
squarify.plot(values)

  • label
    • 사각형 영역마다 해당 영역에 대한 설명을 달아주기 위한 Parameter
    • Value List와 동일한 length를 가져야하며, Value List 중 동일한 index에 존재하는 값으로 만들어진 사각형에 Label이 붙여짐
    • text_kwargs : Label 설정값을 Dict type Data
values = [100, 200, 300, 400]
label = list('ABCD')
squarify.plot(values, label=label)

  • color
    • 사각형 영역마다 색을 지정하기 위한 Parameter
    • label 파라미터와 활용 방법은 동일(단, List값이 색)
  • pad
    • 사각형 사이에 Parameter로 전달한 수치만큼 Padding을 추가함
color = ['#4285F4', '#DB4437', '#F4B400', '#0F9D58']

squarify.plot(values, label=label, color=color, pad=0.2)

  • 깔끔하게 보기 위해선, 모든 축(spines)를 보이지 않게 하는 것을 추천
    • ax.axis('off') : 모든 축을 보이지 않게 함

Waffle Chart

  • Discrete한 Data를 나타내기 좋은 Chart
  • 기본적으로는 정사각형 모양이지만, 원하는 벡터 이미지로도 그릴 수 있음
    • Pictogram Chart : Icon을 활용한 Waffle Chart
  • 인포그래픽에서 유용하게 활용됨
  • 전체적인 구성 또는 비율을 볼 수 있는 시각화 방법
    • Pie Chart보다 향상된 Chart
  • 데이터 결손이 발생할 수 있음
<설명>
Waffle Chart는 정사각형을 활용하여 그림을 그린다.
이 때 중요한 점은 가로 세로를 어느 정도 Size로 정해줘야 한다는 점이다.
예를 들어, 가로 5, 세로 4라면 총 20개의 정사각형을 활용해 Waffle Chart를 
그리는 것이다. 
그리고, 우리가 활용할 수 있는 정사각형의 개수는 한정되어 있으므로 
데이터 결손이 발생할 수 있다.

총 Data 개수가 30개라고 가정해보자.
그럴 경우, 20개 까지의 Data는 정사각형으로 표현할 수 있을 것이다.
하지만, 나머지 10개의 Data는 표현할 수 있는 정사각형이 남아 있지 않으므로, 
표현할 수가 없을 것이다.

따라서 이런 상황에서는 "비율"을 활용하여 정사각형 개수를 할당해주는 것이다.
예를 들어, 9 : 21의 Data 비율을 가지고 있다면,
정사각형을 각각 6개, 14개를 할당해주어 Data를 Chart로 표현한 것이다.

그런데 만약 Data가 10 : 20이라면 어떻게 될까?
이 경우, 정확한 비율을 생각해보면 6.66666 : 13.333333이 될 것이다.
그런데, 정사각형 개수는 "정수"여야 하므로, 각각 7개와 13개의 정사각형을 
할당해 줄 것이다. 이 과정에서 여쩔 수 없이 0.333333만큼의 데이터 결손이 
발생할 수 있는 것이다

코드를 활용한 Waffle Chart

  • 라이브러리 설치 : pip install pywaffle

  • Waffle Chart를 위한 import : from pywaffle import Waffle

  • Default Waffle Chart

    • 정사각형 모양으로 Waffle Chart 그림
      fig = plt.figure(
           FigureClass=Waffle
           rows = 5,
           columns = 10,
           values = [48,46,6],
           figsize=(5,3)
           )
      plt.show()
    • FigureClass = Waffle을 활용하여 Waffle Chart를 그림
    • rows : Row 개수 설정, columns : Column 개수 설정
    • values : 나타내고 싶은 Data List
      * 위 예시에서는, 총 3개 Data Label이 존재하며, 각각 Label에 48, 46, 6개만큼의 Data가 포함된 것이다.
  • 색 지정

    • colors를 통해 색 List를 전달해주거나 cmap_name을 활용하여 컬러맵을 전달할 수 있음
    • plt.figure의 Parameter로 지정해줌
  • legend

    • Dict type으로 Data를 전달
    • legend Parameter를 활용해 범례(Legend) 위치 조정 가능
    • 추천 위치 : 우측 상단, 중앙 하단
    data = {'A': 50, 'B': 45, 'C': 15}
    
    fig = plt.figure(
        FigureClass=Waffle, 
        rows=5, 
        values=data, 
        legend={'loc': 'upper left', 'bbox_to_anchor': (1.1, 1)}
    )
    plt.show()

  • starting_location : 그래프 그리는 시작점을 네 꼭짓점 중 하나로 지정

    • NW, SW, NE, SE 중 한 개 값을 전달
    • 왼쪽 : starting_location = 'NW'
      오른쪽 : starting_location = 'SE'
      • 첫 Data인 A부터 그리는데, 시작 위치가 달라짐을 알 수 있음
  • vertical : Row 기준 수직 방향으로 그릴지 아닐지를 결정하는 Parameter

    • Boolean 값으로 Parameter값 설정
    • 왼쪽 : vertical=False 혹은 설정하지 않은 Case
      오른쪽 : vertical=True
      • vertical=True로 설정할 경우 starting_location을 따로 설정하지 않을 때 'SW'로 설정됨을 알 수 있다. 이는 아래에서도 설명하겠지만, "오른쪽으로" 90도 돌려 Waffle Chart를 그리는 것으로 생각하면, 'SW' 부분이 시작 지점인 것을 알 수 있다.
      • 보기 편하게 하기 위해서 오른쪽은 starting_location을 'NW'로 설정하였다
<설명>
결론만 먼저 말하자면, Waffle Chart를 그릴 때 (오른쪽으로) 90도 회전시킨 다음 
수평으로 그릴지 수직으로 그릴지 결정하는 것으로 생각하면 된다

Vertical은 Data를 "어느 방향으로" 그릴 것인가를 설정하는 Parameter이다.
Vertical은 위에서 말했듯 "Row" 기준으로 수직으로 그릴지 아닐지를 결정한다.

Default는 Vertical이 False로 설정되어 있다.
즉, Row의 방향에 맞춰 그래프를 그린다는 의미이다.
우리는 Row Data를 이동하기 위해서는 위 아래로 움직여야 한다는 것을 알고 있다.
즉, a[0,0]과 a[1,0]의 차이는 "아래로" 한 칸 움직이는 것임을 알고 있다.

vetical = False일 때는 Row 방향에 수직하지 않으므로, 위아래로 움직이며 
Waffle Chart를 그리게 될 것이다.
따라서, 위에서 아래로 혹은 아래에서 위로 움직이게 되는 것이다.

반대로 vertical = True일 경우, Row 방향에 수직한다. 즉, Column 방향과 
평행하게 그려질 것이다.
Column 방향은 왼쪽에서 오른쪽 혹은 오른쪽에서 왼쪽으로 움직이는 것이다.
따라서, Data를 그릴 때 좌우로 움직이며 Waffle Chart를 그리게 될 것이다.

처음에는 좌우로 움직이는 것을 Horizontal이라고 생각하여 vertical=False로 
설정해야 하는 것이 아닌가? 라는 고민을 많이 하였다.
하지만, 항상 생각하자. "ROW를 기준으로" Vertical하게 그릴지 아닐지를 
결정하는 것이다.
  • block_arranging_style

    • Data를 어떤 식으로 나열할지 정할 수 있음
    • Default : snake
      • 한 쪽 방향으로 Data를 그리다 정해진 Row나 Column 끝으로 가면 그린 방향의 수직인 방향으로 한 칸 움직인 뒤, 원래 움직이던 반대 방향으로 Waffle Chart를 계속해서 그림
    • new-line
      * 1개 Label Data에 대한 정사각형을 모두 그릴 경우 새로운 줄에 다음 Label Data를 표현함
    • 왼쪽 : Snake
      오른쪽 : new-line
  • Icon을 활용한 Pictogram Chart그리기

    • icons : 아이콘 명칭
    • icon_legend : Legend(범례)도 icon으로 할지 True, False로 전달
      • False일 경우 Legend에는 정사각형 모양으로 그려짐
    • font_size : 아이콘 사이즈
fig = plt.figure(
    FigureClass=Waffle, 
    rows=10,     
    values=data, 
    legend={'loc': 'lower left', 'bbox_to_anchor': (0, -0.4), 
                            'ncol': len(data), 'framealpha': 0},
    icons='child',
    icon_legend=True,
    font_size=15,
)
plt.show()

Venn (Diagram)

  • 집합(Set) 등에서 활용하는 벤 다이어그램
  • EDA보다는 출판 및 Presentation에서 활용
  • 추천하지는 않는 방법
    • 이유 : 원이 여러개 존재할수록 가독성이 떨어지는 문제 발생
    • 정보 시각화에서는 활용하지 않는 방법

코드를 활용한 Venn

  • Venn 설치 : pip install matplotlib_venn
  • Venn import 시키기 : import matplotlib_venn
  • 원 2개로 Venn Diagram 그리기
    • A와 B에 대한 Venn Diagram을 그릴 때,
      subsets = (AAB,BAB,AB)A-A\cap B, B - A\cap B, A\cap B) 순으로 입력
venn2(subsets = (3, 2, 1))

  • 원 3개로 Venn Diagrm 그리기
    • Set 1, Set 2, Set 3 Data를 각각 001, 010, 100이라고 가정하자. 예를 들어, Set 1과 Set 2의 교집합은 001과 010의 교집합이므로 011로 표현할 수 있을 것이다.
    • subset : (1,2,3,4,5,6,7)일 때,
      1 : 001, 2 : 010, 4: 100
      3 : 011, 5 : 101, 6 : 110
      7 : 111
      Data 수치를 입력하면 원 3개로 Venn Diagram을 그릴 수 있음
    • set_labels Parameter를 활용하여 Label을 붙일 수 있음
venn3(subsets = (1, 2, 3, 4, 5, 6, 7), 
                              set_labels = ('Set1', 'Set2', 'Set3'))

  • venn3의 subsets에 수치가 아닌 Data Set을 전달하면, 원소의 교집합 등을 자동으로 Counting하여 계산 후 Chart를 그림
set1 = set(['A', 'B', 'C', 'D'])
set2 = set(['B', 'C', 'D', 'E'])
set3 = set(['C', 'D',' E', 'F', 'G'])

venn3([set1, set2, set3], ('Set1', 'Set2', 'Set3'))


사진 출처 : https://ko.wikipedia.org/wiki/%EB%A0%88%EC%9D%B4%EB%8B%A4_%EC%B0%A8%ED%8A%B8
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=vi_football&logNo=221445237451
https://venngage.com/blog/pictogram/

profile
개념부터 확실히!

1개의 댓글

comment-user-thumbnail
2022년 11월 5일

좋은 정보 감사합니다. ^^

답글 달기