파이썬

0708 데이터 분석 및 시각화

인뽕 2026. 7. 9. 00:31

 

 

데이터를 다루기 위해서는 데이터를 가공하고 분석만 하는데 그쳐선 안된다.

데이터를 한 눈에 볼 수 있게시각화하는 과정이 반드시 필요하다. 가공되지 않은 데이터의 이상치를 찾아내거나,  결측치, 이상치, 데이터 왜곡 및 타입 오류를 해결하여 의미있는 데이터로 만들고 의미있는 인사이트를 도출해낼 때 데이터의 시각화를 하게 된다.

 

대한민국의 '삶의 만족도', '건강', '경제', '관계및사회참여', '교육', '안전', '환경', '여가' (이하 데이터묶음) ()를 활용해서 지역별 데이터의 평균을 분석하고 시각화 해보자.

 

# 데이터 로드

import pandas as pd

happy_life = pd.read_excel('./data/대한민국행복지도_삶의만족도.xlsx')
happy_life.head();
happy_health =pd.read_excel('./data/대한민국행복지도_건강.xlsx')
happy_health.head()
happy_econo = pd.read_excel('./data/대한민국행복지도_경제.xlsx')
happy_econo.head()
happy_relation =pd.read_excel('./data/대한민국행복지도_관계및사회참여.xlsx')
happy_relation.head()
happy_edu = pd.read_excel('./data/대한민국행복지도_교육.xlsx')
happy_edu.head()
happy_safe = pd.read_excel('./data/대한민국행복지도_안전.xlsx')
happy_safe.head()
happy_leisure = pd.read_excel('./data/대한민국행복지도_여가.xlsx')
happy_leisure.head()
happy_environ = pd.read_excel('./data/대한민국행복지도_환경.xlsx')
happy_environ.head()

 

엑셀에 저장된 각 데이터묶음 들을 pandas의 read_excel 함수로 읽어온다.

 

#데이터 병합

city = list(happy_life['시도'].unique())# 중복제거

happy_merge = pd.DataFrame({'시도' : city})
#삶의 만족도
life = happy_life['삶의 만족도'].groupby(by=happy_health['시도']).mean()
happy_merge = pd.merge(happy_merge,life,on='시도')
#건강
health = happy_health['평균'].groupby(by=happy_health['시도']).mean()
happy_merge = pd.merge(happy_merge,health.rename('건강'),on='시도')
#경제
econo = happy_econo['평균'].groupby(by=happy_econo['시도']).mean()
happy_merge = pd.merge(happy_merge,econo.rename('경제'),on='시도')
#관계및사회참여
relation = happy_relation['평균'].groupby(by=happy_relation['시도']).mean()
happy_merge = pd.merge(happy_merge,relation.rename('관계및사회참여'),on='시도')
#교육
edu = happy_edu['평균'].groupby(by=happy_edu['시도']).mean()
happy_merge = pd.merge(happy_merge,edu.rename('교육'),on='시도')
#안전
safe = happy_safe['평균'].groupby(by=happy_safe['시도']).mean()
happy_merge = pd.merge(happy_merge,safe.rename('안전'),on='시도')
#환경
environ = happy_environ['평균'].groupby(by=happy_environ['시도']).mean()
happy_merge = pd.merge(happy_merge,environ.rename('환경'),on='시도')
#여가
leisure = happy_leisure['평균'].groupby(by=happy_leisure['시도']).mean()
happy_merge = pd.merge(happy_merge,leisure.rename('여가'),on='시도')

데이터묶음 의 '시도' 데이터들을 unique() 함수를 통해 중복이 없는 시도집합을 city 리스트에 저장한다.

중복이 없는시도 데이터들을값으로 갖고 '시도'라는 칼럼을 갖는 happy_merge를 정의한다.

  

데이터묶음 의 '시도' 데이터들로 그룹화 하여 데이터의 평균을 값으로 갖는 시리즈들을 만들고,

어제 공부했던 pandas의 merge 함수를 이용해 각 데이터프레임의 '시도' 데이터로 happy_merge와 병합한다.

이때, 각 데이터묶음 은 같은 종류의 시도를 갖기 때문에 새로운 결측치가 생기지 않는다.

 

#데이터 분석 

happy_merge.info()
happy_merge.describe()

우선 info(), describe()를 통해 결측치를 알아보고 평균을 알아본다.

결측치는 없군.
칼럼별 개수, 평균, 표준편차, 최저값,최고값 등

happy_merge.mean(axis=1,numeric_only=True)# 행의 평균
happy_merge.mean(axis=0,numeric_only=True)# 열의 평균

각 행과 열의 평균을 알아본다. axis =1 : 행 axis = 0 : 열

시도문자열(서울특별시,경기도 등)이 인덱스가 아니고 값이기 때문에, 숫자의 평균을 내는데 문자열 데이터가 섞여들어가는 꼴이기 때문에 mean함수를 사용할때 numeric_only=True를 해줘야 한다.

 

happy_merge.set_index(['시도']).mean(axis=1)

('시도' 데이터를 값 -> 인덱스로 바꾼 데이터프레임).mean이기때문에 여기선 numeric_only=True이 필요 없다.

 

happy_merge.corr(numeric_only=True) # 각 변수(컬럼)들 간의 상관 관계

corr은 각 칼럼들의 상관관계를 나타내는 함수이다.

출력 결과

 


 

 

#데이터 시각화

 

드디어 데이터를 시각화할때가 왔다.

데이터 시각화를 위해서는 matplotlib와 seaborn 라이브러리가 필요하다.

 

import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import seaborn as sns

#OS에 따른 폰트 설정방법
path = 'c:/Windows/Fonts/malgun.ttf'
import platform
from matplotlib import font_manager, rc
if platform.system()=='Darwin':
    rc('font',family='AppleGothic')
elif platform.system() =='Windows':
    font_name=font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system... sorry~~~')

 

우선 플랫폼에 따른 폰트를 설정한다.

 

plt.figure(figsize=(15,6))

플롯의 크기 를 설정한다. 가로 15, 세로 6

 

item = list(happy_merge.columns[1:9])
for a in item:
    chartdata = happy_merge[a]
    plt.plot(chartdata, marker='o', label=a)

 

칼럼의 0열은 '시도' 이므로 1열~8열까지 저장하는 리스트 item을 만들고,

item의 값을 인덱스로하는 happy_merge의 행을  chartdata에 저장하고, plt.plot 함수로 가로축에 지역 라벨을 붙이고 o 모양의 점을 찍고 선을 이어 그래프를 만든다.

 

플롯 그리기

 

여기까지만 하면 뭔가 심심하다. 그래프의 제목과, 가로축 세로축 라벨, 격자, 범례를 추가해주자.

plt.xlabel('시도')
plt.ylabel('수치')
plt.xticks(range(17), happy_merge.index,fontsize=10,rotation=45)
plt.title('대한민국 행복지수')
plt.legend()
plt.grid()
plt.show()

 

짜잔 좀더 이쁜그래프 완성

 

 

#막대 그래프

 

from numpy import *

happy_merge.plot(kind='bar', xlabel = '시도', ylabel='수치',
                 figsize=(15,20), grid=True, subplots=True)

plt.suptitle('대한민국 행복지수', fontsize=25)
plt.tight_layout(pad=8, h_pad =2)
plt.show()

 

위 코드는 matplotlib을 사용하지 않고 pandas의 내장 함수 plot()을 사용해서 막대그래프를 출력하는 코드이다.

subplots=True을 통해 칼럼별로 그래프를 나눠서 그릴 수 있었다. 

 

 

 

꺾은선 그래프와 달리 칼럼 수 슬라이스 처리를 하지 않아 빈 그래프가 하나 더추가된 것을 볼 수 있다.

 

 

 #히트 맵

 

import seaborn as sns

plt.figure(figsize=(15,13))
plt.title('대한민국 행복지수 상관관계',fontsize=25)
plt.rc('axes', unicode_minus=False)
#unicode_minus =False : 한글 사용시, 가끔 '-'부호가 꺠지는 것을 방지
correlation_mat = happy_merge.corr(numeric_only=True)
#happy_merge.corr() : happy_merge의 모든 컬럼들에 대한 
#                     상관관계를 계산하여 계수 표를 만듦
# numeric_only = True : 숫자 영역만
upp_mat = triu(correlation_mat)
#np.triu() : 상관관계 표는 대각선을 기본으로 거울 처럼 표현
#np.ones_like(dtype=bool) :상관관계표와 동일한 크기로 채워진 표
# correlation_mat : corr()로 구한 상관관계 표 데이터
# 참고: triu는 TRIANGLE UPPER의 약자
sns.heatmap(correlation_mat, mask=upp_mat,
            annot=True, cmap='RdYlGn', fmt= '.2f')
# mask=upp_mat : 히트맵의 오른쪽 상단을 가림(masking)
# annot=True : 색상 위에 실제 상관계수를 쓰기
# cmap = 'RdYlGn' : 제공하는 색상 팔레트를 사용 Red Yellow Green
# red->yellow->green 양의 상관관계가 높으면 green
# 음의 상관관계가 높으면 red
# fmt= '.2f' : 숫자를 소수점 이하 두자리까지만

plt.show()

 

상관관계표는 기본적으로 대칭행렬이기 때문에 의미있는 좌하단부만 출력한다.

 

 

 

# 이상치 확인을 위한 boxplot의 예

 

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

#한글 깨짐 방지 설정 (Windows: 'Malgun Gothic', Mac : 'AppleGothic')
plt.rc('font', family='Malgun Gothic')

#1 예시 데이터 만들기(정상 기온 20도 안팎 + 이상치 몇 개)
data = {
        '연도': [2026]*100,
        '기온': list(np.random.normal(loc=20,scale=3,size=97))+[45.2,-15.0,41.8]
        # 45도, -15도 등의 이상치 삽입
        }
weather =pd.DataFrame(data)

#2 boxplot 그리기
plt.figure(figsize=(6,8))
sns.boxplot(y='기온',data=weather,
            color='skyblue',
            flierprops={'markerfacecolor':'red', 'marker':'o'})

#flierprops={'markerfacecolor':'red','marker':'o'}
'''
이상치(Outlier) 점들의 스타일(색상, 모양 등)을 내 입맛대로 꾸미기 위해 사용하는 옵션
'''
plt.title('기온 데이터의 이상치 분석')
plt.ylabel('기온(℃)')
plt.show()
'''
boxplot 보는 방법
'''

 

 

임의의 데이터 만들기 : 정상치 데이터 97개 + 이상치 데이터 3개

 

 

위 박스플롯그래프를 보면 하늘색 박스가평균, 빨간 마커가 이상치로 한눈에 파악할 수 있다.


 

상관계수 용어 정리

 

 

'''
 ...
 1~0~-1 사이의 숫자로 표현
1: 매우 밀접한 관계 : 하나가 크면 다른 하나도 증가 예) 키와 몸무게, 공부 시간과 성적
0: 관계가 없다
-1:매우 밀접한 관계 : 하나가 크면 다른 하나는 감소
    예) 스마트 폰 사용시간과 수면시간

즉, 1, -1은 두 데이터가 강력하게 묶여 있다는 의미    
    0은 두 데이터는 상관 없다
 공분산(Covariance) : 두 개의 데이터가 함께 변화하는 '방향'을 나타내는 통계 값
 공분산이 알려주는 3가지 방향
 공분산> 0 (양수): $X$가 커질 때 $Y$도 같이 커지는 경향이 있다. (우상향)
 공문산< 0 (음수): $X$가 커질 때 $Y$는 작아지는 경향이 있다. (우하향) 공분산 = 0: 두 데이터 사이에 뚜렷한 직선 형태의 관계가 없다.
 두 데이터 X와 Y 있을 때,
 공분산 값의 부호를 보면 두 데이터가 같이 움직이는지, 반대로 움직이는지 알 수 있다 공분산은 두 데이터가 '어떤 방향'으로 움직이는지는 확실하게 알려주지만,
 "그 관계가 얼마나 강한지"는 제대로 알려주지 못한다.
 사람의 '키'와 몸무게'의 공분산을 구한다고 가정.
 키를 미터(m)로 재서 계산했을 때 공분산이 1.5가 나왔다.
 똑같은 사람들의 키를 밀리미터(mm)로 바꿔서 계산하면, 숫자의 단위가 커졌기 때문에 공분산 값이 감자기 1500으로 폭증.
 데이터의 실제 관계는 똑같은데 단위에 따라 숫자가 1.5에서 1500으로 바뀌어 버리니, 다른 데이터와 비교하기가 불가능해진다.
 그래서 이 공분산 을 각 데이터의 '표준편차'로 나누어서, 측정 단위에 상관없이 항상 1에서 그 사이의 값만 나오도록 꽉 암축(정규화)한 것이 바로 앞서 살펴본 상관계수(r).
 •..
 •..
 표준편차 : 데이터들이 평균으로부터 얼마나 멀리 떨어져서 흩어져 있는가?"를 나타내는 숫자
표준편차가 알려주는 것
표준편차가 작다: 데이터들이 평균 근처에 오밀조일하게 모여 있다는 뜻.
(안정적, 예측 가능)
표준편차가 크다: 데이터들이 평균에서 멀리 떨어져서 밟게 퍼져 있다는 뜻.
(변동성이 큼, 들쭉날쭉함)
4반과 B반의 수학 시험 평균이 둘다 70점이라고 가정.
A반: 대부분의 학생이 65점~ 75점 사이를 받았다.    
(평균 근처에 몰려 있음 -> 표준편차가 작다!)
B반: 100점 맞은 학생도 있고, 40점 맞은 학생도 섞여 있다.
(점수가 널뛰기함—> 표준편차가 크다!)
즉, 평균만으로는 알 수 없는 '데이터의 진짜 생김새(퍼짐 정도)'를 알려주는 것이 바로 표준편차
'''

'''
np.random.multivariate_normal(mean, cov, num_points).T

np.random : 임의의 수를 추출
multivariate_normal() : Numpy가 제공하는 다변량 정규분포를 만들어 주는 함수

다변량(Multivariate): 변수가 여러 개(여기서는 X와 Y, 2개) 라는 뜻.
mean (평균) 점들이 어디에 모여 있을지 '중심점'을 정해주기 위함.
코드에서는 [0,0]이었으니 영점(원점) 근처에 점들이 위치.
cov (공분산 행렬): X와 Y가 서로 어떤 방향으로, 얼마나 강하게 엮여서 흩어질지 '규'
여기에 우리가 조절했던 상관계수 (r) 값이 들어간다.
.num_points (개수): 점을 몇 개 찍을 지 정한다. (예: 200개)

따라서 위 함수가 실행되면
파이썬은 (200, 2) 모양의 행렬 (배열)을 만들어낸다.
즉, 200줄(행) 2칸(열)짜리 표가 만들어진다.

.T (Transpose, 전치행렬) : 행과 열을 바꾸는 역할.
데이터가 [x,y] 쌍으로 묶여서 200줄로 서 있으면, 
나중에 x축 데이터와 y축 데이터를 따로 분리해서 그래프에 넣기가 번거롭다.

그래서 수학의 '전치행렬(행과 열을 뒤바꿈' 기능을 하는 .T를 뒤에 붙여준다.
이렇게 하면 (200,2) 모양의 데이터가 (2,200) 모양으로 확 뒤집힌다.
'''

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'파이썬' 카테고리의 다른 글

0713 ML/DL  (0) 2026.07.13
0710 Numpy  (0) 2026.07.10
0709 파이썬 기초 문법 복습  (0) 2026.07.09
0707 Pandas  (0) 2026.07.09
0706 Class  (0) 2026.07.08