촉촉한초코칩
파이썬으로 시작하는 데이터 사이언스 - 4강 본문
1. 라이브러리 로드하고 한글폰트 설정하기
라이브러리 로드
import pandas as pd #데이터 분석용 라이브러리
import numpy as np #수치 계산 라이브러리
import seaborn as sns #matplotlib을 사용하기 쉽게 만든 시각화 라이브러리
import matplotlib.pyplot as plt #그래프 폰트, 스타일, 사이즈 변경, 서브 플롯 사용 라이브러리
%matplotlib inline #구버전 노트북에서는 이 설정을 해줘야 노트북 상에서 그래프가 표시된다.
한글폰트 설정
#jupyter notebook
import os
if os.name == 'poxis':
plt.rc("font, family="AppleGothic")
else
plt.rc("font, family="Malgun Gothic")
plt.rc("axes", unicode_minus=False) #마이너스 폰트가 깨지는 문제를 대처하기 위해 작성
!pip install koreanize-matplotlib
import koreanize_matplotlib
%config inlineBackend.figure_format='retina'
2. 데이터셋 소개와 로드하기 - 가설세우기
- 공공데이터포털에서 건강검진정보를 다운받는다.
- pd.read_까지 입력하여 tab 키를 누르면 불러올 수 있는 다양한 형태의 데이터를 확인할 수 있다.
- shift+tab을 하면 라이브러리 옵션을 볼 수 있다.
- ?을 사용하면 더 자세한 설명을 볼 수 있다.
pd.read_csv("파일명", encoding="cp949")
#데이터 크기 확인하기
df.shape
#데이터 미리보기
df.head()
df.tail() #뒤에서 가져오기
#1개의 데이터만 예시로 가져오기
df.sample()
#기본 정보 보기 - 행/열개수, 결측치 등
df.info()
#column 이름만 보기
df.columns
#데이터 타입 출력
df.dtypes
3. 로드한 데이터의 결측치를 보고 요약, 집계하기 - info, isnull, value_counts
#결측치 보기 - 결측치를 bool 값으로 표시하고 sum()으로 결측치의 수를 세어준다.
df.isnull()
df.isna().sum() #isna()로도 결측치 수를 집계할 수 있다.
#판다스에 내장 된 plot을 통해 시각화한다.
#barh로 글씨를 y축에 두고, figsize로 사이즈를 조절한다.
df.isnull().sum().plot.barh(figsize=(10,9))
#일부 데이터 요약하기
#1개의 열을 가져오면 series 형태의 데이터 구조로 결과가 나타난다.
df["(혈청치오티)ALT"]
#2개 이상을 가져올 때는 리스트로 감싸준다.
#2개의 열을 가져오면 dataframe 형태의 데이터 구조로 결과가 나타난다.
df[["(혈청지오티)ALT","(혈청지오티)AST"]]
#5개의 행을 series 형태로 불러온다.
df["(혈청지오티)ALT"].head()
#5개의 행을 dataframe 형태로 불러온다.
df["(혈청지오티)ALT", "(혈청지오티)AST"]].head()
#수치 데이터 요약보기
#결측치를 제외한 count, mean(평균), std(표준편차), min, max, 50%, 25%, 75%
df["(혈청지오티)ALT", "(혈청지오티)AST"]].describe()
#값 집계하기
#value_counts()로 카테고리나 text 형태 데이터의 빈도수를 체크한다.
df["성별코드"].value_counts()
4. groupBy와 pivot_table로 다양한 집계 연산 하기
2개 이상의 데이터를 보기 위해서는 groupby와 pivot_table을 사용한다.
groupby
#groupby
#성별코드 값에 따라 모든 열에 대한 평균을 구한다.
df.groupby(["성별코드"]).mean()
df.groupby(["성별코드"]).count()
#남성, 여성이 얼마나 되는지 알아본다.
#여러 개의 column, 값들을 알아볼 수 있다.
df.groupby(["성별코드"])["가입자일련번호"].count()
#성별코드에 따라 음주 상태를 알아본다.
df.groupby(["성별코드", "음주여부"])["가입자일련번호"].count()
df.groupby(["성별코드", "음주여부"])["감마지티피"].mean()
df.groupby(["성별코드", 음주여부"])["감마지티피"].agg(["count","mean","median"])
pivot_table
#pivot은 연산을 하지 않고 데이터의 구조를 바꾸고자 할 때 사용한다.
df.pivot
#나머지 수치 데이터를 불러온다.
#기본적으로 dataframe 형태로 결과가 출력된다.
df.pivot_table(index="성별코드", values="가입자일련번호", aggfunc="count")
df.pivot_table(index="음주여부", values="가입자일련번호", aggfunc="count")
pd.pivot_table(df, index="음주여부", values="감마지티피")
pd.pivot_table(df, index="음주여부", values="감마지티피", aggfunc=["mean", "median"])
pd.pivot_table(df, index=["음주여부", "성별코드"], values="감마지티피", aggfunc="describe")
감마지피티 데이터를 성별코드와 음주여부를 기준으로 불러온다.
5. 히스토그램으로 전체 수치 데이터를 한번에 시각화 하기
100만개가 넘는 데이터를 시각화할 때는 속도가 느리기 때문에 groupby 또는 pivot_table로 연산하는 것이 좋다.
히스토그램
#df.hist()를 변수에 넣으면 출력값 없이 바로 시각화를 출력해준다.
h = df.hist(figsize=(12,12))
#iloc[]를 통해 몇 번째에 있는 특정한 행, 열을 사용할 것인지 지정할 수 있다.
#슬라이싱하면 속도가 빨라진다.
#0부터 11번째 행까지 그려본다.
h = df.iloc[;, ;12].hist(figsize=(12,12))
#12~23번째 행
h = df.iloc[:, 12:24].hist(figsize(12,12))
#bins 옵션으로 막대의 개수를 잘게 그린다.
h = df.iloc[:, 12:24].hist(figsize(12,12), bins=100)
#히스토그램은 연속된 데이터를 카테고리형으로 만든다.
h = df.iloc[:, 24:].hist(figsize(12,12), bins=100)
6. 데이터의 빈도수 시각화 하기(막대그래프1) - countplot
- seaborn은 matplotlib을 쉽게 쓸 수 있는 highlevel interface고, 통계 지식 없이 고급 통계 그래프를 구현할 수 있다.
- 범주형 데이터, 수치형 데이터에 따라 시각화에 접근하는 방식이 달라진다.
#random_state=1을 사용하면 1,000,000개 중 랜덤으로 정해준 개수만큼 가져온다.
df.sample(1000, random_state=1)
countplot
df["음주여부"].value_counts().plot.bar()
#sns.countplot()은 x, y, data를 지정한다.
sns.countplot(x="음주여부", data=df)
#hue : 성별코드로 색상을 구분하여 그려본다.
sns.countplot(x="음주여부", data=df, hue="성별코드")
sns.set(font_scale=1.5, font="AppleGothic")
#특정 범위로 연속형 데이터를 묶으면 범주형 데이터로 볼 수 있다.
sns.countplot(data=df, x="연령대코드(5세단위)", hue="음주여부")
#레이블 값이 잘 안 보인다면 plt.figure으로 크기를 조절 할 수 있다.
plt.figure(figsize=(15,4))
sns.countplot(data=df, x="신장(5cm단위)")
#성별코드에 따라서 신장을 알 수 있다.
plt.figure(figsize=(15,4))
sns.countplot(data=df, x="체중(5kg단위)", hue="성별코드")
7. 수치형 vs 범주형 데이터의 시각화(막대그래프2) - barplot
sns.barplot(data=df, x="연령대코드(5세단위)", y="총콜레스테롤")
#속도가 오래 걸리므로 sample을 먼저 그려본다.
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="총콜레스테롤", hue="음주여부")
plt.figure(figsize=(15,4))
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="총콜레스테롤", hue="흡연상태")
#신뢰구간 (ci)
#95%의 신로구간을 지정한다.
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="트리글리세라이드", hue="음주여부", ci=95)
#신뢰구간을 표준편차로 지정한다.
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="트리글리세라이드", hue="음주여부", ci=sd)
# > 음주를 하는 사람이 트리글리세라이드(중성지방수치)가 높은 경향이 있다.
#신뢰구간을 표시하고 싶지 않다면 None을 설정한다.
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5kg 단위)", hue="성별코드", ci=None)
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5kg 단위)", hue="음주여부", ci=None)
8. 수치형 vs 범주형 데이터 선그래프로 그리기 - lineplot, pointplot
- barplot : 막대로 개별값을 표현한다.
- lineplot, pointplot : 선으로 기울기까지 표현할 수 있다.
가격, 매출/제고 데이터는 대체로 lineplot, pointplot으로 그리는 것이 좋다.
#lineplot
plt.figure(figsize=(15,4))
#y축은 평균값이다.
#lineplot은 편차와 신뢰구간을 그림자로 표현한다. 그래프 뒤쪽에 그림자가 없는 이유는 모수가 적어서 편차를 그릴 게 없기 떄문이다.
sns.lineplot(data=df, x="연령대코드(5세단위)", y="체중(5kg 단위)", hue="성별코드")
plt.figure(figsize=(15,4))
sns.lineplot(data=df, x="연령대코드(5세단위)", y="신장(5cm 단위)", hue="성별코드", ci="sd")
plt.figure(figsize=(15,4))
sns.lineplot(data=df, x="연령대코드(5세단위)", y="신장(5cm 단위)", hue="음주여부", ci="sd")
#pointplot : 막대를 통해 편차와 신뢰구간을 표현한다.
plt.figure(figsize=(15,4))
sns.pointplot(data=df, x="연령대코드(5세단위)", y="신장(5cm 단위)", hue="음주여부", ci="sd")
plt.figure(figsize=(15,4))
sns.lineplot(data=df, x="연령대코드(5세단위)", y="신장(5cm 단위)", hue="음주여부", ci="sd")
sns.pointplot(data=df, x="연령대코드(5세단위)", y="신장(5cm 단위)", hue="음주여부", ci="sd")
plt.figure(figsize=(15,4))
sns.pointplot(data=df, x="연령대코드(5세단위)", y="신장(5cm 단위)", hue="성별코드", ci="sd")
plt.figure(figsize=(15,4))
sns.pointplot(data=df, x="연령대코드(5세단위)", y="혈색소", ci=None)
sns.pointplot(data=df, x="연령대코드(5세단위)", y="혈색소", hue="음주여부", ci=None)
9. 데이터를 좀 더 자세히 표현하기 - boxplot, violinplot 그리기
https://pandas.pydata.org/pandas-docs/stable/user_guide/visualization.html
boxplot
- 박스와 수염이 있는 모양이어서 box and whisker plot으로 불린다.
- 특정 column 값들을 boxplot으로 그릴 수 있다.
- 박스의 밑은 1사분위수, 중간은 2사분위수, 위는 3사분위수이다.
plt.figure(figsize=(15,4))
sns.boxplot(data=df, x="신장(5cm 단위)", y="체중(5kg 단위)")
plt.figure(figsize=(15, 4))
sns.boxplot(data=df, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="성별코드")
#사분위수 범위(IQR)은 3사분위수 - 1사분위수이다.
#3사분위수보다 1.5 x IQR 이상을 초과하는 값과 Q1보다 1.5 x IQR 이상 미달하는 값은 이상치이다.
#점, 원, 별표 모양으로 표현합니다.
plt.figure(figsize=(15, 4))
sns.boxplot(data=df, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부")
violinplot
- boxpot의 단점을 보완하여 더 자세하게 보여주는 그래프이다.
plt.figure(figsize=(15, 4))
sns.violinplot(data=df, x="신장(5Cm단위)", y="체중(5Kg 단위)")
plt.figure(figsize=(15, 4))
sns.violinplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부")
#split 옵션을 사용하면 두 개의 데이터를 붙여서 볼 수 있다.
plt.figure(figsize=(15, 4))
sns.violinplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부", split=True)
plt.figure(figsize=(15, 4))
sns.violinplot(data=df_sample, x="연령대코드(5세단위)", y="혈색소", hue="음주여부", split=True)
# > x축의 16에서 보면 음주하는 사람들의 값이 확연히 높고, 전체적으로 더 위에 분포하는 것을 볼 수 있다.
swarm plot
#산점도를 통해 데이터를 찍어볼 수 있다.
plt.figure(figsize=(15, 4))
sns.swarmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부")
plt.figure(figsize=(15, 4))
sns.swarmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부")
sns.violinplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)")
plt.figure(figsize=(15, 4))
sns.swarmplot(data=df_sample, x="연령대코드(5세단위)", y="혈색소", hue="음주여부")
implot
- scatterplot과는 다르게 회귀선을 확인해볼 수 있다.
sns.lmplot(data=df_sample, x="연령대코드(5세단위)", y="혈색소", hue="음주여부")
#col이라는 옵션으로 색상을 다르게 하여 데이터를 분류해볼 수 있다.
sns.lmplot(data=df_sample, x="연령대코드(5세단위)", y="혈색소", hue="음주여부", col="성별코드")
- 값들이 겹쳐서 보이는데 분포를 보고 싶다면 swarmplot을 사용하는 게 좋다. 회귀선을 그리거나 다변수 시각화를 할 때 좋다.
- x축에도 수치형 데이터를 넣어도 되지만 막대가 너무 많으면 보기에 불편합니다. barplot을 기울기로 보고 싶다면 lineplot이 좋다.
- boxplot을 그리면 이상치를 확인하기 좋습니다. violinplot은 분포를 더 자세히 볼 수 있다.
10. 산점도(산포도)와 회귀선 상관관계 보기 - scatterplot, lmplot
scatterplot
- tab 키를 활용해서 자동완성을 활용할 수 있다.
- option을 보면 다른 그래프와 사용 방법이 비슷하다.
- 수치형 데이터, 그래프의 이상치를 파악할 때 사용하기 좋다.
sns.scatterplot(data=df, x="(혈청지오티)AST", y="(혈청지오티)ALT")
sns.scatterplot(data=df_sample, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="음주여부")
#연속형 데이터도 넣을 수 있다.
sns.scatterplot(data=df_sample, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="허리둘레")
#size 옵션을 사용해서 체중에 따라 크기를 다르게 지정할 수 있다.
plt.figure(figsize=(8, 7))
sns.scatterplot(data=df_sample, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="음주여부", size="체중(5Kg 단위)")
implot
- 상관관계를 더 잘 파악할 수 있다.
- 그리드처럼 격자로 나온다. categorical 데이터로 인식하기 때문이다.
- 여러 카테고리 값에 따라 subplot을 그릴 수 있다.
sns.lmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부")
#왼쪽 아래에서 오른쪽 위로 선이 그려지면 양의 상관관계가 있다고 표현한다.
sns.lmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="성별코드", col="음주여부")
sns.lmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부", col="성별코드")
sns.lmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="흡연여부", col="음주여부")
sns.lmplot(data=df_sample, x="수축기혈압", y="이완기혈압", hue="음주여부")
sns.lmplot(data=df_sample, x="(혈청지오티)AST", y="(혈청지오티)ALT")
sns.lmplot(data=df_sample, x="(혈청지오티)AST", y="음주여부")
#robust 옵션을 활용하면 이상치를 빼고 그린다.
#seaborn의 장점은 값만 넣어주면 그래프를 자동으로 그려준다.
#이상치가 있으면 회귀선이 영향을 많이 받으므로 robust 옵션을 사용해주는 것이 좋다.
sns.lmplot(data=df_sample, x="(혈청지오티)AST", y="음주여부", robust=True)
이상치 다루기
#범위를 지정하여 데이터셋을 만들어준다.
df_ASLT = df_sample[(df_sample["(혈청지오티)AST"] < 400) & (df_sample["(혈청지오티)ALT"] < 400)]
#범위를 지정하여 변수로 만들어주면 그래프를 그리는 데에 시간이 더 짧게 걸린다.
sns.lmplot(data=df_ASLT, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="음주여부", ci=None)
df_ASLT_high = df_sample[(df["(혈청지오티)AST"] > 400) | (df["(혈청지오티)ALT"] > 400)]
sns.lmplot(data=df_ASLT_high, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="음주여부", ci=None)
#특정 칼럼들에 따라 이상치를 따로 확인해볼 수 있다.
df_ASLT_high_8000 = df_ASLT_high[df_ASLT_high["(혈청지오티)AST"] > 8000]
df_ASLT_high_8000.iloc[:, 10:27]
11. 수치형 데이터의 분포를 표현하기 - distplot
scatterplot : x, y가 모두 수치형 데이터일 때 그릴 수 있다.
distplot
- 히스토그램(도수분포표에 따라 그림을 그리는 것)을 그려준다.
- 계급에 따라 데이터의 개수를 세어준다.
- 결측치가 있으면 그릴 수 없다.
df_chol = df.loc[df["총콜레스테롤"].notnull(), "총콜레스테롤"]
df_chol.head()
#총콜레스테롤을 부드러운 곡선과 막대로 표현할 수 있다.
#히스토그램은 막대를 나타내고, 히스토그램을 부드러운 곡선으로 처리해주는 것이 확률밀도함수이다.
#왜도와 첨도도 확인할 수 있다.
sns.distplot(df_chol)
#bin으로 데이터를 몇 개로 나눠 담을 것인지 설정한다.
#이상치 때문에 그래프가 한쪽으로 몰리는 것을 볼 수 있다. max 값이 지나치게 크기 때문이다.
sns.distplot(df_chol, bins=10)
df[df["총콜레스테롤"].notnull() & (df["음주여부"] == 1)]
#displot은 series데이터를 넣어줘야 한다.
sns.distplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 1), "총콜레스테롤"])
sns.distplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 0), "총콜레스테롤"])
#hist=False로 설정해주면 선만 나온다.
sns.distplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 1), "총콜레스테롤"], hist=False)
sns.distplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 0), "총콜레스테롤"])
#확률밀도함수만 그리기 위해 kdeplot을 그린다.
sns.kdeplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 1), "총콜레스테롤"])
sns.kdeplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 0), "총콜레스테롤"])
#label을 넣어서 각 데이터를 설명해준다.
sns.kdeplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 1), "총콜레스테롤"], label="음주 중")
sns.kdeplot(df.loc[(df["총콜레스테롤"].notnull()) & (df["음주여부"] == 0), "총콜레스테롤"], label="음주 안 함")
#plt.axvline()을 사용하여 그래프에 평균값과 중앙값 선을 그린다.
plt.axvline(df_sample["총콜레스테롤"].mean(), linestyle=":")
plt.axvline(df_sample["총콜레스테롤"].median(), linestyle="--")
sns.kdeplot(df_sample.loc[(df_sample["총콜레스테롤"].notnull()) & (df["음주여부"] == 1), "총콜레스테롤"], label="음주 중")
sns.kdeplot(df_sample.loc[(df_sample["총콜레스테롤"].notnull()) & (df["음주여부"] == 0), "총콜레스테롤"], label="음주 안 함")
#음주 여부에 따른 감마지피티를 확인한다.
s_1 = df_sample.loc["음주여부"] == 1, "감마지티피"]
s_0 = df_sample.loc["음주여부"] == 0, "감마지티피"]
sns.distplot(s_1, label="음주 중")
sns.distplot(s_0, label="음주 중")
12. 상관계수 - heatmap 으로 표현하기
상관계수
- 변수들 간의 관계를 알아볼 때 유용한 개념이다.
- 특정 데이터에 대한 상관관계를 볼 수 있다.
- 상관계수는 -1부터 1사이로 구성되고, 0.3부터 0.7 사이면 뚜렷한 양적 선형관계, 0.7 이상이면 강한 양적 상관관계라 할 수 있다.
- 상관계수를 계산할 때 대각선이 1인 이유는 자기자신과 가장 관계가 있기 때문이다.
-는 음의 상관관계이고, +는 양의 상관관계이다. - 우선 columns 변수 안에 상관계수에 사용할 컬럼들을 담는다.
df_small = df_sample[columns]
df_corr = df_small.corr()
df_corr
#0에 가까우면 상관관계가 없다고 볼 수 있다.
df_corr["신장(5Cm단위"].sort_values()
#신장과의 상관계수가 0.3 이상인 feature만 가져온다.
df_corr.loc[df_corr["신장(5Cm단위"] > 0.3, "신장(5Cm단위)"]
#음주여부와의 상관계수가 0.3 이상인 feature만 가져온다.
df_corr.loc[df_corr["음주여부"] > 0.1, "음주여부"]
df_corr["음주여부"].sort_values()
#상관계수는 두 변수 간의 연관된 정도만 나타낼 뿐 인과관계를 설명하는 것은 아니다.
df_corr.loc[df_corr["음주여부"] > 0.25, "음주여부"]
#혈색소와의 상관계수를 내림차순으로 정렬한다.
df_corr["혈색소"].sort_values(ascending=False).head(7)
#간수치와 관련된 값들이 상위로 나온다.
df_corr["감마지티피"].sort_values(ascending=False).head(7)
heatmap
- 바로 data만 넣어준다.
- 상관관계가 클수록 값의 색이 진해진다.
- annot 옵션으로 숫자를 나타낼 수 있고, fmt으로 소수점 개수를 지정할 수 있고, cmap으로 색상을 지정할 수 있다.
plt.figure(figsize=(20,7))
sns.heatmap(df_corr, annot=True, fmt=".2f", cmap="Blues")
#공식문서에서 매트릭스의 대각선 아래만 표시하는 mask 설정을 가져온다.
mask = np.triu(np.ones_like(corr, dtype=np.bool))
plt.figure(figsize=(20, 7))
sns.heatmap(df_corr, annot=True, fmt=".2f", cmap="Blues", mask=mask)
#그 외로 vmax, vmin은 색상 농도를 지정하는 옵션이다.
'Study > Big Data' 카테고리의 다른 글
파이썬으로 시작하는 데이터 사이언스 - 5강 (0) | 2023.11.22 |
---|---|
파이썬으로 시작하는 데이터 사이언스 - 3강 (0) | 2023.10.21 |
파이썬으로 시작하는 데이터 사이언스 - 2강 (0) | 2023.10.21 |
파이썬으로 시작하는 데이터 사이언스 - OT, 1강 (0) | 2023.10.13 |
[부스트코스] 데이터 사이언스 (5) (0) | 2023.04.12 |