참고: 여기서 사용하는 코드는 조엘 그루스(Joel Grus)의 밑다닥부터 시작하는 데이터 과학 3장에 사용된 소스코드의 일부를 기반으로 작성되었다.
데이터를 탐색하거나 데이터로 부터 얻은 정보를 전달할 때, 시각화를 이용하면 매우 효율적이다. 파이썬을 이용하여 아래 네 가지 시각화 기술을 설명한다.
막대 그래프는 범주별로 도수, 횟수, 퍼센트 등의 크기만큼 막대를 그리는 그래프이다. 범주별 미세한 차이를 명확하게 전달할 수 있는 그래프이다.
영화별 아카데미 수상 횟수가 다음과 같다.
영화 제목 | 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()
산점도는 두 변수 간의 연관 관계를 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차 테스트에서 보다 높은 점수를 얻었음을 알 수 있다.