데이터 분석 초보자를 위한 데이터 시각화 플롯 탐방 (with Matplotlib)

Gayeon Kim·2020년 9월 4일
0

데이터 분석

목록 보기
1/9

1. 어떤 차트를 선택하면 좋을지 몰라 막막한 당신에게


데이터 분석가를 꿈꾸는 초보자라면 "데이터 분석을 해보겠어!" 하고 용감하게 컴퓨터 앞에 앉았지만 눈앞에 놓인 데이터를 어떤 차트를 사용해서 시각화해야 하는지 몰라 혼란스러웠던 경험이 있을 것이다. 데이터 분석을 하기 위해서 어떤 데이터를 가지고 어떤 분석 방법을 사용하느냐 못지않게 중요한 것이 바로 어떤 차트를 사용할 것인지 결정하는 것이다. 올바른 차트를 선택해야 본인이 열심히 분석한 결과를 명확하게 전달할 수 있기 때문이다. 따라서 오늘은 파이썬의 Matplotlib를 사용하여 데이터 시각화 플롯의 종류에 대해 알아보려고 한다.


2. 데이터 시각화 플롯의 종류


사용할 데이터 만들기

시작하기에 앞서, 우선 데이터 시각화 플롯 탐방에 사용할 데이터를 만들어보자.

  • 필요한 패키지 및 모듈 import
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pylab as plt

import random
  • 데이터 생성

지금부터 당신은 짹짹 초등학교 참새반의 담임 선생님이라고 상상해보자. 참새반에는 11명의 학생이 있으며, 학생들은 지난 학기 동안 5번에 걸쳐서 Speaking과 Writing 시험을 봤다. 방학을 맞은 당신은 참새반 학생들의 정보와 시험 결과를 시각화하고 이를 바탕으로 다음 학기의 강의 계획을 세우려고 한다.

참새반에는 11명의 학생이 있다. 그리고 당신은 각각의 학생에 대하여 학번, 이름, 출생 월, 그리고 성별에 대한 정보를 가지고 있다.

# 학생의 정보에 대한 데이터 생성
student_data = {
    "Code": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111],
    "Name": ["Andrew", "Clara", "Daniel", "Emma", "Henry", "Oliver", "Paul", "Peter", "Sarah", "Tiffany", "William"],
    "Birth_Month": ["January", "May", "July", "July", "July", "February", "November", "March", "October", "July", "May"],
    "Sex": ["male", "female", "male", "female", "male", "male", "male", "male", "female", "female", "male"]
}

학생들은 지난 학기에 5번의 Speaking, Writing 시험을 봤다. 점수는 random을 사용해서 입력하였다. 다만, 너무 의미 없는 데이터만 생성되는 것을 방지하기 위해서 특정 학생의 점수는 임의로 수정하였다.


# 시험 점수에 대한 데이터 생성
score_data = {
    "Code": [],
    "Subject": [],
    "Lesson": [],
    "Score": []
}

# 시험 점수 입력 (random 활용)
def score_setting(sub_name, start, end):
  for i in range(11):
    for j in range(5):
      score_data["Code"].append(101 + i)
      score_data["Subject"].append(sub_name)
      score_data["Lesson"].append(j+1)
      score_data["Score"].append(random.randint(start, end))

score_setting("Writing", 75, 100)
score_setting("Speaking", 40, 85)

# DataFrame 만들기
student_df = pd.DataFrame(student_data)
score_df = pd.DataFrame(score_data)

# 일부 데이터 수정
score_df.loc[5] = [102, "Writing", 1, 80]
score_df.loc[6] = [102, "Writing", 2, 72]
score_df.loc[7] = [102, "Writing", 3, 89]
score_df.loc[8] = [102, "Writing", 4, 92]
score_df.loc[9] = [102, "Writing", 5, 95]

score_df.loc[60] = [102, "Speaking", 1, 30]
score_df.loc[61] = [102, "Speaking", 2, 60]
score_df.loc[62] = [102, "Speaking", 3, 85]
score_df.loc[63] = [102, "Speaking", 4, 90]
score_df.loc[64] = [102, "Speaking", 5, 97]

자, 이제 참새반 학생들에 대한 DataFrame이 완성되었다.

CodeNameBirth_MonthSex
0101AndrewJanuarymale
1102ClaraMayfemale
2103DanielJulymale
3104EmmaJulyfemale
4105HenryJulymale
5106OliverFebruarymale
6107PaulNovembermale
7108PeterMarchmale
8109SarahOctoberfemale
9110TiffanyJulyfemale
10111WilliamMaymale

위의 표는 방금 우리가 만든 student_df이다. row가 11개밖에 되지 않는 간단한 DataFrame이다. 그러나 만일 당신이 이 표를 보고 있을 때 까치반 선생님이 "참새반 학생들은 몇 월에 가장 많이 태어났나요?"라고 묻는다면 당신은 바로 대답하지 못할 것이다. 이렇게 DataFrame만으로는 데이터의 특징을 빠르게 파악할 수 없다. 이번에는 당신이 위의 표가 아니라 아래의 그림을 보고 있다고 생각해보자.


이제는 까치반 선생님의 질문에 "7월이요!"라고 쉽게 대답할 수 있다. 이처럼 데이터 시각화는 데이터를 더 쉽고 편하게 볼 수 있도록 도와준다.

그럼 지금부터 참새반 학생들의 데이터를 matplotlib를 사용해서 시각화해보자.


1) 파이 차트 (pie chart)


참새반의 성비는 어떨까? 또 학생들은 몇 월에 가장 많이 태어났을까?

  • 성비 알아보기
sex = student_df["Sex"]
info = ["male", "female"]
num = [sex.value_counts()["male"], sex.value_counts()["female"]]
plt.rc("font", size=12)
plt.pie(num, labels=info, autopct="%0.1f%%")
plt.show()

파이 차트를 그려보니 참새반에는 남학생이 여학생보다 많다는 것을 알 수 있다. 이렇게 파이 차트는 전체에서 각 요소가 차지하는 비율을 나타낼 때 사용하는 그래프이다. 그런데 파이 차트에는 한 가지 단점이 있다.

  • 출생 월의 비율 알아보기
month_d = student_df["Birth_Month"].value_counts()
info = list(month_d.index)
num = list(month_d)
plt.pie(num, labels=info, autopct="%0.1f%%")
plt.show()


이 그래프는 참새반 학생들의 출생 월의 구성 비율을 표현한 것이다. 어떤가. 그래프의 내용이 한 눈에 들어오는가? July가 가장 많다는 건 그나마 쉽게 알 수 있지만, May와 다른 것들의 차이는 빠르게 인식되지 않는다. 이처럼 파이 차트는 구성하고 있는 요소가 많을 때, 특히 그 요소간의 비율의 차이가 크지 않을 때 그래프를 한눈에 알아볼 수 없다는 단점이 있다.



2) 바 차트(bar chart)


이제부터 본격적으로 학생들의 시험 성적을 살펴보도록 하자. 과연 참새반은 남학생들의 점수가 더 높을까, 여학생들의 점수가 더 높을까? 학생들은 Speaking과 Writing 중에 어떤 것의 시험을 더 잘 봤을까?

  • 남학생과 여학생의 평균 점수 비교
total_df = pd.merge(student_df, score_df) # 데이터 테이블 합치기
score_d = total_df[["Sex", "Score"]]
result = score_d.groupby("Sex").mean()

info = list(result.index)
num = list(result["Score"])

index = np.arange(len(info))
plt.xticks(index, info)
plt.ylim(0, 100)
plt.bar(index, num, width = 0.5)
plt.show()

바 차트를 그려보니 여학생과 남학생의 평균 점수가 비슷하다는 것을 알 수 있다. 그렇다고 '아 여학생이랑 남학생의 성취도가 비슷하네' 하고 그냥 넘어가기엔 조금 부족하다. 눈치챈 사람도 있겠지만 이 그래프는 Speaking과 Writing의 점수가 합해져 있다. 성별에 따라 Speaking과 Writing의 성적에 차이가 있을 수도 있지 않을까?

  • 성별에 따른 Speaking, Writing 평균 점수 비교
score_d = total_df[["Sex", "Subject", "Score"]]
result_male = score_d[score_d["Sex"]== "male"].groupby("Subject").mean()
result_female = score_d[score_d["Sex"]== "female"].groupby("Subject").mean()
info = list(result_male.index)

index = np.arange(len(info))
plt.xticks(index, info)
plt.xlim(-0.5, 2)
plt.ylim(0, 90)
plt.bar(index, list(result_male["Score"]), color ="skyblue", width = 0.4)
plt.bar(index + 0.45, list(result_female["Score"]), color="orange", width = 0.4)
plt.show()

하늘색은 남학생, 주황색은 여학생의 평균 점수이다. 남학생과 여학생 모두 Speaking보다 Writing 시험을 더 잘 보았다. 그런데 Speaking은 여학생, Writing은 남학생의 평균 점수가 더 높다. 그리고 Speaking이 Writing보다 여학생과 남학생의 평균 점수의 차가 더 컸다. 이 그래프를 보고 당신은 참새반 담임 선생님으로서 '다음 학기에는 Speaking 수업의 비중을 늘려야겠네. 그리고 남학생들이 수업에 더 적극적으로 참여할 수 있도록 요즘 남학생들이 열심히 하는 딱지치기를 수업 시간에 활용해봐야겠어.'라는 생각을 할 수 있다.

지금까지 남학생과 여학생의 Speaking, Writing 시험의 평균 점수를 바 차트를 사용해서 비교해보았다. 이처럼 바 차트는 각 범주에 대한 값의 크기를 비교할 때 사용한다.


3) 히스토그램 (histogram)


이제 '다음 학기에 Speaking 수업의 비중을 늘려야 한다.'라는 당신의 생각이 맞는지 확인해보자. 히스토그램을 통해서 학생들의 성적 분포를 살펴보면 시험이 학생들의 성취도를 평가할 적절한 도구가 되어주었는지 알 수 있다.

#Speaking
score_speaking = list(score_df[score_df["Subject"]=="Speaking"]["Score"])
plt.hist(score_speaking, color="orange")
plt.show()

# Writing
score_writing = list(score_df[score_df["Subject"]=="Writing"]["Score"])
plt.hist(score_writing)
plt.show()

주황색은 Speaking, 파란색은 Writing 시험 성적의 분포이다. Speaking의 경우 학생들의 성적이 비교적 골고루 퍼져있는 것으로 보인다. 그런데 Writing은 몇몇 학생을 제외하고는 모두 70점 이상에 분포해 있으며, 심지어는 87~100점 사이에 학생이 가장 많았다. 지난 학기에 참새반 학생들의 Writing 시험 성적이 Speaking 시험 성적보다 더 높았던 것은 학생들의 실력이 향상되어서가 아니라 시험 문제가 너무 쉬워서였을 수도 있다. 당신은 Speaking 수업의 비중을 늘리는 것은 잠시 보류하고 Writing 시험의 문제와 난이도부터 다시 확인해야 한다.

히스토그램은 도수분포표를 막대그래프 형태로 나타낸 것이다. 앞에서 본 바 차트와 비슷해 보이므로 '둘이 똑같은 거 아니야?'라는 생각이 들었을 수도 있다. 그러나 바 차트는 각 범주에 대한 크기를 그림으로 표현한 것이기에 x축에 범주의 label이 쓰여있지만, 히스토그램은 x축에 반드시 구간이 명시되어 있어야 한다는 차이가 있다.


4) 라인 차트 (line chart)


문득 당신은 지난 학기에 Clara가 수업을 정말 열심히 들었던 게 생각났다. 특히 Speaking 수업 첫날에는 아무런 말도 못 하고 의기소침해서 앉아 있었는데, 마지막 날에는 의사 표현도 분명하게 전달하고 자진해서 발표도 하는 등 실력이 많이 늘은 것 같았다. Clara의 성적이 어떻게 변했는지 한 번 살펴보자.

clara_writing = list(total_df[(total_df["Name"] == "Clara") & (total_df["Subject"] == "Writing")]["Score"])
clara_speaking = list(total_df[(total_df["Name"] == "Clara") & (total_df["Subject"] == "Speaking")]["Score"])
plt.plot(clara_writing, color="skyblue")
plt.plot(clara_speaking, color="orange")
plt.xticks([0, 1, 2, 3, 4], ["1st", "2nd", "3rd", "4th", "5th"])
plt.ylim(0, 100)
plt.show()


하늘색은 Writing, 주황색은 Speaking 성적이다. 그래프를 보니 Clara의 성적이 많이 올랐다는 게 확연히 보인다. 특히 Speaking은 아주 빠른 속도로 실력이 향상됐다는 것을 확인할 수 있다. Clara의 실력이 어떻게 이렇게 향상될 수 있었는지 알아보고, 참새반 학생들의 Speaking 실력 향상을 위해 Clara의 공부법을 다음 학기의 수업에 어떻게 적용하면 좋을지 고민해보자. 이처럼 라인 차트는 시계열 데이터의 변화를 확인할 때 효과적이다.


5) 스캐터플롯(scatter plot)


마지막으로 Speaking 성적과 Writing 성적 사이에 상관관계가 있는지 살펴보자.

plt.scatter(score_writing, score_speaking)
plt.show()


x축은 Writing 시험의 점수를, y축은 Speaking 시험의 점수를 나타낸다. 점들이 분포된 모양을 보니 특정한 규칙이 없어 보인다. 즉, 두 시험의 성적 간 뚜렷한 상관관계는 보이지 않는다.

아래의 차트를 보자.

import seaborn as sns
iris = sns.load_dataset("iris")
data_sample = iris["petal_length"]

plt.scatter(list(iris["sepal_length"]), list(iris["petal_length"]))
plt.show()


이 그림은 파이썬 패키지 중 하나인 Seaborn에서 제공하는 iris 데이터의 꽃잎 길이와 꽃받침 길이에 대한 스캐터플롯이다. 그림을 보면 점들이 직선 모양으로 분포되어 있음을 확인할 수 있다. 이렇게 점들이 일정한 규칙에 따라 분포한 경우 두 변수 사이에 상관관계가 있다고 말한다. 이처럼 스캐터플롯은 두 변수 간의 관계를 나타낼 때 사용한다.


지금까지 참새반 학생들의 데이터와 matplotlib를 사용하여 데이터 시각화 플롯에 대해서 알아보았다. 이 글이 앞으로 당신이 데이터를 분석하고 그 결과를 표현하기 위해 적절한 데이터 시각화 플롯을 선택해야 하는 순간에 조금이나마 도움이 되기를 바란다.

참고한 자료

0개의 댓글