오도원입니다.

건강과 행복을 위하여

PNU DSC/파이썬 데이터 분석

02-3. 데이터 시각화 기초 3

오도원공육사 2020. 5. 6. 00:54
반응형

기온 데이터를 다양하게 시각화하기

1. 히스토그램

히스토그램은 자료의 분포상태를 직사각형 모양의 막대 그래프로 나타난 것이다. 막대 그래프의 높이는 데이터의 빈도에 따라 결정된다.

import matplotlib.pyplot as plt
plt.hist([1, 1, 2, 3, 4, 5, 6, 6, 7, 8, 10])
plt.show()

1, 6은 두 개씩 있고, 9를 제외한 나머지는 한 개씩, 9는 아예 없습니다. 

 

주사위 시뮬레이션

random 모듈의 randint() 함수를 사용하여 주사위를 구현해보자.

import random
print(random.randint(1, 6))

randint(a, b)를 실행하면 a이상 b이하의 정수 하나를 반환한다.

 

for문을 사용하여 주사위를 5번 굴려보겠다.

import random
dice = []
for i in range(5):
	dice.append(random.randint(1, 6))
print(dice)

해당 dice를 hist()에 입력하여 출력해보자. bins옵션은 가로축의 구간 개수를 설정하는 속성이다.

plt.hist(dice, bins=6)
plt.show()

이번에는 100번 굴려보자.

dice = []
for i in range(100):
	dice.append(random.randint(1, 6))
plt.hist(dice, bins=6)
plt.show()

1000000번 굴려보자.

dice = []
for i in range(1000000):
	dice.append(random.randint(1, 6))
plt.hist(dice, bins=6)
plt.show()

반복횟수가 1~6까지 거의 1/6씩 (1000000/6 = 166666.66) 균등한 빈도로 발생한다. 

 

실험 또는 관찰을 통해 얻은 통계 비율을 통계적 확률이라 하고, 각각의 사건의 확률이 동일하다고 가정하여 얻은 통계 비율을 '수학적 확률'이라고 한다. 주사위를 던지는 횟수를 늘릴수록 특정 숫자가 나오는 횟수가 전체의 1/6에 가까워진다고 예상할 수 있다. 이러한 법칙을 '큰 수의 법칙'이라고 합니다. 

 

3. 기온 데이터를 히스토그램으로 표현하기

부산의 기온 데이터를 히스토그램으로 표현해보자. 색은 빨간색이고, 구간은 100개로 나누겠습니다.

import csv
import matplotlib.pyplot as plt

f = open('pusan.csv')
data = csv.reader(f)
header = next(data)
result = []

for row in data:
	if row[-1] != '':
    	result.append(float(row[-1]))
    
plt.hist(result, bins=100, color='r')
plt.show()
f.close()

 

이번에는 8월 데이터만 뽑아서 히스토그램으로 그려보겠다.

f = open('pusan.csv')
data = csv.reader(f)
header = next(data)
aug = [] # 8월 최고 기온값을 저장할 aug 리스트

for row in data:
	month = row[0].split('-')[1] # '-'로 구분하여 2번째 값(월)을 month로 저장
    if row[-1] != '':
    	if month == '08': # 8월달 이라면
        	aug.append(float(row[-1])) # aug 리스트에 최고기온 추가
            
plt.hist(aug, bins=100, color='r')
plt.show()
f.close()

1월과 8월 데이터를 히스토그램으로 시각화하기

f = open('pusan.csv')
data = csv.reader(f)
header = next(data)

aug = [] # 8월 최고기온을 저장할 aug 리스트
jan = [] # 1월 최고기온을 저장할 jan 리스트

for row in data : 
	month = row[0].split('-')[1] # '-'로 구분된 값 중 2번째 값(월)을 month에 저장
    if row[-1] != '':
    	if month == '08': # 8월이라면 
        	aug.append(float(row[-1])) # aug리스트에 최고기온 추가
        if month == '01': # 1월이라면
        	jan.append(float(row[-1])) # jan리스트에 최고기온 추가

plt.hist(aug, bins=100, color='r', label='Aug')
plt.hist(jan, bins=100, color='b', label='Jan')
plt.legend()
plt.show()    

한 눈에 확연한 차이를 볼 수 있다. 8월 히스토그램은 20~40 범위에 빨간색으로 나타나고, 1월 히스토그램은 -10~10 범위 안에 파란색으로 표현된 것을 알 수 있다.

 


같은 데이터에서 어떤 내용을 추출하며, 어떤 방법으로 시각화하느냐에 따라 새로운 정보를 발견할 수 있다.


4. 기온 데이터를 상자 그림(boxplot)으로 표현하기

상자 그림은 가공하지 않은 자료를 그대로 이용하는 것이 아니라, 자료에서 얻어낸 최대값, 최소값, 상위 1/4, 2/4(중앙값), 3/4에 위치한 값을 보여주는 그래프이다.

 

먼저, randint()로 임의의 데이터를 생성해서 상자그림으로 나타내보자.

import matplotlib.pyplot as plt
import random

result = []
for i in range(13):
	result.append(random.randint(1, 1000))
print(sorted(result))

plt.boxplot(result)
plt.show()

해당 그래프를 분석하면 다음과 같다.

 

최대값 965, 3/4인 717, 중앙값 549, 1/4인 394, 최소값인 3이 그래프에 표현된다.

 

다른 위치 값을 정확히 알고싶다면 다음과 같이 수행하면 된다.

import numpy as np
result = np.array(result)
print("1/4: " + str(np.percentile(result, 25))
print("2/4: " + str(np.percentile(result, 50))
print("3/4: " + str(np.percentile(result, 75))

 

1월과 8월의 상자 그림을 함께 그려보겠다. 히스토그림을 그릴 때 작성했던 코드에서 그래프의 종류를 히스토그램 hist()에서 상자 그림인 boxplot()으로 바꿔주기만 하면 된다.

f = open('pusan.csv')
data = csv.reader(f)
header = 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()
f.close()

최소값, 최대값, 1/4, 2/4, 3/4 값의 위치를 비교적 명확하게 확인할 수 있다. 

 

boxplot 그래프에서 o(동그라미)는 이상치(outlier) 값을 표현한 것으로, 다른 수치에 비해 너무 크거나 작은 값을 자동으로 나타낸 것이다.

 

boxplot 그래프를 1월, 8월 최고기온 데이터를 원소로 하는 리스트로 표현하면 다음과 같다.

plt.boxplot([aug, jan])

1월, 8월 최고기온 데이터를 표현한 상자 그림이 분리된다.

 

해당 개념을 이용하여 월별 데이터를 상자그림으로 표현해보자.

1. 데이터를 월별로 분류해 저장한다.

2. 월별 데이터를 상자 그림(boxplot)으로 그린다.

# 최고기온 데이터를 월별로 분류하기

f = open('pusan.csv')
data = csv.reader(f)
header = next(data)

# 월별 데이터를 저장할 리스트 month 생성(12개)
month = [[] for _ in range(12)]

for row in data:
    if row[-1] != '':
        # 월과 같은 번호의 인덱스에 월별 데이터 저장(1월 -> month[0])
        month[int(row[0].split('-')[1])-1].append(float(row[-1]))

plt.boxplot(month)
plt.show()
f.close()

 

8월 일별 기온 데이터를 상자 그림으로 표현하기

# 8월 일별 기온 데이터를 boxplot으로 표현하기

f = open('pusan.csv')
data = csv.reader(f)
header = next(data)

day = [[] for _ in range(31)] # 일별 데이터를 저장할 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]))

plt.style.use('ggplot')  #그래프 스타일 지정
plt.figure(figsize=(10,5), dpi=300) # 그래프 크기 수정
plt.boxplot(day, showfliers=False) # 아웃라이어(outlier) 값 생략
plt.show()
f.close()

plt.style.use('ggplot')은 그래프의 스타일을 ggplot으로 지정한 것이다. 배경이 회색의 격자 무늬로 바뀌었으며, 2/4를 의미하는 선의 색도 바뀌었다.

 

plt.figure(figsize=(10, 5), dpi=300)은 그래프의 크기를 가로 10, 세로 5로 지정한 것이다.

 

마지막 showfliers=False는 이상치값(outlier)를 보이지 않게 설정한 것이다.

 

문제. 1년 중 일교차가 가장 큰 달은 몇 월일까?

일교차가 가장 큰 달을 일교차가 가장 큰 날을 포함한 달로 설정하고, 범위를 2019년으로 설정하여 풀어보았다.

 

내 풀이>>

더보기
# 일년 중 일교차가 가장 큰달은 몇 월인가
# 일교차가 가장 큰달을 일교차가 가장 큰 날을 포함한 달로 설정

with open('pusan.csv') as f:
    data = csv.reader(f)
    header = next(data)
    diff_month = []
    max_diff = -999
    max_month = ''
    for row in data:
        if row[0].split('-')[0] == '2020':
            if row[-1] != '' and row[-2] != '':
                diff = float(row[-1]) - float(row[-2])
                if diff > max_diff:
                    max_diff = diff
                    max_month = row[0].split('-')[1]
print(f'1년 중 일교차가 가장 큰 달은 {max_month}월이고, 그 날의 일교차는 {max_diff:g}\'C 였습니다.')
반응형