[Python] 데이터 시각화

0ㅑ채
|2024. 2. 14. 16:24

1. 데이터 시각화 - matplotlib

1) 앤스콤 데이터

- 이 데이터는 4개의 데이터 그룹으로 구성

- 앤스콤 데이터 가져오기

#앤스콤 데이터 가져오기
import seaborn as sns
anscombe = sns.load_dataset("anscombe")
print(anscombe.head())
print(anscombe['dataset'].unique())
  dataset     x     y
0       I     10.0  8.04
1       I      8.0  6.95
2       I     13.0  7.58
3       I      9.0  8.81
4       I     11.0  8.33

['I' 'II' 'III' 'IV']

 

# 데이터셋 분리

#dataset 별로 분리
dataset_1 = anscombe[anscombe['dataset'] == 'I']
dataset_2 = anscombe[anscombe['dataset'] == 'II']
dataset_3 = anscombe[anscombe['dataset'] == 'III']
dataset_4 = anscombe[anscombe['dataset'] == 'IV']

print(dataset_1)

 

   dataset     x      y
0        I  10.0   8.04
1        I   8.0   6.95
2        I  13.0   7.58
3        I   9.0   8.81
4        I  11.0   8.33
5        I  14.0   9.96
6        I   6.0   7.24
7        I   4.0   4.26
8        I  12.0  10.84
9        I   7.0   4.82
10       I   5.0   5.68
  • 데이터셋 네개의 평균, 표준편차를 구해보면 모두 같다.
  • 상관계수도 큰 차이가 없다.
  • 그렇다고 해서 데이터들의 특성이 비슷할 것이라 판단하면 안됨!

 

# 앤스콤 데이터 각 세트 시각화

## 데이터 시각화
import matplotlib.pyplot as plt
fig = plt.figure()

axes1 = fig.add_subplot(2, 2, 1)
axes2 = fig.add_subplot(2, 2, 2)
axes3 = fig.add_subplot(2, 2, 3)
axes4 = fig.add_subplot(2, 2, 4)

axes1.plot(dataset_1['x'], dataset_1['y'], 'o')
axes2.plot(dataset_2['x'], dataset_2['y'], 'o')
axes3.plot(dataset_3['x'], dataset_3['y'], 'o')
axes4.plot(dataset_4['x'], dataset_4['y'], 'o')

axes1.set_title("dataset_1")
axes2.set_title("dataset_2")
axes3.set_title("dataset_3")
axes4.set_title("dataset_4")

  • axes4는 상관계수가 전혀 보이지 않는데
  • 이상치 하나가 평균이나 상관계수에 영향을 많이 준 것이다.

 

2) 자주 사용되는 시각화 라이브러리

- matplotlib: 가장 기본이 되는 라이브러리

- seaborn

- plotnine

- polt.ly

- pyecharts

- folium: 지도 시각화

 

 

3) matplotlib

- 시각화(그래프, 이미지)에 가장 많이 이용하는 라이브러리

- 파이썬의 대다수 시각화 기능

- 설치 필요

* 아나콘다는 내장

 

# 엑셀 파일 읽기

df = pd.read_excel('./data/시도_별_이동자수.xlsx', header=0)
df.head()

 

# 엑셀에서 셀 병합이 있으면 천번째를 제외하고는 NaN으로 처리

df = df.fillna(method="ffill")
df.head()

 

# 조건에 맞는 데이터 필터링

#전출지별 : 서울특별시
#전입지별 : 서욱특별시가 아닌 데이터
mask = (df['전출지별'] == '서울특별시') & (df['전입지별'] != '서울특별시')
df_seoul = df[mask]
df_seoul

 

# 컬럼 삭제

df_seoul = df_seoul.drop(['전출지별'], axis=1, inplace=True)

 

# 컬럼 이름변경

df_seoul.rename({'전입지별':'전입지'}, axis=1, inplace=True)

 

# 인덱스 설정

df_seoul.set_index('전입지', inplace=True)

 

 

4) 라인그래프 그리기

# 인덱스가 전라남도인 데이터 추출
sr_one = df_seoul.loc['전라남도']
sr_one

import matplotlib.pyplot as plt
plt.plot(sr_one.index, sr_one.values)
plt.show()
1970    10513
1971    16755
1972    20157
1973    22160

....

 

- matplotlib을 사용했을 때의 문제점

  • 한글이나 음수는 제대로 출력되지 않음

 

한글 처리

import matplotlib.pyplot as plt
#그래프 크기 설정 - 단위는 inch
plt.figure(figsize=(14, 5))
#x축 눈금 라벨 회전
plt.xticks(size=10, rotation='vertical')
plt.title('seoul->전라남도', size=20)
plt.plot(sr_one.index, sr_one.values)
plt.show()

 

from matplotlib import font_manager, rc
import platform

font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)

 

#라인 그래프 출력
plt.plot(sr_one.index, sr_one.values, marker='o', markersize=5)

#축 제목
plt.xlabel('기간', size=20)
plt.ylabel('이동 인구수', size=20)

#범례
plt.legend(labels=['서울 -> 전라남도'], loc='best', fontsize=15)

plt.show()

5) 막대그래프 그리기

#그래프 크기 설정 - 단위는 inch
plt.figure(figsize=(14, 5))

# 제목 설정
plt.title('서울->전라남도', size=20)

# x축 눈금 라벨 회전
plt.xticks(size=10, rotation='vertical')

#막대 그래프
plt.bar(sr_one.index, sr_one, width =1.0)

plt.show()

 

6) 빈도수 그래프 (히스토그램)

df = pd.read_csv('./data/lovefruits.csv', encoding='cp949')
df
  • 웹사이트는 euk-kr
  • 파일은 cp949
data = df['선호과일'].value_counts(sort=False)
data
선호과일
사과      4
바나나     3
포도      5
복숭아    11
체리      8
Name: count, dtype: int64

 

막대그래프로 그리기 - 직접 빈도수 구해야 함

data = df['선호과일'].value_counts(sort=False)
plt.bar(range(0, len(data), 1), data)
plt.xticks(range(0, len(data), 1), data.index)

plt.show()

히스토그램 - 알아서 빈도수 구해줌

plt.hist(df['선호과일'])
plt.show()

 

 

7) 산포도(scatter)

- 데이터 분포나 상관관계를 파악하기 위한 그래프

- x와 y 옵션에 데이터를 설정

- s 옵션: 사이즈를 설정해서 크기로 다른데이터를 반영하는 것이 가능

mpg = pd.read_csv('./data/auto-mpg.csv', header=None)
mpg.columns = ['mpg', 'cylinders', 'displacement', 'horsepower', 'weight', 'acceleration', 'model year', 'origin', 'name']
plt.scatter(x=mpg['weight'], y=mpg['mpg'])
plt.show()

size = mpg['cylinders'] / mpg['cylinders'].max() * 200
plt.scatter(x=mpg['weight'], y=mpg['mpg'], s=size, c='coral', alpha=0.5)
plt.show()

 

 

8) pie 

- 기여도를 나타냄

 

9) box plot

- 데이터의 범위를 표현

 

10) fill_between

- 데이터 크기를 영역으로 나타내는 그래프 

 

 

 

2. Seaborn

- matplotlob 기반으로 다양한 색상 테마와 통계용 차트의 기능을 추가한 패키지

- numpy와 pandas의 자료구조 지원

- 샘플데이터 

  • 내장되어 있음
  • load_dataset 메소드로 호출, DataFrame으로 리턴
#회귀에서 사용하는 데이터 셋 가져오기
import seaborn as sns
tips = sns.load_dataset("tips")
print(tips.head())

 

1) 산점도와 회귀식을 출력

  • regplot(), implot() 이용
  • 산점도와 회귀선 같이 출력
  • 회귀선 출력하지 않으려면 fit_reg 옵션 설정을 수정
  • data에 데이터프레임을 설정하고 x와 y에 컬럼 이름 설정
plt.figure(figsize=(8,6)) #캔버스 크기 설정
sns.regplot(x="total_bill", y="tip", data=tips)
plt.show()

 

# 회귀선 두개 옵션

plt.figure(figsize=(8,6)) #캔버스 크기 설정
sns.lmplot(x="total_bill", y="tip", hue = 'smoker', data=tips)
plt.show()

 

2) heatmap

- 기간별 추세를 알아보고자 할 때 사용

- 가로와 세로 모두 기간을 설정하고 색상을 이용해서 크기 설정

- 라인 그래프는 일반적으로 가로 방향에만 기간 설정

- 히트맵을 출력할 때는 범례나 레이블을 출력해줘야 값의 변화를 파악하기 쉽다. 

flights = sns.load_dataset("flights")
print(flights)
     year month  passengers
0    1949   Jan         112
1    1949   Feb         118
2    1949   Mar         132
3    1949   Apr         129
4    1949   May         121
..    ...   ...         ...
print(flights.pivot(columns=("month", "year", "passengers")))
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, ...]

[144 rows x 0 columns]
data = flights.pivot(index="month", columns="year", values="passengers")
print(data)
year   1949  1950  1951  1952  1953  1954  1955  1956  1957  1958  1959  1960
month                                                                        
Jan     112   115   145   171   196   204   242   284   315   340   360   417
Feb     118   126   150   180   196   188   233   277   301   318   342   391
Mar     132   141   178   193   236   235   267   317   356   362   406   419
Apr     129   135   163   181   235   227   269   313   348   348   396   461
May     121   125   172   183   229   234   270   318   355   363   420   472
Jun     135   149   178   218   243   264   315   374   422   435   472   535
Jul     148   170   199   230   264   302   364   413   465   491   548   622
Aug     148   170   199   242   272   293   347   405   467   505   559   606
Sep     136   158   184   209   237   259   312   355   404   404   463   508
Oct     119   133   162   191   211   229   274   306   347   359   407   461
Nov     104   114   146   172   180   203   237   271   305   310   362   390
Dec     118   140   166   194   201   229   278   306   336   337   405   432
sns.heatmap(data, annot=True, fmt='d')
기본  annot = True fmt = 'd'

 

 

3) 데이터 분포를 출력해주는 다양한 그래프

- boxplot: 4분위수와 IQR * 1.5배 되는 데이터의 위치 및 그 이외의 데이터 분포 확인

* IQR: (3/4-1/4)

 

- violinplot: 4분위 수 대신에 두께를 이용해서 데이터의 밀집 형태 판단할 수 있음

 

- stripplot: 두께가 아니라 점으로 데이터의 밀집 형태 표시 (점이 겹침)

 

- swarmplot: 두께가 아니라 점으로 데이터의 밀집 형태 표시 (점이 겹치지 않음)

 

- box plot과 swarmplot을 같이 추력하면 데이터의 밀집 형태 확인 가능

 

- pairplot: 데이터프레임의 컬럼이 숫자로만 된 경우 2개씩 조합해서 모든 경우의 조합의 산포도 출력

 

# boxplot

tips = sns.load_dataset('tips')
sns.boxplot(x='day', y='total_bill', data=tips)
plt.show()

 

# violinplot

sns.violinplot(x='day', y='total_bill', data=tips)
plt.show()

  • 데이터의 밀집 형태를 두께감으로 표시

# stripplot

sns.stripplot(x='day', y='total_bill', hue='smoker', data=tips)
plt.show()

# swarmplot

sns.swarmplot(x='day', y='total_bill', data=tips)
plt.show()

# box plot과 swarmplot을 같이

sns.boxplot(x='day', y='total_bill', data=tips)
sns.swarmplot(x='day', y='total_bill', data=tips)
plt.show()

# pariplot

sns.pairplot(tips)
plt.show()

  • tip과 total_bill만 상관관계
sns.pairplot(tips[['total_bill', 'tip', 'size']])
plt.show()
  • 숫자 데이터만 넣어주는게 바람직

 

 

3. Plotnine

- R의 ggplot2에 기반해서 그래프를 그려주는 라이브러리

- 기본 패키지가 아니라서 설치 필요

- 도큐먼트: https://plotnine.readthedocs.io/en/stable 

- 파이썬을 매개변수를 설정할 때 쉼표(,)로 구분하는데, R은 +로 결합 가능

import plotnine
df = pd.DataFrame({
    'letter':["Alpha", 'Beta', 'Delta', 'Gamma'] * 2,
    'pos':[1, 2, 3, 4] * 2,
    'num_of_letters': [5, 4, 5, 5] * 2
})

(plotnine.ggplot(df)
+ plotnine.geom_col(plotnine.aes(x='letter', y='pos', fill='letter')) 
+ plotnine.geom_line(plotnine.aes(x='letter', y='num_of_letters', color='letter'), size=1) 
+ plotnine.scale_color_hue(I=0.45)
+ plotnine.ggtitle('Greek Letter Analysis')
)

 

 

4. plotly

- 인터럭티브한 그래프를 그려주는 라이브러리

- https://plotly.com/python 

- D3.js 라이브러리 활용

  • 자바스크립트로 차트를 html에 표현하는 라이브러리
  • 웹상에서 동적인 차트 가능

- 설치: chart_studio 라이브러리도 함께 설치

 

 

5. folium

- 지도를 그려주는 라이브러리

- 자바스크립트 기반으로 인터럭티브한 그래프

- 설치 필요

- Map() 함수를 이용해서 지도 객체를 생성

  • locations 옵션에 중앙점의 위도와 경도 설정하고 zoom_start 옵션에 초기 확대 축소 배율 설정

- Chrome 브라우저를 사용하는 Jupyter Notebook에서는 바로 출력이 가능, 그 이외의 경우에는 html로 저장해서 확인

- 단계 구분도 생성 가능

import folium

m = folium.Map(location = [37.572656, 126.973300], zoom_start=15)
m

 

지도 위에 마커 표시

folium.Marker(location=[위도, 경도], popup='보여지는 문자열', icon=이미지모양).add_to(맵객체)
folium.Marker(location=[37.572656, 126.973300], popup='여기예요', icon=folium.Icon(color='red')).add_to(m)
m

 

 

 

 

 

 

 

'Python' 카테고리의 다른 글

[Python] 데이터 스케일링  (1) 2024.02.16
[Python] 데이터 전처리  (0) 2024.02.15
[Python] 데이터 탐색  (0) 2024.02.14
[Python] MySQL 데이터로 DataFrame 만들기  (0) 2024.02.14
[Python] 크롤링 - Selenium  (0) 2024.02.14