You are on page 1of 124

10.

데이터 확인
[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
DataFrame 확인
계산 가능한 데이터에 대해 Column 별로 데이터의 갯수, 평균, 표준편차, 최소/최대값
등의 정보를 보여줌
[5]
df.describe()

출력

[6]
df.info()

<class 'pandas.core.frame.DataFrame'>
Index: 8 entries, 1번 to 8번
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 이름 8 non-null object
1 학교 8 non-null object
2 키 8 non-null int64
출력
3 국어 8 non-null int64
4 영어 8 non-null int64
5 수학 8 non-null int64
6 과학 8 non-null int64
7 사회 8 non-null int64
8 sw특기 6 non-null object
dtypes: int64(6), object(3)
memory usage: 640.0+ bytes

- 2 -
[7]
df.head()

출력

[8]
df.head(7) #처음 7개의 row를 가져옴

출력

[9]
df.tail() #마지막 5개 row를 가져옴

출력

- 3 -
[10]
df.tail(3) #마지막 3개 row를 가져옴

출력

[11]
df.values

array([['채치수', '북산고', 197, 90, 85, 100, 95, 85, 'Python'],


['정대만', '북산고', 184, 40, 35, 50, 55, 25, 'Java'],
['송태섭', '북산고', 168, 80, 75, 70, 80, 75, 'Javascript'],
['서태웅', '북산고', 187, 40, 60, 70, 75, 80, nan],
출력
['강백호', '북산고', 188, 15, 20, 10, 35, 10, nan],
['변덕규', '능남고', 202, 80, 100, 95, 85, 80, 'C'],
['황태산', '능남고', 188, 55, 65, 45, 40, 35, 'PYTHON'],
['윤대협', '능남고', 190, 100, 85, 90, 95, 95, 'C#']], dtype=object)

[12]
df.index

출력 Index(['1번', '2번', '3번', '4번', '5번', '6번', '7번', '8번'], dtype='object', name='지원번호')

[13]
df.columns

출력 Index(['이름', '학교', '키', '국어', '영어', '수학', '과학', '사회', 'sw특기'], dtype='object')

[14]
df.shape

출력 (8, 9)

- 4 -
[15]
df

출력

Series 확인
[16]
df['키'].describe()

count 8.000000
mean 188.000000
std 9.985704
min 168.000000
출력 25% 186.250000
50% 188.000000
75% 191.750000
max 202.000000
Name: 키, dtype: float64

[17]
df['키'].min()

출력 168

[18]
df['키'].max()

출력 202

- 5 -
[19]
df['키'].nlargest(3) #키 큰 사람 순서대로 3명 데이터

지원번호
6번 202
출력 1번 197
8번 190
Name: 키, dtype: int64

[20]
df['키'].mean()

출력 188.0

[21]
df['키'].sum()

출력 1504

[22]
df['sw특기'].count()

출력 6

[23]
df['학교'].unique()

출력 array(['북산고', '능남고'], dtype=object)

[24]
df['학교'].nunique()

출력 2

- 6 -
11. 데이터 선택(기본)
[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
Column 선택 (label)
[5]
df['이름']

지원번호
1번 채치수
2번 정대만
3번 송태섭
4번 서태웅
출력
5번 강백호
6번 변덕규
7번 황태산
8번 윤대협
Name: 이름, dtype: object

[6]
df['키']

지원번호
1번 197
2번 184
3번 168
4번 187
출력
5번 188
6번 202
7번 188
8번 190
Name: 키, dtype: int64

- 2 -
[7]
df[['이름','키']]

출력

Column 선택 (정수 index)


[8]
df.columns

출력 Index(['이름', '학교', '키', '국어', '영어', '수학', '과학', '사회', 'sw특기'], dtype='object')

[9]
df.columns[0]

출력 '이름'

[10]
df.columns[2]

출력 '키'

- 3 -
[11]
df[df.columns[0]] #df['이름'] 과 동일한 동작

지원번호
1번 채치수
2번 정대만
3번 송태섭
4번 서태웅
출력
5번 강백호
6번 변덕규
7번 황태산
8번 윤대협
Name: 이름, dtype: object

[12]
df[df.columns[-1]] #맨 끝에 있는 값을 가져옴

지원번호
1번 Python
2번 Java
3번 Javascript
4번 NaN
출력
5번 NaN
6번 C
7번 PYTHON
8번 C#
Name: sw특기, dtype: object

- 4 -
슬라이싱
[13]
df

출력

[14]
df['영어'][0:5]

지원번호
1번 85
2번 35
출력 3번 75
4번 60
5번 20
Name: 영어, dtype: int64

[15]
df[['이름','키']][:3]

출력

- 5 -
[16]
df[3:]

출력

- 6 -
12. 데이터 선택(loc)
이름을 이용하여 원하는 row에서 원하는 col 선택

[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
[5]
df.loc['1번'] # index 1번에 해당하는 전체 데이터

이름 채치수
학교 북산고
키 197
국어 90
영어 85
출력
수학 100
과학 95
사회 85
sw특기 Python
Name: 1번, dtype: object

[6]
df.loc['5번'] # index 5번에 해당하는 전체 데이터

이름 강백호
학교 북산고
키 188
국어 15
영어 20
출력
수학 10
과학 35
사회 10
sw특기 NaN
Name: 5번, dtype: object

[7]
df.loc['1번','국어'] # index 1번에 해당하는 국어 데이터

출력 90

- 2 -
[8]
df.loc[['1번','2번'],'영어'] # index 1번, 2번에 헤당하는 영어 데이터

지원번호
1번 85
출력
2번 35
Name: 영어, dtype: int64

[9]
df.loc[['1번','2번'],['영어','수학']] # index 1번, 2번에 해당하는 영어, 수학 데이터

출력

[10]
df.loc['1번':'5번','국어':'사회'] # index 1번부터 5번까지, 국어부터 사회까지 데이터

출력

- 3 -
14. 데이터 선택(조건)
조건에 해당하는 데이터 선택

[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
[5]
df['키'] >= 185 # 학생들의 키가 185 이상인지 여부를 True / False

지원번호
1번 True
2번 False
3번 False
4번 True
출력
5번 True
6번 True
7번 True
8번 True
Name: 키, dtype: bool

[6] filt = (df['키'] >= 185)


df[filt]

출력

[7]
df[~filt] # filter 를 역으로 적용

출력

- 2 -
[8]
df[df['키'] >= 185]

출력

[9]
df.loc[df['키'] >= 185, '수학'] # 키가 185 이상인 학생들의 수학 데이터

지원번호
1번 100
4번 70
5번 10
출력
6번 95
7번 45
8번 90
Name: 수학, dtype: int64

[10] # 키가 185 이상인 학생들의 이름, 수학, 과학 데이터


df.loc[df['키'] >= 185, ['이름','수학','과학']]

출력

- 3 -
다양한 조건
& 그리고
[11] # 키가 185 이상인 북산고 학생 데이터
df.loc[(df['키'] >= 185) & (df['학교'] == '북산고')]

출력

| 또는
[12] # 키가 170 보다 작거나, 200 보다 큰 학생 데이터
df.loc[(df['키'] < 170) | (df['키'] > 200)]

출력

str 함수
[13]
df['이름'].str.startswith('송') # '송'씨 성을 가진 사람

지원번호
1번 False
2번 False
3번 True
4번 False
출력
5번 False
6번 False
7번 False
8번 False
Name: 이름, dtype: bool

- 4 -
[14] filt = df['이름'].str.contains('태') #이름에 '태'가 들어가는 사람
df[filt]

출력

[15]
df[~filt] # 이름에 '태'가 들어가는 사람을 제외

출력

[16] langs = ['Python', 'Java']


filt = df['sw특기'].isin(langs) # sw 특기가 Python이거나 Java인 사람
df[filt]

출력

- 5 -
[17]
df

출력

[18] langs = ['python', 'java']


filt = df['sw특기'].str.lower().isin(langs)
df[filt]

출력

[19] filt = df['sw특기'].str.contains('Java')


df[filt]

# 에러 일부 생략
출력
ValueError: Cannot mask with non-boolean array containing NA / NaN values

- 6 -
[20]
df['sw특기'].str.lower().isin(langs)

지원번호
1번 True
2번 True
3번 False
4번 False
출력
5번 False
6번 False
7번 True
8번 False
Name: sw특기, dtype: bool

[21]
df['sw특기'].str.contains('Java', na=True) # NaN 데이터에 대해서 True로 설정

지원번호
1번 False
2번 True
3번 True
4번 True
출력
5번 True
6번 False
7번 False
8번 False
Name: sw특기, dtype: bool

[22]
df['sw특기'].str.contains('Java', na=False) # NaN 데이터에 대해서 False로 설정

지원번호
1번 False
2번 True
3번 True
4번 False
출력
5번 False
6번 False
7번 False
8번 False
Name: sw특기, dtype: bool

- 7 -
[23] filt = df['sw특기'].str.contains('Java', na=False)
df[filt]

출력

- 8 -
15. 결측치
비어 있는 데이터

[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
NaN 확인하기 isnull
[5]
df.isnull()

출력

[6]
df.isnull().sum() # 각 열의 NaN 데이터 개수 계산하기

이름 0
학교 0
키 0
국어 0
영어 0
출력
수학 0
과학 0
사회 0
sw특기 2
dtype: int64

- 2 -
데이터 채우기 fillna
[7]
df.fillna('') # NaN 데이터를 빈 칸으로 채움

출력

[8]
df.fillna('없음')

출력

- 3 -
[9] import numpy as np
df['학교'] = np.nan
df

출력

[10]
df.fillna('모름')

출력

[11]
df.fillna('모름', inplace=True)

- 4 -
[12]
df

출력

[13] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

[14] # sw특기 데이터 중에서 NaN에 대해서 채움


df['sw특기'].fillna('확인 중', inplace=True)

- 5 -
[15]
df

출력

- 6 -
데이터 제외하기 dropna
[16] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')
df

출력

[17] # 전체 데이터 중에서 NaN을 포함하는 데이터 삭제


df.dropna(inplace=True)

[18]
df

출력

- 7 -
[19] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')
df

출력

- 8 -
• axis : index or columns
• how : any or all
[20]
df.dropna(axis='index',how='any') # NaN이 하나라도 있는 row 삭제

출력

[21]
df.dropna(axis='columns') # NaN이 하나라도 있는 column 삭제

출력

- 9 -
[22] df['학교'] = np.nan
df

출력

[23] # 데이터 전체가 NaN인 경우에만 column 삭제


df.dropna(axis='columns', how='all')

출력

- 10 -
16. 데이터 정렬
[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
[5]
df.sort_values('키') # 키 기준으로 오름차순 정렬

출력

[6]
df.sort_values('키', ascending=False) # 키 기준으로 내림차순 정렬

출력

[7]
df.sort_values(['수학','영어']) # 수학, 영어 점수 기준으로 오름차순

출력

- 2 -
[8]
df.sort_values(['수학','영어'], ascending=False) # 수학, 영어 점수 기준으로 내림차순

출력

[9] # 수학 점수는 오름차순으로, 영어 점수는 내림차순으로 정렬


df.sort_values(['수학','영어'], ascending=[True, False])

출력

[10]
df['키'].sort_values()

지원번호
3번 168
2번 184
4번 187
5번 188
출력
7번 188
8번 190
1번 197
6번 202
Name: 키, dtype: int64

- 3 -
[11]
df['키'].sort_values(ascending=False)

지원번호
6번 202
1번 197
8번 190
5번 188
출력
7번 188
4번 187
2번 184
3번 168
Name: 키, dtype: int64

[12]
df.sort_index()

출력

[13]
df.sort_index(ascending=False)

출력

- 4 -
17. 데이터 수정
[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
Column 수정
[5]
df['학교'].replace({'북산고':'상북고', '능남고':'무슨고'})

지원번호
1번 상북고
2번 상북고
3번 상북고
4번 상북고
출력
5번 상북고
6번 무슨고
7번 무슨고
8번 무슨고
Name: 학교, dtype: object

[6]
df

출력

[7]
df['학교'].replace({'북산고':'상북고'}, inplace=True)

- 2 -
[8]
df

출력

[9]
df['sw특기'].str.lower()

지원번호
1번 python
2번 java
3번 javascript
4번 NaN
출력
5번 NaN
6번 c
7번 python
8번 c#
Name: sw특기, dtype: object

[10]
df['sw특기'] = df['sw특기'].str.lower()

- 3 -
[11]
df

출력

[12]
df['sw특기'] = df['sw특기'].str.upper()

[13]
df

출력

- 4 -
[14] df['학교'] = df['학교'] + '등학교' # 학교 데이터 + 등학교
df

출력

Column 추가
[15] df['총합'] = df['국어'] + df['영어'] + df['수학'] + df['과학'] + df['사회']
df

출력

[16]
90 + 85 + 100 + 95 +85

출력 455

- 5 -
[17] df['결과'] = 'Fail'
df

출력

[18] # 총합이 400보다 큰 데이터에 대해서 결과를 Pass로 업데이트


df.loc[df['총합'] > 400, '결과'] = 'Pass'
df

출력

- 6 -
Column 삭제
[19]
df.drop(columns=['총합']) # 총합 Column을 삭제

출력

[20]
df

출력

- 7 -
[21]
df.drop(columns=['국어','영어','수학']) #국어, 영어, 수학 Column을 삭제

출력

[22]
df

출력

- 8 -
Row 삭제
[23]
df.drop(index='4번') # 4번 학생 데이터 row 삭제

출력

[24] filt = df['수학'] < 80 # 수학 점수 80점 미만 학생 필터링


df[filt]

출력

[25]
df[filt].index

출력 Index(['2번', '3번', '4번', '5번', '7번'], dtype='object', name='지원번호')

[26]
df.drop(index=df[filt].index)

출력

- 9 -
[27]
df

출력

Row 추가
[28] df.loc['9번'] = ['이정환', '해남고등학교', 184, 90, 90, 90, 90, 90, 'Kotlin', 450, 'Pass']
df

출력

- 10 -
Cell 수정
[29] # 4번 학생의 sw특기 데이터를 Python으로 변경
df.loc['4번','sw특기'] = 'Python'
df

출력

[30] # 5번 학생의 학교는 능남고등학교로, sw특기는 C로 변경


df.loc['5번',['학교','sw특기']] = ['능남고등학교', 'C']
df

출력

- 11 -
Column 순서 변경
[31] cols = list(df.columns)
cols

출력 ['이름', '학교', '키', '국어', '영어', '수학', '과학', '사회', 'sw특기', '총합', '결과']

[32] # 맨 뒤에 있는 결과 Column을 앞으로 가져오고, 나머지 Column들과 합쳐서 순서 변경


df = df[[cols[-1]] + cols[0:-1]]
df

출력

[33] df = df[['결과','이름','학교']]
df

출력

- 12 -
Column 이름 변경
[34]
df.columns

출력 Index(['결과', '이름', '학교'], dtype='object')

[35] df.columns = ['Result', 'Name', 'School']


df

출력

[36] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 13 -
[37]
df.rename(columns={'이름':'성명', '학교':'고등학교'})

출력

[38] df.rename(columns={'이름':'성명', '학교':'고등학교'}, inplace=True)


df

출력

- 14 -
18. 그룹화
동일한 값을 가진 것들끼리 합쳐서 통계 또는 평균 등의 값을 계산하기 위해 사용

[1]
import pandas as pd

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4] df = pd.read_excel(drive_path + 'score.xlsx', index_col='지원번호')


df

출력

- 1 -
[5]
df.groupby('학교')

출력 <pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fa5b466a250>

[6]
df.groupby('학교').get_group('북산고')

출력

[7]
df.groupby('학교').get_group('능남고')

출력

[8]
df.groupby('학교').mean() #계산 가능한 데이터들의 평균값

출력

- 2 -
[9]
df.groupby('학교').size() #각 그룹의 크기

학교
능남고 3
출력
북산고 5
dtype: int64

[10] #학교로 그룹화를 한 뒤에 능남고에 해당하는 데이터의 수


df.groupby('학교').size()['능남고']

출력 3

[11] #학교로 그룹화를 한 뒤에 키의 평균 데이터


df.groupby('학교')['키'].mean()
학교
능남고 193.333333
출력
북산고 184.800000
Name: 키, dtype: float64

[12] #학교로 그룹화를 한 뒤에 국어, 영어, 수학 평균 데이터


df.groupby('학교')[['국어','영어','수학']].mean()

출력

- 3 -
[13] df['학년'] = [3, 3, 2, 1, 1, 3, 2, 2] # 학년 Column 추가
df

출력

[14]
df.groupby(['학교','학년']).mean() # 학교별, 학년별 평균 데이터

출력

[15]
df.groupby('학년').mean() # 학년별 평균 데이터

출력

- 4 -
[16]
df.groupby('학년').mean().sort_values('키')

출력

[17]
df.groupby('학년').mean().sort_values('키', ascending=False)

출력

[18]
df.groupby(['학교','학년']).sum()

출력

- 5 -
[19] # 학교로 그룹화를 한 뒤에 각 학교별 이름과 sw특기 데이터의 수를 가져옴
df.groupby('학교')[['이름','sw특기']].count()

출력

[20] # 학교로 그룹화를 한 뒤에 학년별 학생 수를 가져옴


school = df.groupby('학교')
school['학년'].value_counts()
학교 학년
능남고 2 2
3 1
출력 북산고 1 2
3 2
2 1
Name: 학년, dtype: int64

[21] # 학교로 그룹화를 한 뒤에 북산고에 대해서 학년별 학생 수를 가져옴


school['학년'].value_counts().loc['북산고']
학년
1 2
출력 3 2
2 1
Name: 학년, dtype: int64

[22] # 학교로 그룹화를 한 뒤에 능남고에 대해서 학년별 학생 수를 가져옴


school['학년'].value_counts().loc['능남고']
학년
2 2
출력
3 1
Name: 학년, dtype: int64

- 6 -
[23] # 학생들의 수 데이터를 퍼센트로 비교하여 가져옴
school['학년'].value_counts(normalize=True).loc['북산고']
학년
1 0.4
출력 3 0.4
2 0.2
Name: 학년, dtype: float64

- 7 -
19. seaborn으로 데이터 시각화하기
[1]
import seaborn as sns

seaborn에서 제공하는 데이터셋


[2]
import pandas as pd

[3]
sns.get_dataset_names()

['anagrams',
'anscombe',
'attention',
'brain_networks',
'car_crashes',
'diamonds',
'dots',
'exercise',
'flights',
출력 'fmri',
'gammas',
'geyser',
'iris',
'mpg',
'penguins',
'planets',
'taxis',
'tips',
'titanic']

- 1 -
음식점에서 지불한 팁 금액, 손님 정보 등을 확인할 수 있는 'tips' 데이터셋을 사용

• total_bill: 음식가격
• tip: 팁 금액
• sex: 성별
• smoker: 흡연여부
• day: 방문요일
• time: 방문시간
• size: 인원수

[4] df = sns.load_dataset('tips')
df.head()

출력

[5]
df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 244 entries, 0 to 243
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 total_bill 244 non-null float64
1 tip 244 non-null float64
출력
2 sex 244 non-null category
3 smoker 244 non-null category
4 day 244 non-null category
5 time 244 non-null category
6 size 244 non-null int64
dtypes: category(4), float64(2), int64(1)
memory usage: 7.4 KB

- 2 -
[6]
df.describe()

출력

[7]
df['sex'].unique()

['Female', 'Male']
출력
Categories (2, object): ['Male', 'Female']

[8]
df['sex'].value_counts()

Male 157
출력 Female 87
Name: sex, dtype: int64

- 3 -
산점도 (scatterplot)
산점도는 x축 변수와 y축 변수의 상관관계를 확인할 때 사용하는 그래프
비싼 음식을 먹은 사람들이 팁을 많이 지불했을까요? 음식가격과 팁의 상관관계 확인
[9]
sns.scatterplot(x=df['total_bill'], y=df['tip'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876ac25090>

출력

음식가격의 값이 커질 수록 팁의 가격도 증가하는 것을 확인할 수 있다. 즉, 음식가격


과 팁은 양의 상관관계에 있다.
성별에 따라 어떤 차이가 있는지 확인하기 위해 scatterplot의 hue 속성값을 지정
[10]
sns.scatterplot(x=df['total_bill'], y=df['tip'], hue=df['sex'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876ac0cb90>

출력

- 4 -
인원수에 따른 값의 분포도 함께 확인하기 위해 size 속성값을 지정
[11]
sns.scatterplot(x=df['total_bill'], y=df['tip'], hue=df['sex'], size=df['size'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a6b04d0>

출력

회귀선 (regplot)
개별 데이터 분포를 대표할 수 있는 하나의 선인 회귀선을 표시하는 그래프
[12]
sns.regplot(x=df['total_bill'], y=df['tip'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a5dbfd0>

출력

- 5 -
회귀선만 표시하고 싶은 경우, scatter 속성을 False로 지정
[13]
sns.regplot(x=df['total_bill'], y=df['tip'], scatter=False)

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a5f5e10>

출력

회귀선 주변에 연한 배경이 함께 표시되는 것을 확인할 수 있다. 이 배경은 회귀선의


신뢰구간을 나타내는데, 데이터 분포가 회귀선을 기준으로 얼마나 퍼져 있는지 확인하
는데 도움이 된다. 신뢰구간을 표시하지 않으려면 ci=None으로 설정한다.
[14]
sns.regplot(x=df['total_bill'], y=df['tip'], scatter=False, ci=None)

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a4c8390>

출력

회귀선은 데이터의 상관관계를 파악할 수 있을 뿐 아니라 데이터의 경향성을 확인하여


새로운 데이터가 들어왔을 때 결과를 예측하는 경우에도 도움이 된다. 예를 들어 새로
운 고객이 방문했을 때 총 지불한 음식가격이 30달러라면 약 4달러 정도의 팁을 지불
할 것이라는 것을 예측할 수 있다.

- 6 -
선 그래프 (lineplot)
선 그래프는 x축에 연도, 월, 일과 같은 시간을 사용한다면 시간에 따른 데이터 변화
추이를 쉽게 확인할 수 있다. 그렇기 때문에 선 그래프는 변수의 변화, 트렌드, 변화율
정보가 중요한 경우 사용한다.
[15] x = [1, 2, 3, 4, 5]
y = [10, 20, 25, 30, 42]
sns.lineplot(x=x, y=y)
<matplotlib.axes._subplots.AxesSubplot at 0x7f876a4a3650>

출력

[16]
sns.lineplot(x=df['size'], y=df['tip'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a42e950>

출력

- 7 -
이번에는 앞의 그래프와 다르게 연한 배경이 함께 그려져있다. 이번 예제는 x축에 해
당하는 y축의 값이 여러 개 존재하기 때문에 값의 분포를 나타내는 부분이 함께 표시
된다. size가 2인 경우는 대부분 tip의 값이 표시된 직선 값에 수렵되는 반면, size가 5
인 경우에는 값의 편차가 큰 것을 확인할 수 있다.

hue 옵션을 이용해서 색상을 달리하여 표시할 수 있다. 위에서 그린 인원수(size)에 따


른 팁(tip)의 선 그래프를 요일(day)에 따라 값을 나누어 표시해보자.
[17]
sns.lineplot(x=df['size'], y=df['tip'], hue=df['day'], ci=None)

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a3bd410>

출력

- 8 -
막대 그래프 (barplot, countplot)
막대 그래프(barplot, countplot)는 수치를 막대의 길이로 표현해 시각화하는 그래프
앞서 선 그래프에서 그렸던 동일한 변수를 사용하여 막대 그래프를 그려보자.
[18]
sns.barplot(x=df['size'], y=df['tip'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a3868d0>

출력

각 size에 따른 tip의 평균값을 막대 길이로 표시한다. 막대 그래프에는 중심선이 그려


지는데, 이 역시 신뢰구간을 의미한다. 중심선이 없는 막대 그래프를 그리기 위해서는
ci=None 옵션을 설정한다.
[19]
sns.barplot(x=df['size'], y=df['tip'], ci=None)

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a1ca610>

출력

- 9 -
seaborn에서는 barplot과 모양은 유사하지만, y축의 값을 x축 변수의 개수(count)를 표
시하는 countplot도 제공한다. countplot은 y축은 개수를 표시하기 때문에 x축 변수만
지정한다.
[20]
sns.countplot(x=df['day'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a1911d0>

출력

[21]
df['day'].value_counts()

Sat 87
Sun 76
출력 Thur 62
Fri 19
Name: day, dtype: int64

- 10 -
pointplot
pointplot은 막대 그래프에서 막대를 제외하고, 데이터의 평균값을 선으로 잇고 신뢰구
간을 함께 표시한 그래프
[22]
sns.pointplot(x=df['day'], y=df['tip'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876b9bed10>

출력

- 11 -
박스플롯(boxplot)
박스플롯(boxplot, 상자그림)는 막대 그래프와 유사하게 수치를 길이로 표현하지만, 사
분위수를 함께 시각화한다.

박스플롯은 사분위수와 IQR(1사분위수와 3사분위수의 간격)에 기반한 이상치를 확인할


수 있기 때문에 변수의 분포가 치우침이 있는지, 이상치가 어느 정도 포함되어 있는지
한눈에 확인할 수 있다.
[23]
sns.boxplot(x=df['size'], y=df['tip'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a4b12d0>

출력

막대 그래프에서 중앙성을 통해 신뢰구간을 확인할 수 있었지만, 박스플롯에서는 데이


터의 분포를 좀 더 확실하게 확인할 수 있다. 인원수(size)가 3일 때, 팁(tip)을 일반적인
금액보다 매우 큰 값(10달러)을 낸 사례도 확인할 수 있고, 인원수가 4일 때는 팁의 금
액 분포가 굉장히 다양하게 분포되어 있음도 확인할 수 있다.

- 12 -
바이올린플롯 (violinplot)
바이올린플롯은 박스플롯의 가장 큰 값과 작은 값을 모두 하나로 연결하여 하나의 도
형으로 표시한다. 그 모양의 가운데는 볼록하고 양 끝으로 갈수록 가늘어지는 형태를
띄어 바이올린 모양 같아서 바이올린플롯이라고 한다.
[24]
sns.violinplot(x=df['size'], y=df['tip'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f876a025e10>

출력

박스플롯과 바이올린플롯 모두 데이터의 분포를 확인할 수 있지만, 박스플롯은 데이터


분포의 중앙값을 확인하는데 효과적이고 바이올린플롯은 최대, 최소값을 확인하는데
효과적이다.

- 13 -
히스토그램 (histplot)
히스토그램(histplot)은 변수의 분포를 막대형 그래프를 사용하여 표시하는 방법이다.
히스토그램은 x축에 계급을, y축에 빈도(도수)를 나타낸 뒤, 각 계급의 크기를 가로의
길이로, 빈도(도수)를 세로의 길이로 하는 직사각형을 차례로 그려서 표현한다. 막대 그
래프와 다르게 히스토그램은 가로축과 세로축이 연속형 자료이다.
[25]
sns.histplot(data=df['total_bill'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f8769fc0250>

출력

[26]
sns.histplot(data=df['total_bill'], bins=5)

<matplotlib.axes._subplots.AxesSubplot at 0x7f8767eba650>

출력

- 14 -
[27]
sns.histplot(data=df['total_bill'], kde=True)

<matplotlib.axes._subplots.AxesSubplot at 0x7f8767e28a90>

출력

히스토그램은 연속형 변수의 분포를 확인할 때 사용하는 그래프로, 범주형(categorical)


데이터를 사용하여 그래프를 그릴 경우, 카운트플롯과 유사한 형태로 그려진다.
[28]
sns.histplot(data=df['day'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f8767d621d0>

출력

- 15 -
[29]
sns.countplot(x=df['day'])

<matplotlib.axes._subplots.AxesSubplot at 0x7f8767d45d50>

출력

히트맵 (heatmap)
히트맵(heatmap)은 여러 가지 변수를 한 번에 비교할 때 유용하게 사용하는 시각화 방
법으로, 2차원 격자 모양으로 나뉜 각각의 칸에 데이터의 값을 색상으로 표시한다.

히트맵을 그리기 위해서 필요한 데이터만 갖도록 변형된 데이터를 새로 생성해야 한


다. 히트맵에서 사용하는 데이터는 데이터프레임을 피봇팅하여 생성할 수 있다. 인원
수, 요일에 따른 평균 팁을 표시하도록 피봇 테이블을 생성해보자.

[30] #피봇 테이블은 평균을 기본 연산으로 수행함


pivot_df = df.pivot_table('tip', 'day', 'size')
pivot_df

출력

- 16 -
[31] #피봇 테이블의 값 연산을 변경하고 싶다면, aggfunc 속성을 지정하여 변경할 수 있다.
#최대값(max), 최소값(min), 합계(sum), 개수(count)
df.pivot_table('tip', 'day', 'size', aggfunc='count')

출력

[32]
sns.heatmap(pivot_df)

<matplotlib.axes._subplots.AxesSubplot at 0x7f8767c8a6d0>

출력

히트맵 우측에 색상표를 참고하여 해석할 수 있다. 색상이 밝아질수록 큰 값, 어두워질


수록 작은 값이다. 흰색으로 표시된 값은 결측치(NaN)이다. 결측치를 제외하고 size가
클수록, day가 Thur일 때 표시된 값(tip)이 큰 값을 갖는다는 것을 확인할 수 있다.

- 17 -
결측치를 0으로 변환하여 다시 히트맵을 확인해보자.
[33] pivot_df.fillna(0, inplace=True)
pivot_df

출력

[34]
sns.heatmap(pivot_df)

<matplotlib.axes._subplots.AxesSubplot at 0x7f87653c84d0>

출력

0이 추가되어 기존에 흰색으로 표시된 영역이 검정색으로 표시되었다.

- 18 -
히트맵은 색상을 기반으로 값의 분포와 경향성을 파악하지만, 구체적으로 값을 확인할
수도 있다. heatmap의 annot 속성을 True로 지정하면 값을 함께 표시할 수 있다.
[35]
sns.heatmap(pivot_df, annot=True)

<matplotlib.axes._subplots.AxesSubplot at 0x7f8765304a50>

출력

- 19 -
20. 붓꽃 데이터 분석
붓꽃의 품종을 구분할 수 있도록 하는 열 데이터는 무엇일까?

[1] import pandas as pd


import seaborn as sns

[2]
sns.get_dataset_names()

['anagrams',
'anscombe',
'attention',
'brain_networks',
'car_crashes',
'diamonds',
'dots',
'exercise',
'flights',
출력 'fmri',
'gammas',
'geyser',
'iris',
'mpg',
'penguins',
'planets',
'taxis',
'tips',
'titanic']

- 1 -
[3] df = sns.load_dataset('iris')
df

출력

sepal_length : 꽃받침의 길이
sepal_width : 꽃받침의 너비
petal_length : 꽃잎의 길이
petal_width : 꽃잎의 너비
species : 품종

[4]
df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sepal_length 150 non-null float64
출력
1 sepal_width 150 non-null float64
2 petal_length 150 non-null float64
3 petal_width 150 non-null float64
4 species 150 non-null object
dtypes: float64(4), object(1)
memory usage: 6.0+ KB

- 2 -
[5]
df.describe()

출력

결측데이터 확인
[6]
df.isnull().sum()

sepal_length 0
sepal_width 0
petal_length 0
출력
petal_width 0
species 0
dtype: int64

[7]
df.isnull().sum().sum()

출력 0

- 3 -
중복데이터 확인
[8]
df.duplicated()[140:150]

140 False
141 False
142 True
143 False
144 False
출력 145 False
146 False
147 False
148 False
149 False
dtype: bool

[9] # 1개의 행이 그 이전 행과 중복된 상태라는 것


df.duplicated().sum()

출력 1

실제 어느 행의 데이터가 중복인지 확인해 본다.


[10]
df.loc[df.duplicated(), :]

출력

142번째 행 데이터는 이전 행에 있는 다른 샘플과 데이터가 중복된다는 의미이다.


sepal_length 값이 5.8, petal_width 값이 1.9인 행을 추출해보자.

- 4 -
[11]
df.loc[(df['sepal_length']==5.8) & (df['petal_width']==1.9), :]

출력

중복 데이터 제거 (drop_duplicates() 함수)


[12] df = df.drop_duplicates()
df.loc[(df['sepal_length']==5.8) & (df['petal_width']==1.9), :]

출력

상관관계(correlation) 분석 (corr() 함수)


양의 비례관계로 관련성이 높다면 1에 가깝다.
음의 비례관계로 관련성이 높다면 -1에 가깝다.
0에 가까우면 서로 관련성이 없다.
[13]
df.corr()

출력

- 5 -
[14]
sns.heatmap(df.corr(), annot=True)
<matplotlib.axes._subplots.AxesSubplot at 0x7f117e04dbd0>

출력

품종의 분포 확인
[15]
df['species'].value_counts()

setosa 50
versicolor 50
출력
virginica 49
Name: species, dtype: int64

[16]
sns.histplot(x=df['sepal_length'], kde=True)
<matplotlib.axes._subplots.AxesSubplot at 0x7f117e0481d0>

출력

- 6 -
[17]
sns.histplot(x=df['sepal_width'], kde=True)

<matplotlib.axes._subplots.AxesSubplot at 0x7f117b111310>

출력

[18]
sns.histplot(x=df['petal_length'], kde=True)
<matplotlib.axes._subplots.AxesSubplot at 0x7f1179043950>

출력

- 7 -
[19]
sns.histplot(x=df['petal_width'], kde=True)
<matplotlib.axes._subplots.AxesSubplot at 0x7f1178f20390>

출력

품종별 sepal_length 값의 분포 밀도만 나타내기


[20]
sns.displot(x=df['sepal_length'])

<seaborn.axisgrid.FacetGrid at 0x7f1178f0c7d0>

출력

- 8 -
[21]
sns.displot(x=df['sepal_length'], hue=df['species'])

<seaborn.axisgrid.FacetGrid at 0x7f1178e26990>

출력

[22] # kind='hist' 또는 kind='kde'


sns.displot(x=df['sepal_length'], hue=df['species'], kind='kde')
<seaborn.axisgrid.FacetGrid at 0x7f1178cbc9d0>

출력

- 9 -
나머지 3개 열 데이터는 한번에 그래프로 출력

[23] for col in ['sepal_width', 'petal_length', 'petal_width']:


sns.displot(x=df[col], hue=df['species'], kind='kde')

출력

- 10 -
출력

pairplot() 을 이용하면 열 데이터간 관계를 나타내는 그래프를 한번에 그릴 수 있다.

- 11 -
[24]
sns.pairplot(df, hue='species', diag_kind='kde')

<seaborn.axisgrid.PairGrid at 0x7f59abdc2c90>

출력

- 12 -
21. 타이타닉 데이터 분석
타이타닉 승객의 데이터로 다양한 생존율 분포를 확인해보자.

[1] # 설치 후 반드시 [런타임 다시 시작] 메뉴를 실행해주어야 함


!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
# 설치 메시지 일부 생략
Processing triggers for fontconfig (2.12.6-0ubuntu2) ...
출력
/root/.fontconfig: not cleaning non-existent cache directory
fc-cache: succeeded

데이터 확인하기
[2] import seaborn as sns
df_titanic = sns.load_dataset('titanic')
df_titanic.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 15 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 class 891 non-null category
9 who 891 non-null object
10 adult_male 891 non-null bool
11 deck 203 non-null category
12 embark_town 889 non-null object
13 alive 891 non-null object
14 alone 891 non-null bool
dtypes: bool(2), category(2), float64(2), int64(4), object(5)
memory usage: 80.7+ KB

- 1 -
[3]
df_titanic.head()

출력

[4] column_t = ['생존여부', '선실등급', '성별', '연령', '형제및배우자수',


'부모및자녀수', '요금', '승선항코드', '선실등급명',
'남녀어린이구분', '성인남성여부', '데크번호', '승선항',
'생존여부(y/n)', '독신여부']

df_titanic.columns = column_t

[5]
df_titanic.head()

출력

- 2 -
[6]
df_titanic.head()

출력

[7]
df_titanic.describe(include='all')

출력

- 3 -
결측치 확인하기
[8]
df_titanic.isnull().sum()

생존여부 0
선실등급 0
성별 0
연령 177
형제및배우자수 0
부모및자녀수 0
요금 0
승선항코드 2
출력
선실등급명 0
남녀어린이구분 0
성인남성여부 0
데크번호 688
승선항 2
생존여부(y/n) 0
독신여부 0
dtype: int64

[9]
df_titanic.isnull().sum().sum()

출력 869

[10] import matplotlib


matplotlib.rcParams['font.family'] = 'NanumBarunGothic'
matplotlib.rcParams['font.size'] = 15 # 글자크기
# 한글 폰트 사용시, 마이너스 글자가 깨지는 현상을 해결
matplotlib.rcParams['axes.unicode_minus'] = False

- 4 -
[11] import missingno as msno
msno.bar(df_titanic, figsize=(15, 5), color=(0.7, 0.2, 0.2))

출력

[12]
msno.matrix(df_titanic, figsize=(15, 5), color=(0.7, 0.2, 0.2))

출력

- 5 -
상관관계분석
[13]
df_titanic.corr()

출력

[14] import matplotlib.pyplot as plt


plt.figure(figsize=(8, 8))
sns.heatmap(df_titanic.corr(), annot=True)

출력

- 6 -
목표 열인 '생존여부'와 상관계수가 높은 열은 '선실등급', '요금', '성인남성여부'이다. '
선실등급'과 '요금' 열의 상관계수는 -0.55이므로 매우 강한 음의 상관관계가 있다. 이
를 통해 객실등급에 따라 객실요금이 달라지는 것을 확인할 수 있다.

생존여부 (survived)

1 : 생존자
0 : 사망자

[15]
df_titanic['생존여부'].value_counts()

0 549
출력 1 342
Name: 생존여부, dtype: int64

[16]
sns.countplot(df_titanic['생존여부'])

출력

- 7 -
선실등급 (pclass)
[17]
sns.countplot(df_titanic['선실등급'])

출력

[18]
sns.countplot(df_titanic['선실등급'], hue=df_titanic['생존여부'])

출력

- 8 -
이번에는 barplot을 이용해 등급별 객실요금의 평균값을 본포를 알아보자. 생존자 비율
이 높은 1등석, 2등석을 보면 생존자들이 지불한 객실요금이 높은 패턴을 보인다.

[19]
sns.barplot(x=df_titanic['선실등급'], y=df_titanic['요금'], hue=df_titanic['생존여부'])

출력

성별 (sex)
[20]
df_titanic['성별'].value_counts()

male 577
출력 female 314
Name: 성별, dtype: int64

- 9 -
[21]
sns.histplot(x=df_titanic['성별'], hue=df_titanic['생존여부'], multiple='dodge')

출력

남성의 생존율이 낮고 여성의 생존율이 상대적으로 높다.

multiple 속성에 stack을 설정하면 막대 그래프를 상하 방향으로 누적하여 나타낸다.

[22]
sns.histplot(x=df_titanic['성별'], hue=df_titanic['생존여부'], multiple='stack')

출력

- 10 -
multiple 속성에 fill을 설정하면 hue 속성의 상대적 비율을 백분율로 나타낸다.

[23]
sns.histplot(x=df_titanic['성별'], hue=df_titanic['생존여부'], multiple='fill')

출력

연령 (age)
[24]
df_titanic.loc[(df_titanic['연령'].isnull()) & (df_titanic['선실등급']==3), ['선실등급', '연령']]

출력

- 11 -
[25]
df_titanic.loc[(df_titanic['연령'].isnull()) & (df_titanic['선실등급']==2), ['선실등급', '연령']]

출력

[26]
df_titanic.loc[(df_titanic['연령'].isnull()) & (df_titanic['선실등급']==1), ['선실등급', '연령']]

출력

- 12 -
[27]
df_titanic.groupby('선실등급')['연령'].mean()

선실등급
1 38.233441
출력 2 29.877630
3 25.140620
Name: 연령, dtype: float64

[28]
df_titanic['연령'] = df_titanic.groupby('선실등급')['연령'].apply(lambda x: x.fillna(round(x.mean(),0)))

[29]
df_titanic.iloc[19, [1, 3]]

선실등급 3
출력 연령 25.0
Name: 19, dtype: object

[30]
df_titanic.iloc[181, [1, 3]]

선실등급 2
출력 연령 30.0
Name: 181, dtype: object

[31]
df_titanic.iloc[839, [1, 3]]

선실등급 1
출력 연령 38.0
Name: 839, dtype: object

- 13 -
형제및배우자수 (sibsp)
동승한 형제, 자매, 배우자수를 의미한다. boxplot으로 생존여부를 표시하면 동승자가
2 ~ 3명일 경우 생존여부에 차이가 있음을 알 수 있다.
[32]
sns.boxplot(x=df_titanic['형제및배우자수'], y=df_titanic['연령'], hue=df_titanic['생존여부'])

출력

- 14 -
부모및자녀수 (parch)
함께 탑승한 부모 및 자녀수를 의미한다. boxplot으로 생존여부와 함께 나이 분포를
그려보면, 동승자가 4명 이상일 경우, 생존자가 거의 없다는 것을 알 수 있다.
[33]
sns.boxplot(x=df_titanic['부모및자녀수'], y=df_titanic['연령'], hue=df_titanic['생존여부'])

출력

형제및배우자수와 부모및자녀수를 합하여 가족수를 열을 추가한다. 가족수와 객실등급


을 기준으로 생존율의 차이를 확인해보자. 가족수와 객실 등급에 따라 생존율에 차이
가 있음을 알 수 있다.

- 15 -
[34] # 승선 대표자를 고려해서 +1 을 해준다.
df_titanic['가족수'] = df_titanic['형제및배우자수'] + df_titanic['부모및자녀수'] + 1
df_titanic.head()

출력

[35]
sns.barplot(x=df_titanic['가족수'], y=df_titanic['생존여부'], hue=df_titanic['선실등급'])

출력

- 16 -
요금 (fare)
요금 열은 연속적인 값을 갖는다. displot의 kind 옵션을 kde로 설정하고 밀도함수 그
래프를 그려보자. 왼쪽으로 치우친 비대칭 구조를 보인다.
[36]
sns.displot(x=df_titanic['요금'], kind='kde', hue=df_titanic['생존여부'])

출력

비대칭 분포로 나타나서 요금이 높은 부분은 잘 파악이 안되고 있다. 비대칭 분포를
정규화하기 위해 로그 변환을 수행한다. 넘파이의 log1p 함수를 이용하여 '요금' 열에
로그를 취하면 분포 그래프가 아래와 같이 변하는 것을 확인할 수 있다.

- 17 -
[37] import numpy as np
df_titanic['요금로그'] = np.log1p(df_titanic['요금'])
sns.displot(x=df_titanic['요금로그'], kind='kde', hue=df_titanic['생존여부'])

출력

[38]
sns.stripplot(x=df_titanic['선실등급'], y=df_titanic['요금'], hue=df_titanic['생존여부'])

출력

- 18 -
[39]
sns.stripplot(x=df_titanic['선실등급'], y=df_titanic['요금로그'], hue=df_titanic['생존여부'])

출력

승선항코드 (embarked)
탑승항구를 나타내는 승선항코드 열은 결측값이 2개로 확인된다.
[40]
df_titanic.loc[df_titanic['승선항코드'].isnull(), :]

출력

탑승 장소를 확인할 수 있는 방법이 없기 때문에 가장 탑승자가 많은 항구 값으로 결


측값을 채운다.
[41]
df_titanic['승선항코드'].value_counts()

S 644
C 168
출력
Q 77
Name: 승선항코드, dtype: int64

- 19 -
[42]
df_titanic['승선항코드'].mode()

0 S
출력
dtype: object

[43]
df_titanic['승선항코드'].mode()[0]

출력 ‘S’

[44] df_titanic['승선항코드'].fillna(df_titanic['승선항코드'].mode()[0], inplace=True)


#df_titanic['승선항코드'] = df_titanic['승선항코드'].fillna(df_titanic['승선항코드'].mode()[0])

[45]
df_titanic['승선항코드'].value_counts()

S 646
C 168
출력
Q 77
Name: 승선항코드, dtype: int64

- 20 -
barplot으로 탑승장소에 따른 생존율을 확인해보자.
[46]
sns.barplot(df_titanic['승선항코드'], y=df_titanic['생존여부'])

출력

- 21 -
22. 출생아수 분석
[1] # 설치 후 반드시 [런타임 다시 시작] 메뉴를 실행해주어야 함
!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
# 설치 메시지 일부 생략
Processing triggers for fontconfig (2.12.6-0ubuntu2) ...
출력
/root/.fontconfig: not cleaning non-existent cache directory
fc-cache: succeeded

[2] # 구글 드라이브 마운트


from google.colab import drive
drive.mount('/gdrive')

출력 Mounted at /gdrive

[3]
drive_path = '/gdrive/My Drive/Colab/'

[4]
import pandas as pd

[5] df_kosis = pd.read_csv(drive_path + '출생아수_시도_시_군_구__20220312140740.csv', encoding='utf-8')


df_kosis.shape

출력 (19, 865)

- 1 -
[6]
pd.options.display.max_columns = 865

[7]
df_kosis.head()

출력

[8] df = df_kosis.melt(id_vars='시군구별')
df.head()

출력

- 2 -
[9]
df['시군구별'].unique()

array(['시군구별', '전국', '서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시',


출력 '대전광역시', '울산광역시', '세종특별자치시', '경기도', '강원도', '충청북도', '충청남도',
'전라북도', '전라남도', '경상북도', '경상남도', '제주특별자치도'], dtype=object)

[10] print(df.shape)
df = df[df['시군구별'] != '시군구별'].copy()
print(df.shape)
(16416, 3)
출력
(15552, 3)

[11]
df['시군구별'].unique()

array(['전국', '서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시', '대전광역시',


출력 '울산광역시', '세종특별자치시', '경기도', '강원도', '충청북도', '충청남도', '전라북도',
'전라남도', '경상북도', '경상남도', '제주특별자치도'], dtype=object)

[12]
df.head()

출력

- 3 -
[13] df['연도'] = df['variable'].str.split('.', expand=True)[0]
df['월'] = df['variable'].str.split('.', expand=True)[1]
df['성별'] = df['variable'].str.split('.', expand=True)[2]
df.head()

출력

[14]
df.tail()

출력

[15]
df['성별'].unique()

출력 array([None, '1', '2'], dtype=object)

- 4 -
[16]
df['성별'].nunique()

출력 2

[17] df['성별'] = df['성별'].fillna('전체')


df['성별'].unique()

출력 array(['전체', '1', '2'], dtype=object)

[18] df['성별'] = df['성별'].replace('1', '남자').replace('2', '여자')


df['성별'].unique()

출력 array(['전체', '남자', '여자'], dtype=object)

[19]
df['성별'].value_counts()

전체 5184
남자 5184
출력
여자 5184
Name: 성별, dtype: int64

[20]
df.head()

출력

- 5 -
[21] df = df.rename(columns={'variable':'기간', 'value':'출생아수'})
df.head()

출력

[22]
df.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 15552 entries, 1 to 16415
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 시군구별 15552 non-null object
출력 1 기간 15552 non-null object
2 출생아수 15552 non-null object
3 연도 15552 non-null object
4 월 15552 non-null object
5 성별 15552 non-null object
dtypes: object(6)
memory usage: 850.5+ KB

- 6 -
[23] import numpy as np
df['출생아수'] = df['출생아수'].replace('-', np.nan)
df['출생아수'] = df['출생아수'].astype(float)
df['출생아수'].describe()
count 15012.000000
mean 3012.725286
std 6587.701782
min 30.000000
출력 25% 621.000000
50% 1025.000000
75% 1908.250000
max 63268.000000
Name: 출생아수, dtype: float64

[24] df_all = df[(df['시군구별'] == '전국') & (df['성별'] == '전체')]


df_all.head(2)

출력

[25] df_all = df_all[['연도', '월', '출생아수']].copy()


df_all.head()

출력

- 7 -
[26] import seaborn as sns
import matplotlib.pyplot as plt
sns.set(font='NanumBarunGothic')

[27]
df_all.set_index(['연도', '월']).plot(figsize=(15,4))

<matplotlib.axes._subplots.AxesSubplot at 0x7f265bc67750>

출력

[28]
df_all[-48:].set_index(['연도', '월']).plot.bar(figsize=(15,4))

<matplotlib.axes._subplots.AxesSubplot at 0x7f265ab3c790>

출력

- 8 -
[29] plt.figure(figsize=(15,4))
sns.lineplot(data=df_all, x='연도', y='출생아수', ci=None)
<matplotlib.axes._subplots.AxesSubplot at 0x7f265b3919d0>

출력

[30] plt.figure(figsize=(15,4))
sns.lineplot(data=df_all, x='연도', y='출생아수', ci=None, hue='월')
<matplotlib.axes._subplots.AxesSubplot at 0x7f265a08cb50>

출력

[31] plt.figure(figsize=(15,4))
sns.barplot(data=df_all, x='연도', y='출생아수', ci=None)
<matplotlib.axes._subplots.AxesSubplot at 0x7f265ad86e90>

출력

- 9 -
[32] plt.figure(figsize=(15,4))
sns.barplot(data=df_all, x='연도', y='출생아수', ci=None, hue='월')
<matplotlib.axes._subplots.AxesSubplot at 0x7f2659fafcd0>

출력

[33] df_local = df[df['시군구별'] != '전국'].copy()


df_local.head()

출력

- 10 -
[34] plt.figure(figsize=(15,4))
sns.pointplot(data=df_local, x='연도', y='출생아수', hue='성별')
<matplotlib.axes._subplots.AxesSubplot at 0x7f2659a04d50>

출력

[35] df_local_all = df_local[df_local['성별'] == '전체']


df_local_all.head()

출력

[36] plt.figure(figsize=(15,4))
sns.pointplot(data=df_local_all, x='연도', y='출생아수')
<matplotlib.axes._subplots.AxesSubplot at 0x7f26595fa5d0>

출력

- 11 -
[37] plt.figure(figsize=(15,4))
sns.pointplot(data=df_local_all, x='연도', y='출생아수', hue='시군구별', ci=None)
plt.legend(loc='center right', bbox_to_anchor=(1.15, 0.5), ncol=1)
<matplotlib.legend.Legend at 0x7f26586928d0>

출력

[38] df_local_2 = df_local_all[df_local_all['시군구별'].isin(['서울특별시', '경기도', '세종특별자치시'])]


df_local_2.head()

출력

- 12 -
[39] plt.figure(figsize=(15,4))
sns.pointplot(data=df_local_2, x='연도', y='출생아수', ci=None, hue='시군구별')
<matplotlib.axes._subplots.AxesSubplot at 0x7f26596a29d0>

출력

[40] df_sj = df[(df['시군구별'] == '세종특별자치시') & ((df['성별'] == '전체'))].dropna(how='any')


df_sj.head()

출력

[41] plt.figure(figsize=(15,4))
sns.pointplot(data=df_sj, x='연도', y='출생아수', ci=None)
<matplotlib.axes._subplots.AxesSubplot at 0x7f2658274e50>

출력

- 13 -
[42] import numpy as np
plt.figure(figsize=(15,4))
sns.pointplot(data=df_sj, x='연도', y='출생아수', ci=None, estimator=np.sum)
<matplotlib.axes._subplots.AxesSubplot at 0x7f2657fe3190>

출력

- 14 -

You might also like