[모두의 데이터분석 With 파이썬] Unit.06 리뷰 / 다양한 그래프 시각화
2022.03.23 - [데이터 분석 학습] - [모두의 데이터분석 With 파이썬] Unit.01 리뷰 / CSV, 아나콘다, 크롬
2022.03.23 - [데이터 분석 학습] - [모두의 데이터분석 With 파이썬] Unit.02 리뷰 / 주피터, 코랩
2022.03.23 - [데이터 분석 학습] - [모두의 데이터분석 With 파이썬] Unit.03 리뷰 / 데이터 전처리
2022.03.23 - [데이터 분석 학습] - [모두의 데이터분석 With 파이썬] Unit.04 리뷰 / 기본 그래프 그리기
2022.03.24 - [데이터 분석 학습] - [모두의 데이터분석 With 파이썬] Unit.05 리뷰 / 데이터에 맞는 시각화
Unit. 06 기온 그래프를 다양하게 시각화하기
이전에 기온데이터는 꺾은선 그래프로 표현했지만 그걸로는 특별한 정보를 얻기 힘들었다. 정보를 한번에 파악 가능한 다른 형태로 시각화를 해야한다.
- 히스토그램(histogram): 자료의 분포 상태를 직사각형 모양의 막대그래프로 나타낸 것. 데이터의 빈도에 따라 높이가 결정된다.
- hist()함수: 파이썬(matplotlib, pyplot)에서 데이터를 히스토그램으로 그린다.
hist()함수로 파이썬에서 히스토그램을 그려보자
import matplotlib.pyplot as plt # 시각화 라이브러리인 matplotlib에서 .으로 pyplot만 가져오고 plt로 이름을 정해준다
plt.hist([1,1,2,3,4,5,6,6,7,8,10]) # plt(pyplot)라이브러리에서 .으로 hist()함수를 불러오고 함수안에 1,1,2..로 구성된 리스트('[]')를 넣어준다.
plt.show() # plt라이브러리를 보여준다
결과값:
그래프를 보면 수가 2개(1,6)인 지표는 y값이 2로 나오고 9는 없는걸 발견할 수 있다.
본격적인 그래프 그리기를 시작하기 전 주사위 굴리기로 기본 내용을 알아보자
주사위 시뮬레이션
히스토그램 표현 연습을 위해 임의의 수를 뽑는 랜덤 함수를 활용해 주사위 시뮬레이션을 해보면 다음과 같다
- 주사위를 굴린다
- 나온 결과를 기록한다.
- 이전 과정을 n번 반복한다.
- 주사위의 눈이 나온 횟수를 히스토그램으로 그린다.
주사위를 시뮬레이션하기 위해 random 모듈의 randint()함수를 사용한다. 또한 다음 코드가 실행되면 1~6 중 하나의 숫자가 무작위로 출력된다.
*결과값은 어차피 랜덤임으로 따로 기재하지 않을 예정
import random # 랜덤 값을 출력할 수 있는 라이브러리 가져오기
print(random.randint(1,6)) #random 라이브러리에서 .으로 randint를 추가하여 숫자의 범위를 정해준다.
주사위를 여러번 굴리는 상황을 시뮬레이션하려면 for 반복문을 사용해야한다.
5번 굴려 생성된 랜덤 숫자를 dice라는 변수의 리스트에 순서대로 저장해보자
import random # 랜덤 값을 출력할 수 있는 라이브러리 가져오기
dice = [] # dice라는 리스트('[]')를 담는 변수 만들기
for i in range(5): # i라는 변수를 5라는 범위(range(5))안에 넣어둔다.
dice.append(random.randint(1,6)) #dice라는 변수 안에 .으로 append()함수를 실행한다. random 라이브러리에서 .으로 randint를 추가하여 숫자의 범위를 정해준다.
print(dice)
무작위 숫자(1~6)가 dice 변수 안에 5번 반복하여 저장되어 있는 것을 발견할 수 있다.
이 리스트를 히스토그램으로 표현해보면
import matplotlib.pyplot as plt # 시각화 라이브러리인 matplotlib에서 .으로 pyplot만 가져오고 plt로 이름을 정해준다
plt.hist(dice, bins=6) # plt(pyplot)라이브러리에서 .으로 hist()함수를 불러오고 dice 변수를 넣어준다. 구간 개수(bins)는 6개로 설정한다.
plt.show()
결과값:
나는 2가 한번도 나오지 않았다 이걸 100번 해보면?
import random # 랜덤 값을 출력할 수 있는 라이브러리 가져오기
dice = [] # dice라는 리스트('[]')를 담는 변수 만들기
for i in range(100): # i라는 변수를 100이라는 범위(range(100))안에 넣어둔다.
dice.append(random.randint(1,6)) #dice라는 변수 안에 .으로 append()함수를 실행한다. andom 라이브러리에서 .으로 randint를 추가하여 숫자의 범위를 정해준다.
plt.hist(dice, bins=6) # plt(pyplot)라이브러리에서 .으로 hist()함수를 불러오고 dice 변수를 넣어준다. 구간 개수(bins)는 6개로 설정한다.(숫자 범위)
plt.show()
아마 이전보다 꽤 고르게 분포될 것이다. 100만 번 한다면 더더욱 그렇고. 이를 큰 수가 나올수록 수학적 확률에 수렴하는 '큰 수의 법칙'이라 부른다
이제 실제 기온데이터를 히스토그램으로 표현해보자
구간은 100개로 나눈다.
import csv # csv 관련 라이브러리 가져오기
import matplotlib.pyplot as plt # pylpot 라이브러리 가져오고 plt로 이름 설정
f = open('/content/seoul.csv', encoding='cp949') # f라는 변수는 seoul.csv 파일을 cp949라는 형식으로 읽는(open) 변수다
data = csv.reader(f) # data라는 변수는 csv라이브러리의 reader() 함수를 이용해 f변수 안에 담긴 seoul.csv를 읽어오는 것이다.
next(data) # data 변수의 데이터의 첫 번째 데이터 행 읽어오고 탐색 위치를 다음 행으로 이동시킴
result = [] #result 변수는 리스트형태로 설정
for row in data: # data 안의 row(행)에 대해 반복적인 작업을 수행한다.
if row[-1] != '' : # 만약(if) row의 전체(row[-1])를 보았을 때 그것이 비어있지 않은 행(!='')이라면
result.append(float(row[-1])) # result 변수에 row데이터 전체(row[-1])를 추가한다(append). 소수형태로!(float)
plt.hist(result, bins=100, color='r') # plt 라이브러리의 hist() 함수의 내용물을 result 데이터(result)로 넣어주고, 구간을 100개로(bins=100) 두며, 색을 빨간색으로 설정한다(color='r')
plt.show() # 이제 보여줘(show())
결과값:
쌍봉낙타같은 그래프가 나왔다. 여기서 8월 데이터만 뽑아서 그려보자
aug = [] # aug 변수는 리스트형태로 설정
for row in data: # data 안의 row(행)에 대해 반복적인 작업을 수행한다.
month = row[0].split('-')[1] # 행의 첫번째 값에서(row[0]), -로 구분된 값(split('-')) 중 2번째 값[1]을 month 변수에 저장
if row[-1] != '' : # 만약(if) row의 전체(row[-1])를 보았을 때 그것이 비어있지 않은 행(!='')이고
if month == '08': # 만약(if) month 변수의 데이터가 8월달('== 08')이라면
aug.append(float(row[-1])) # aug 변수에 row데이터 전체(row[-1])를 추가한다(append). 소수형태로!(float)
plt.hist(aug, bins=100, color='r') # plt 라이브러리의 hist() 함수의 내용물을 aug 데이터(result)로 넣어주고, 구간을 100개로(bins=100) 두며, 색을 빨간색으로 설정한다(color='r')
plt.show() # 이제 보여줘(show())
결과값:
8월달만 보니 정규분포처럼 나타난다. 그래프를 해석하면 8월에는 30도 정도였던 날이 가장 많았고 20도 이하이거나 40도에 가까웠던 적은 거의 없었다는 것을 알 수 있다.
1월과 8월을 동시에 뽑으려면?
aug = [] # aug 변수는 리스트 형태로 설정, 8월의 최고 기온 값을 저장한다.
jan = [] # jan 변수는 리스트 형태로 설정, 1월의 최고 기온 값을 저장한다.
for row in data: # data 안의 row(행)에 대해 반복적인 작업을 수행한다.
month = row[0].split('-')[1] # 행의 첫번째 값에서(row[0]), -로 구분된 값(split('-')) 중 2번째 값[1]을 month 변수에 저장
if row[-1] != '' : # 만약(if) row의 전체(row[-1])를 보았을 때 그것이 비어있지 않은 행(!='')이고
if month == '08': # 만약(if) month 변수의 데이터가 8월달('== 08')이라면
aug.append(float(row[-1])) # aug 변수에 row데이터 전체(row[-1])를 추가한다(append). 소수형태로!(float)
if month == '01': # 만약(if) month 변수의 데이터가 1월달('== 01')이라면
jan.append(float(row[-1])) # jan 변수에 row데이터 전체(row[-1])를 추가한다(append). 소수형태로!(float)
plt.hist(aug, bins=100, color='r', label='Aug') # plt 라이브러리의 hist() 함수의 내용물을 aug 데이터(result)로 넣어주고, 구간을 100개로(bins=100) 두며, 색을 빨간색으로 설정한다(color='r')
plt.hist(jan, bins=100, color='b', label='Jan') # plt 라이브러리의 hist() 함수의 내용물을 jan 데이터(result)로 넣어주고, 구간을 100개로(bins=100) 두며, 색을 파란색으로 설정한다(color='b')
plt.legend() # 그래프에 범례를 추가한다
plt.show() # 이제 보여줘(show())
결과값:
이처럼 1월과 8월의 데이터는 서로 다른 범위에 있다는 것을 확인할 수 있다.
BoxPlot 그리기
이제 박스플롯 그래프를 그려보자. 일단 randint()함수를 이용해 데이터를 만들고 박스플롯을 그린다
import matplotlib.pyplot as plt
import random
result = []
for i in range(13) : # i라는 변수를 13개의 범위 안에(in range(13)) 넣는다.
result.append(random.randint(1, 1000)) # 1에서 1000까지의 범위 안의 숫자를 랜덤으로 추가한다.
print(sorted(result)) #결과를 출력하는데.... sorted() 함수로 result값을 일렬로 배열한다.
plt.boxplot(result) #boxplot 함수로 result 변수를 그린다.
plt.show()
결과값:
최솟값인 1, 최댓값인 983, 중앙값인 582, 데이터가 주로 있는 부분 등이 한 눈에 들어온다.
import numpy as np
result_ov = np.array(result) # 넘파이 배열 안에 result 데이터 값을 넣는다.
print("1/4: " +str(np.percentile(result_ov,25))) # 출력한다. ("1/4: 값") 형태로. 값은 str()함수로 문자열 형태로 저장한다. 또한 넘파이의 percentile()함수를 활용해 백분위 값으로 저장한다. 여기선 1/4분위(25) 값
print("2/4: " +str(np.percentile(result_ov,50))) # 출력한다. ("2/4: 값") 형태로. 값은 str()함수로 문자열 형태로 저장한다. 또한 넘파이의 percentile()함수를 활용해 백분위 값으로 저장한다. 여기선 2/4분위(50) 값
print("3/4: " +str(np.percentile(result_ov,75))) # 출력한다. ("3/4: 값") 형태로. 값은 str()함수로 문자열 형태로 저장한다. 또한 넘파이의 percentile()함수를 활용해 백분위 값으로 저장한다. 여기선 3/4분위(75) 값
결과값: 1/4: 337.0 2/4: 582.0 3/4: 827.0
각 사분면에 위치한 데이터의 값을 알 수 있다.
for row in data:
if row[-1] != '' : # 만약(if) row의 전체(row[-1])를 보았을 때 그것이 비어있지 않은 행(!='')이면
result.append(float(row[-1])) # result 변수에 row데이터 전체(row[-1])를 추가한다(append). 소수형태로!(float)
plt.boxplot(result) # 박스플롯으로 result 데이터 그리기
plt.show() # 이제 보여줘(show())
그냥 플롯차트를 그릴 때와 똑같다.
히스토그램 그렸던 방식이랑 거의 같다. 1월과 8월도 이전 코드를 가지고 바꿔서 그려본다.
import csv
import matplotlib.pyplot as plt
f = open('/content/seoul.csv', encoding='cp949')
data = csv.reader(f)
next(data)
aug = []
jan = []
for row in data:
month = row[0].split('-')[1]
if row[-1] != '' :
if month == '08':
aug.append(float(row[-1]))
if month == '01':
jan.append(float(row[-1]))
plt.boxplot(aug)
plt.boxplot(jan)
plt.show()
위 그래프를 보면 동그라미가 그려져 있는데 이상치(outlier) 값을 표현한 것으로, 다른 수치에 비해 너무 크거나 작은 값을 자동으로 나타낸 것이다.
plt.boxplot([jan, aug])
오? 월별 데이터도 확인 가능할 것 같다.
요렇게 해보자
month = [[],[],[],[],[],[],[],[],[],[],[],[]] # 큰 하나의 리스트를 담는 month 변수에 하위 12개 리스트 형태를 담는다.
for row in data:
if row[-1] != '' : # row 데이터가 비어있지 않다면
month[int(row[0].split('-')[1])-1].append(float(row[-1])) # month 변수는 정수 형태로(int) row데이터의 첫 번째 값인 날짜 데이터(row[0])를 split() 함수를 이용해 ('-')로 구분하여 2번째 위치의([1])의 값에 1을 빼 월과 같은 번호의 인덱스에 월별 데이터를 저장한다. 1월은 month[0]으로!
plt.boxplot(month)
plt.show()
플롯차트와 비슷한 추세의 그림이 그려진다.
여기서 잠깐!
여기서 중요한 것은 숫자를 리스트의 인덱스 값으로 다루기 위해 int값으로 month의 월별 데이터에 -1를 넣어줬다. 인덱스는 0부터 시작하기 때문에 월별 데이터인 1월과 맞지 않기 때문이다. 만약 여기서 -1을 안해줬다면
next(data)
month = [[],[],[],[],[],[],[],[],[],[],[],[]]
for row in data:
if row[-1] != '' :
month[int(row[0].split('-')[1])].append(float(row[-1]))
plt.boxplot(month)
plt.show()
결과값: list index out of range
이처럼 인덱스 에러가 발생한다. 인덱스의 범위를 벗어나는 것이다. 그럼 리스트가 13개라면?
month = [[],[],[],[],[],[],[],[],[],[],[],[],[]]
for row in data:
if row[-1] != '' :
month[int(row[0].split('-')[1])].append(float(row[-1]))
plt.boxplot(month)
plt.show()
이처럼 정상출력은 되지만 첫번째 인덱스에는 값이 들어가지 않았다는 걸 볼 수 있다. 이렇게 궁금한게 있으면 요리조리 확인해서 확실히 이해하고 넘어가자
day = []
for i in range(31):
day.append([]) # day 리스트 안에 31개 리스트 생성
for row in data:
if row[-1] != '':
if row[0].split('-')[1] == '08': #8월이라면
day[int(row[0].split('-')[2])-1].append(float(row[-1])) # 이번에는 3번째 위치(날짜)를 기준으로 분리한다! 역시 인덱스 값과 맞추기 위해 -1을 붙여준다.
plt.style.use('ggplot') # 그래프 스타일 지정
plt.figure(figsize=(10,5), dpi=300) # 그래프 크기 수정
plt.boxplot(day, showfliers=False) # day 데이터의 아웃라이어값 생략
plt.show()
박스플롯으로 일별 데이터를 한 눈에 확인 가능하다
이번에 배운 명령어 SET
append(): 데이터를 추가하는 명령어. 데이터의 형식도 지정 가능하다(float...) split(): 값을 구분하는 기준을 정하는 명령어, 값의 위치도 설정 가능
- ex) row[0].split('-')[1]
[라이브러리] matplotlib의 pyplot 모듈 명령어
bins= : 가로축의 구간 개수를 설정하는 속성 'bins = 구간개수'
boxplot(): 박스플롯 그래프를 그린다.
showfliers= True/False: 박스플롯에서 이상치를 보여주거나(True) 사라지게 하는 것(False)이다.
style: 그래프의 스타일을 지정하는 코드로 style.use('스타일')형태로 사용한다. 참고로 ggplot은 격자형 무늬를 보여준다.
figure(): 그래프의 모양을 결정한다.
figsize=(가로,세로): figure()에서 그래프의 크기를 결정한다 dpi='dpi크기': dpi 크기를 결정한다.
[라이브러리] random 라이브러리 명령어
randint(): 랜덤 숫자의 범위 정하기 randint(첫 번째 숫자, 마지막 숫자)