이번 비디오에서는 데이터 시각화를 다룬다.
데이터를 탐색하거나 데이터로 부터 얻은 정보를 전달할 때, 시각화를 이용하면 매우 효율적이다. 파이썬 프로그래밍으로 다음 네 가지 시각화 기술을 설명한다.
막대 그래프는 범주별로 도수, 횟수, 퍼센트 등의 크기만큼 막대를 그리는 그래프이다. 범주별 미세한 차이를 명확하게 전달할 수 있는 그래프이다.
영화별 아카데미 수상 횟수가 다음과 같다.
영화 제목 | Annie Hall | Ben-Hur | Casablanca | Gandhi | West Side Story |
수상 횟수 | 5 | 11 | 3 | 8 | 10 |
위 표를 막대 그래프로 그리면 다음과 같다.
from matplotlib import pyplot as plt
movies = ["Annie Hall", "Ben-Hur", "Casablanca", "Gandhi", "West Side Story"]
num_oscars = [5, 11, 3, 8, 10]
plt.bar(range(len(movies)), num_oscars) # x축 레이블 = [0, 1, 2, 3, 4]
plt.ylabel("# of Academy Awards") # y축 레이블
plt.xticks(range(len(movies)), movies) # x축 레이블 = movies 로 변경
plt.show()
축을 지정할 때 조심하지 않으면 오해를 불러일으킬 수 있다.
다음 예제는 2017년과 2018년 사람들이 데이터과학에 대해 언급하는 것을 경험한 횟수를 표로 담고 있다.
연도 | 2017 | 2018 |
횟수 | 500 | 505 |
mentions = [500, 505]
years = [2017, 2018]
plt.bar(years, mentions, 0.8)
plt.xticks(years) # x축 레이블 표시에 필수적임
plt.ylabel("# of times I heard someone say 'data science'")
plt.ticklabel_format(useOffset=False)
# y축의 시작점을 499로 잡으면 오해를 불러일으킬 수 있음.
plt.axis([2016.5, 2018.5, 499, 506])
plt.title("Look at the 'Huge' Increase!")
plt.show()
plt.bar(years, mentions, 0.8)
plt.xticks(years)
plt.ylabel("# of times I heard someone say 'data science'")
plt.ticklabel_format(useOffset=False)
# y축의 시작점을 0으로 잡으면 상황이 달라짐.
plt.axis([2016.5, 2018.5, 0, 550])
plt.title("Not So Huge Anymore")
plt.tight_layout()
plt.show()
히스토그램은 막대 그래프의 한 종류이며, 양적 데이터를 범주로 사용할 때 유용하다. 예를 들어, 무게, 길이, 시간, 점수 등 숫자의 범위에 따라 나뉘어진 데이터를 막대 그래프로 보여줄 때 사용한다.
양적 데이터들의 연속성을 반영하기 위해 막대 그래프들 사이의 간극이 없도록 그린다. 따라서 정해진 구간에 해당되는 항목의 개수나 빈도수를 보여주어 값의 분포를 쉽게 관찰할 수 있게 해준다.
학생들의 점수가 다음과 같다.
83, 95, 91, 87, 70, 0, 85, 82, 100, 67, 73, 77, 0
점수를 십분위수(10점 단위로 구분)로 구분하면 아래 표를 얻는다.
점수 구간(십분위수) | 0-9 | 10-19 | 20-29 | 30-39 | 40-49 | 50-59 | 60-69 | 70-79 | 80-89 | 90-100 |
학생 수 | 2 | 0 | 0 | 0 | 0 | 0 | 1 | 3 | 4 | 3 |
위 데이터를 히스토그램으로 나타내면 다음과 같다.
from collections import Counter
grades = [83, 95, 91, 87, 70, 0, 85, 82, 100, 67, 73, 77, 0]
histogram = Counter(min(grade // 10 * 10, 90) for grade in grades)
plt.bar([x + 5 for x in histogram.keys()],
histogram.values(),
10,
edgecolor=(0, 0, 0))
plt.axis([-5, 105, 0, 5])
plt.xticks([10 * i for i in range(11)])
plt.xlabel("Decile")
plt.ylabel("# of Students")
plt.title("Distribution of Exam 1 Grades")
plt.show()
선 그래프는 막대 그래프의 상단 중심부를 선분으로 연결하여 범주별 변화를 비교하는 그래프이다. 시계열 데이터에 대한 정보를 전달할 때 유용하다.
1950년 부터 10년 주기로 미국 국내총생산(GDP)를 정리한 표가 다음과 같다. 단위는 10억달러이다.
연도 | 1950 | 1960 | 1970 | 1980 | 1990 | 2000 | 2010 |
GDP | 300.2 | 543.3 | 1075.9 | 2862.5 | 5979.6 | 10289.7 | 14958.3 |
위 데이터를 선 그래프로 나타내면 다음과 같다.
years = [1950, 1960, 1970, 1980, 1990, 2000, 2010]
gdp = [300.2, 543.3, 1075.9, 2862.5, 5979.6, 10289.7, 14958.3]
plt.plot(years, gdp, color='green', marker='o', linestyle='solid')
plt.title("Nominal GDP")
plt.ylabel("Billions of $")
plt.show()
머신러닝에서 알고리즘을 학습시킬 때 학습시킨 알고리즘의 예측이 정답으로부터 떨어져 있는 오차를 재는 기준으로 편향(bias)과 분산(variance)를 사용한다.
일반적으로 편향과 분산은 서로 트레이드오프의 관계에 있으며, 두 값의 합이 알고리즘의 오차를 결정한다. 아래 이미지에서 보여주는 세 개의 선 그래프는 분산과 편향과 오류합계(분산+편향)의 관계를 동시에 표현하였다.
variance = [1, 2, 4, 8, 16, 32, 64, 128, 256]
bias_squared = [256, 128, 64, 32, 16, 8, 4, 2, 1]
total_error = [x + y for x, y in zip(variance, bias_squared)]
xs = [i for i, _ in enumerate(variance)]
plt.plot(xs, variance, 'g-', label='variance') # green solid line
plt.plot(xs, bias_squared, 'r-.', label='bias^2') # red dot-dashed line
plt.plot(xs, total_error, 'b:', label='total error') # blue dotted line
plt.legend(loc=9)
plt.xlabel("model complexity")
plt.xticks([])
plt.title("The Bias-Variance Tradeoff")
plt.show()
산점도는 두 변수 간의 연관 관계를 2차원 평면 상에서 점으로 찍어 보여 주는 그래프이다.
어떤 웹사이트 회원의 친구 수와 하룻동안의 사이트 이용시간 사이의 연관 관계를 담은 표가 다음과 같다.
친구 수 | 70 | 65 | 72 | 63 | 71 | 64 | 60 | 64 | 67 |
이용 시간 | 175 | 170 | 205 | 120 | 220 | 130 | 105 | 145 | 190 |
사용자 라벨 | a | b | c | d | e | f | g | h | i |
위 데이터를 선 그래프로 나타내면 다음과 같다.
friends = [ 70, 65, 72, 63, 71, 64, 60, 64, 67]
minutes = [175, 170, 205, 120, 220, 130, 105, 145, 190]
labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
plt.scatter(friends, minutes)
for label, friend_count, minute_count in zip(labels, friends, minutes):
plt.annotate(label,
xy=(friend_count, minute_count),
xytext=(5, -5),
textcoords='offset points')
plt.title("Daily Minutes vs. Number of Friends")
plt.xlabel("# of friends")
plt.ylabel("daily minutes spent on the site")
plt.show()
1차 테스트 | 99 | 90 | 85 | 97 | 80 |
2차 테스트 | 100 | 85 | 60 | 90 | 70 |
test_1_grades = [ 99, 90, 85, 97, 80]
test_2_grades = [100, 85, 60, 90, 70]
plt.scatter(test_1_grades, test_2_grades)
plt.title("Axes Aren't Comparable")
plt.xlabel("test 1 grade")
plt.ylabel("test 2 grade")
plt.show()
결론: 1차 테스트, 2차 테스트 점수가 별 변동이 없는 것으로 보인다.
test_1_grades = [ 99, 90, 85, 97, 80]
test_2_grades = [100, 85, 60, 90, 70]
plt.scatter(test_1_grades, test_2_grades)
plt.title("Axes Are Comparable")
plt.axis("equal") # 양 축의 비율을 동일하게 함
plt.xlabel("test 1 grade")
plt.ylabel("test 2 grade")
plt.show()
결론: 1차 테스트 점수가 높은 친구가 2차 테스트에서 보다 높은 점수를 얻었음을 알 수 있다.