본문 바로가기
개발일지/Pandas

pandas 판다스 기초 12 Matplotlib

by 다니엘의 개발 이야기 2022. 7. 26.
320x100

이번 파트는 정말정말 중요한 부분중에 하나라고 본다.

 

# The plot() method

import pandas as pd
titanic = pd.read_csv('titanic.csv')
titanic.info()

'''
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 9 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   survived  891 non-null    int64  
 1   pclass    891 non-null    int64  
 2   sex       891 non-null    object 
 3   age       714 non-null    float64
 4   sibsp     891 non-null    int64  
 5   parch     891 non-null    int64  
 6   fare      891 non-null    float64
 7   embarked  889 non-null    object 
 8   deck      203 non-null    object 
dtypes: float64(2), int64(4), object(3)
memory usage: 62.8+ KB
'''

# 2째줄에 보면 RangeIndex 라고 있다. 891 인데, 이것은 결측치가 없을때의 범위값. 즉, 정상 non-null의 갯수인 것이다.
# 따라서 891보다 적은 non-null은 그만큼 결측치가 있다고 보면 된다.
import matplotlib.pyplot as plt

# x축은 기본적으로 행의 갯수가 찍히게 되고
# y축은 기본적으로 각각의 필드가 가지고 있는 숫자에 대해서 표현해주게 된다.
titanic.plot()

# show()메서드는 pyplot에서 가장 마지막에 반드시 보여주기 위해서 호출해 주어야 하는 메서드다.
plt.show()
# plot에는 정말 많은 기능들이 들어가있다.
# 그 중에서 한 가지인 subplots
# subplots은 각각의 컬럼에 대해서 분리시켜서, 각 컬럼 별로 그래프를 확인할 수 있게끔 해주는 것이다.

titanic.plot(subplots = True)
plt.show()

# 이에 대해서 크기가 너무 작기 때문에 그래프의 너비, 높이를 정해주어야한다.
# 각 컬럼별로 같은 x축의 표시를 공유하고 싶으면 sharex = False를 추가해주면 된다.
# 값 자체야 sharex 를 쓰든 안쓰든 같은 행의 숫자를 공유하지만, 그것이 표기되는 것은 따로 설정이 없는 경우
# 가장 마지막에 있는 컬럼에 대해서만 표기된다.

# sharex = False는 각 컬럼에 대해서 이 x축의 값을 표시해주는 것이다.
titanic.plot(subplots = True, figsize = (15,12), sharex = False)
plt.show()
# sharey = True는 각 컬럼 중 가장 값이 큰  y축의 값을 기준으로 하여
# 모든 컬럼에 해당 값의 구간을 적용시키는 것이다.
# 기본적으로는 sharey가 False로 설정 되어있다.

titanic.plot(subplots = True, figsize= (15,12), sharex = False, sharey = True)
plt.show()
# 만약 특별한 컬럼 한개만 보고싶다면 원리는 그동안 배웠던것과 같다.
# 옵션을 뺀 이유는 그 동안 쓰인 옵션에 대해서는 2개 이상의 컬럼을 비교할 때 유의미했던 값들이기 때문이다.
titanic.age.plot(figsize = (15,12))
plt.show()


# Customization

# fontsize - 글씨크기(폰트 사이즈)
# c - 그래프 색상
# linestyle - 그래프 표현 선의 스타일 - (-는 기존의 그래프와 같이 하나의 선으로 이어져 있는 형태이고)
# (--는 파선으로 표현되는 형태다.)
# (:는 점선으로 표현되는 형태다.)
titanic.age.plot(figsize = (15,12), fontsize = 13, c = 'purple', linestyle = '--')
plt.show()
# 그래프 제목
titanic.age.plot(figsize = (14,10))
plt.title('title place', fontsize = 15)
plt.show();
# 범주 생성
# loc 자리에는 best = 1, 처럼 10가지 정도의 자리를 정해주는 값이 있다.
# 그 10개의 자리 값 안에서만 범주의 위치가 조정이 가능하다.

titanic.age.plot(figsize = (14,10))
plt.legend(loc = 'best', fontsize = 14)
plt.show();
# x label
# y label
# 각각 x축과 y축에 제목을 붙여 주는 것이다.

# grid는 뒤에 그리드 처리 (사각형으로 격자형태라고 하나? 아무튼 그거 해주는거)
# 그러면 각각에 해당하는 값을 추적해서 가늠하기가 더욱 편리해진다.

titanic.age.plot(figsize = (14,10))
plt.xlabel('rows_num', fontsize = 14)
plt.ylabel('field_num', fontsize = 14)
plt.grid()
plt.show();
# limit 설정
# 이거는 아직 어디에 유용한지는 모르겠으나, 필요할 때가 머잖아 올것같긴 하다.
# xlim에 설정해주는 시작값으로 시작해서 끝값으로 끝나는 것이다.
# ylim도 xlim과 원리가 완전히 동일하다.
# lim은 규격을 정해주는 원리다. 즉, 내가 보길 원하는 해당 변수에 lim 안의 값이 없으면 값도 출력이 안되는 것이다.

titanic.age.plot(figsize= (14,10), xlim=(200,400), ylim=(20,40))
plt.show();

# 중간중간에 짤리게 되는 이유는, 해당 값들이 없기때문이다. 즉, 결측치들 이기 때문이다.

# *******매우 중요******
# 기본적으로 lim을 설정해 주게되면, 해당 시작lim부터 끝 lim에 걸쳐서 구간은 자동 설정되기 때문에
# 구간이 24일수도 있고 100일수도 있고 제각각이다.
# 내가 원하는 구간이 50이라면 다음의 방법을 사용한다.
# 약간 좀 재래식 느낌의 방법인것같다;
# 컴프레헨스로 50단위의 숫자를 만들어준다.
xticks = [x for x in range(0,901,50)]
xticks

'''
[0,
 50,
 100,
 150,
 200,
 250,
 300,
 350,
 400,
 450,
 500,
 550,
 600,
 650,
 700,
 750,
 800,
 850,
 900]
'''
yticks = [y for y in range(0,81,5)]
yticks

# [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]
# xticks, yticks는 시퀀스 즉, 어느정도의 구간을 설정해주겠느냐.라는 설정 값이다.
titanic.age.plot(figsize=(14,10), fontsize = 13,
                xlim = (0,900), ylim = (0,80), xticks = xticks, yticks = yticks)
plt.show();
# x축에 쓰인 값들의 나열 각도를 조절 해주는 기능 rot

titanic.age.plot(figsize = (14,10), rot=45)
plt.show();
# 그래프 전체 스타일을 조정해주는 내장 함수다.
# 일단은 어떤 style이 있는지 확인
plt.style.available

'''
['Solarize_Light2',
 '_classic_test_patch',
 '_mpl-gallery',
 '_mpl-gallery-nogrid',
 'bmh',
 'classic',
 'dark_background',
 'fast',
 'fivethirtyeight',
 'ggplot',
 'grayscale',
 'seaborn',
 'seaborn-bright',
 'seaborn-colorblind',
 'seaborn-dark',
 'seaborn-dark-palette',
 'seaborn-darkgrid',
 'seaborn-deep',
 'seaborn-muted',
 'seaborn-notebook',
 'seaborn-paper',
 'seaborn-pastel',
 'seaborn-poster',
 'seaborn-talk',
 'seaborn-ticks',
 'seaborn-white',
 'seaborn-whitegrid',
 'tableau-colorblind10']
'''
# 스타일을 사용하는 방법
plt.style.use('tableau-colorblind10')


# Histogram

import pandas as pd
import matplotlib.pyplot as plt
# plot 그래프의 style을 seaborn으로 설정
plt.style.use('seaborn')

titanic = pd.read_csv('titanic.csv')
titanic.head(4)

'''
	survived	pclass	sex	age	sibsp	parch	fare	embarked	deck
0	0	3	male	22.0	1	0	7.2500	S	NaN
1	1	1	female	38.0	1	0	71.2833	C	C
2	1	3	female	26.0	0	0	7.9250	S	NaN
3	1	1	female	35.0	1	0	53.1000	S	C
'''
titanic.age.value_counts()

'''
24.00    30
22.00    27
18.00    26
19.00    25
28.00    25
         ..
36.50     1
55.50     1
0.92      1
23.50     1
74.00     1
Name: age, Length: 88, dtype: int64
'''

# 24살이 30번 있으므로, 가장 많은 빈도를 차지 한다는 것을 알 수 있다.
# 즉, value_counts()는 빈도수를 확인하는 함수다.
titanic.age.plot(kind = 'line', figsize = (12,8), fontsize = 15)
plt.show();
# 빈도수를 세되, 계층을 구분해주기
# 기본적으로는 가장 빈도가 많은 그룹부터 나열이 된다.
# 하지만 계층을 기준으로 나열해주고 싶다면 ascding 혹은 sort로 이용하여 정렬하면 된다.
titanic.age.value_counts(bins = 10)

'''
(16.336, 24.294]    177
(24.294, 32.252]    169
(32.252, 40.21]     118
(40.21, 48.168]      70
(0.339, 8.378]       54
(8.378, 16.336]      46
(48.168, 56.126]     45
(56.126, 64.084]     24
(64.084, 72.042]      9
(72.042, 80.0]        2
Name: age, dtype: int64
'''

# 이건 이전에도 한적이 있지만,
# 해당 컬럼의 필드값들이 int 혹은 float처럼 숫자의 형태를 띄고 있어야 가능하며,
# string type의 object들은 bins로 구간을 설정하려고하면 에러가 난다.
# 히스토그램
# 기본적으로 plot은 많은 옵션들을 가지고 있다. 그 중에 하나가 histogram이다.

titanic.age.plot(figsize = (14,10), kind = 'hist', fontsize = 15)
plt.show();

'''
   - 'line' : line plot (default)
    - 'bar' : vertical bar plot
    - 'barh' : horizontal bar plot
    - 'hist' : histogram
    - 'box' : boxplot
    - 'kde' : Kernel Density Estimation plot
    - 'density' : same as 'kde'
    - 'area' : area plot
    - 'pie' : pie plot
    - 'scatter' : scatter plot (DataFrame only)
    - 'hexbin' : hexbin plot (DataFrame only)
'''

# 저 위의 내용들이 모두 kind에 사용이 가능한 값들이다.
# 가장 기본 값으로는 line으로 설정되어있다.
# 계층을 30개로 구분해주기
titanic.age.plot(figsize = (14,10), kind='hist', fontsize =15, bins = 30)
plt.show();


# 두번째 histogram 사용 방법

# 이거는 왜 필요한건진 모르겠다.
# 왜냐하면 이 방법은 최소한에 ylabel의 이름설정을 할 수가 없다.

titanic.age.hist(figsize = (14,10), bins = 80, xlabelsize=14, ylabelsize=14)
plt.show();
# density는 의미가 "밀도"
# cumulative는 의미가 '누적하다'

'''
plt.figure(figsize = (14,10))
plt.hist(titanic.age, bins = 80, density = False, cumulative=False)
plt.show();
'''


# 엠.... 해설강의에는 이게 작동에 있어서 에러가 났었다.
# 이유는 결측값이 age에 포함되어있었기 때문이다.
# 하지만 난 동일한 작업물을 가지고 하는데도 작동이 되었다.
# 아무튼 결측치 때문에 작동이 안되었다고 가정하고
# dropna()를 붙여서, 결측값에 대한 필드는 drop한다는 명령을 주자.

plt.figure(figsize = (14,10))
# dessity는 False일때는 절대 계수로 표기가 되는데 True면 상대 계수로 표시해주는 역할을 한다. 
# 이해는 되나, 크게 뭔말인지 와닿지가 않는다.
 

# 하지만 cumulative는 명확하다. 누적된 값 만큼 오른쪽으로 갈수록 누적값으로 표현되어서
# 결국엔 언덕과 같은 모양이 되거나 아무튼 왼쪽에 비해서 그래프의 모양은 같거나 커질 수 밖에 없어진다.
plt.hist(titanic.age.dropna(), bins = 80, density = False, cumulative= True)
plt.show();

# 약간만 더 생각해보면 cumulative는 결국 누적값이기 때문에 총 합계가 1을 넘지 않는다.
# 혹은 총 합계수를 넘지 않는다.
# 반드시 1 (100%)로 귀결된다.

# 결과적으로 봤을때 density를 False로 해주면 "절대값"측정이 되게 되므로 총 합계 액에 대해 표기되게 되고
# density를 True로 해주게 되면 "상대값"측정이 되기 때문에 반드시 그 값은 1이 된다.


# Barcharts and Piecharts

import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('seaborn')

summer_2012 = pd.read_csv('summer_2012.csv', index_col= 'Country')
summer_2012

'''
	Medal
Country	
USA	250
RUS	130
CHN	128
GBR	126
AUS	114
GER	94
JPN	84
FRA	82
NED	69
ITA	68
ESP	65
KOR	63
BRA	59
CAN	57
CRO	35
HUN	26
MEX	26
NZL	26
JAM	25
UKR	25
Others	393
'''
# kind를 bar로 해놓으면 세로베열로 bar chart가 생성된다.
summer_2012.Medal.plot(kind = 'bar', figsize = (14,10), fontsize = 14, rot = 45)
plt.show();
# 반면, kind를 barh로 해놓으면 가로 배열로 놓이게 된다.
summer_2012.Medal.plot(kind = 'barh', figsize = (14,10), fontsize = 14, rot = 45)
plt.show();
# kind를 pie로 하게 되면 파이차트가 생성된다.
summer_2012.Medal.plot(kind = 'pie', figsize = (14,10), fontsize = 14)
plt.show();


# Scatterplots

import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('seaborn')

titanic = pd.read_csv('titanic.csv')
titanic.plot(kind = 'scatter', figsize = (14,10))
plt.show();

# ValueError: scatter requires an x and y column
# x와 y를 설정해주라는 메세지가 뜬다.
# 이것은 일반적인 x와 y라기 보다는 비교대상1과 비교대상2를 두고 scatter 처리를 해달라는 의미에 더 부합하다.
# scatter를 위한 올바른 시도

titanic.plot(kind = 'scatter', figsize = (14,10), x = 'age', y = 'fare', fontsize = 15)
plt.show();
# scatter의 각 점의 모양은 기본적으로 'o'로 설정이 되어있다.
# 이것을 변경해줄 수도 있다.
# marker가 그것이다.

# 번외로 c - color 색상이며
# s - size 사이즈(크기)이다.
# s로 설정하는 것은 각 점의 크기다.

titanic.plot(kind = 'scatter', figsize = (14,10), x = 'age', y = 'fare', c = 'red', s = 30, marker = 'x')
plt.show();
# 이게 진짜 어메이징 하다.
# 진짜 matplotlib에서 가장 중요한 기능 중 하나라고 본다.
# 생존 여부에 따라서 서로 다른 색으로 표기해주는 것은 그 색상의 자리에, 구분하고자 하는 컬럼의 값을 넣어주는 것이다.
# 3차원 산포도 라고한다.
# 기존에는 2개를 각각 비교하는 2차원 산포도였다면
# 그 2차원 산포도에서 1개의 차원을 더 추가하여 비교해주는 것이기 때문이다.

# c에 컬럼 값을 넣어주면 기본적으로 흑과 백으로 구분이 지어진다. 물론 컬럼의 필드에 몇개의 값이 있느냐에 따라 변동이 될 수 있는 것 같지만
# 기본적으로 2개의 색상에서 진해지고 연해지고로 조절이 되기 때문에 색상이 단조롭다.
# 이것에 변화를 주기 위해서 사용하는 것이 colormap이다.

titanic.plot(kind = 'scatter', figsize = (14,10), x = 'age', y = 'fare', c = 'survived', 
             marker = 's', s = 30, colormap = 'cool')
plt.show()

# colormap의 색상은 https://matplotlib.org/stable/tutorials/colors/colormaps.html
# 여기서 확인 가능하다.
300x250