촉촉한초코칩

[부스트코스] 데이터 사이언스 (4) 본문

Study/Big Data

[부스트코스] 데이터 사이언스 (4)

햄친구베이컨 2023. 4. 1. 14:20

건강검진 데이터로 가설검정하기 

라이브러리 로드 
import pandas as pd  #분석에 사용 
import numpy as np   #수치계산에 사용
import seaborn as sns # 시각화에 사용 
import matplotlib.pyplot as plt #구버전 주피터 노트북에서는 %matplotlib inline 설정이 되어야 그래프 시각화가 가능하다.

%matplotlib inline

 

한글폰트 설정 
#나눔고딕 설정
!apt -qq -y install fonts-nanum > /dev/numpy

import matplotlib.font_manager as fm 

fontpath = '/usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf'
font = fm.FontProperties(fname=fontpath, size=9)
# fm._rebuild()

#colab 한글 폰트 설정
plt.rc('font', family='NanumGothic')
#마이너스 폰트 깨지는 문제 대처
plt.rc('axes', unicode_minus=False)

import os

if os.name == 'posix':
  plt.rc("font", family="AppleGothic")
else:
  plt.rc("font", family="Magun Gothic")

plt.rc("axes", unicode_minus=False)

#폰트 주변이 흐릿하게 보이는 것 방지 
%config InlineBacked.figure_fotmat = 'retina'

 

데이터 불러오기

 

드라이브 마운트 > content > drive > MyDrive > Colab Notebooks

#다운로드 받은 파일 read_csv로 불러온다.
#파일을 읽어 온 후 shape로 행과 열의 수를 출력한다.
df = pd.read_csv("/content/drive/MyDrive/Colab Notebooks/health.CSV", encoding="cp949")
df.shape

 

데이터 미리보기 (sample, head, tail)
df.head() #초기값 : 5

df.sample() #랜덤으로 1개 가져오기 

df.tail() #초기값 : 5

 

기본정보 보기
#info : 데이터 크기, 영역, 메모리 사용량 
df.info()
# 0 : 결측치

#컬럼만 출력하기
df.columns

#dtypes > 데이터 형식만 출력
df.dtypes

 

결측치 보기 
#isnull > 결측치를 bool 값으로 표시하고 sum하면 컬럼마다 결측치를 세어준다.
#true : 결측치 o, false : 결측치 x 
df.isnull().sum()

#isna : 결측치 여부 확인, sum을 통해 결측치 수 집계
df.isna().sum

#plot으로 시각화
df.isnull().sum().plot.barh(figsize=(10,9))

 

일부 데이터 요약하기
#여러 컬럼 가져오기
#1개 : 시리즈, 2개 : 데이터프레임 형태 
#1개도 괄호 2개로 묶어주면 데이터프레임형태로 보여준다.
df[["(혈청지오티)ALT", "(혈청지오티)AST"]].head()

#요약하기 > info, describe
df[["(혈청지오티)ALT", "(혈청지오티)AST"]].info()
df[["(혈청지오티)ALT", "(혈청지오티)AST"]].describe()

 

value_counts로 값 집계하기
#성별코드로 그룹화하고 개수 집계하기
df["성별코드"].value_counts()
#흡연상태 
df["흡연상태"].value_counts()

 

groupby와 pivot_table 사용하기

 

groupby

#데이터 그룹화
#성별코드로 그룹화한 데이터 세어보기
#value_counts와 동일 
df.groupby(["성별코드"])["가입자일련번호"].count()

#여러 개로 그룹화하고 개수 세어보기
df.groupby(["성별코드","음주여부"])["가입자일련번호"].count()

#성별코드, 음주여부로 그룹화하고 감마지티피의 평균 구하기 
df.groupby(["성별코드","음주여부"])["감마지티피"].mean()

#성별코드와 음주여부로 그룹화하고 감마지티피의 요약수치 구하기 
df.groupby(["성별코드","음주여부"])["감마지티피"].describe()

#agg : 여러 수치 함께 구하기
df.groupby(["성별코드","음주여부"])["감마지티피"].agg(["count","mean","median"])

 

pivot_table

#음주여부에 따른 그룹화된 수를 피봇테이블로 구하기 
#기본값 aggfunc : 평균값 
df.pivot_table(index="음주여부",values="가입자일련번호",aggfunc="count")

#음주여부에 따른 감마지티피의 평균 구하기
#기본값 aggfunc : 평균값 
pd.pivot_table(df, index="음주여부", values="감마지티피", aggfunc=["mean","median"])

#aggfunc에 describe를 사용해서 통계요약값 한번에 보기
pd.pivot_table(df, index="음주여부", values="감마지티피", aggfunc="describe")

#성별코드, 음주여부에 따른 감마지티피 값 평균 구하기
pd.pivot_table(df, index=["성별코드","음주여부"], values="감마지티피", aggfunc="mean")

 

전체 데이터 시각화하기
 
  • 100만개가 넘는 데이터 > groupby, pivot table 연산으로 시각화화하는 것 추천
  • seaborn과 같은 고급 통계 연산을 하는 그래프는 많이 느릴 수 있다. 

슬라이싱 해서 히스토그램 그리기

  • iloc : 인덱스의 순서대로 슬라이싱이 가능하다.
  • iloc[행, 열] 순으로 인덱스를 써주면 해당 인덱스만 불러오며, 전체 데이터를 가져올 때는 [:, :]을 사용한다. 
  • 대괄호 안의 콜론 앞뒤에 숫자를 써주면 > 시작인덱스:끝나는인덱스+1 지정 가능
  • 끝나는 인덱스를 안 쓸 경우 > 마지막까지 가져온다는 뜻
#전체 데이터에 대한 히스토그램 출력
h = df.hist(figsize=(12,12))

#앞에서 12개 칼럼에 대한 데이터로 히스토그램 그리기
h = df.iloc[:,:12].hist(figsize=(12,12))

#슬라이싱 사용해서 앞에서 12번째부터 23번째까지 컬럼에 대한 데이터로 히스토그램 그리
h = df.iloc[:, 12:24].hist(figsize=(12,12), bins=100)

#슬라이싱 사용해서 앞에서 24번째부터 24번째까지 컬럼에 대한 데이터로 히스토그램 그리
h = df.iloc[:, 24:].hist(figsize=(12,12), bins=100)

 

샘플 데이터 추가하기

 

  • seaborn 그래프 : 내부적으로 수학적 연산이 되기 때문에 데이터가 많으면 속도가 오래걸린다.
  • 전체 데이터를 사용하면 너무 느리기 때문에 일부만 샘플링해서 사용한다. 
#df.sample > 일부 데이터만 샘플데이터 추출
#random_state > 샘플링되는 값 고정
#실험을 통제하기 위해 random_state를 고정하기도 한다. 

df_sample = df.sample(1000, random_state=1)
df_sample.shape

 

범주형 (카테고리) 데이터 시각화

 

  • countplot : 범주형 데이터의 수를 더한 값을 그래프로 표현한다.
  • value_counts로 구한 값을 시각화한다고 보면 된다.
df["음주여부"].value_counts().plot.bar()
sns.countplot(x="음주여부", data=df)

 

hue 옵션 사용하기

  • 음주여부에 따른 countplot을 그리고 hue를 사용해서 성별코드로 색상을 구분해 그린다. 
  • hue : 포토샵에 있는 hue 메뉴(색상)
  • seaborn에서 제공하는 폰트 설정 사용 가능 (기본 스타일)
sns.countplot(data=df, x="음주여부", hue="성별코드")
#1 : 남성, 2 : 여성, 0.0 : 음주x, 1.0 : 음주o

#연령대별 음주여부 보기
#hue를 사용해서 다른 색상으로 표현한다.
sns.countplot(data=df, x="연령대코드(5세단위)", hue="음주여부")

#키, 몸무게 : 연속형 데이터
#이렇게 특정 범위로 묶게 되면 연속형 데이터라기보다는 범주형 데이터라고 볼 수 있다.
plt.figure(figsize=(15,4))
sns.countplot(data=df, x="신장(5Cm단위)")

plt.figure(figsize=(15,4))
sns.countplot(data=df, x="체중(5Kg 단위)")

#성별에 따른 키 차이 보기
plt.figure(figsize=(15,4))
sns.countplot(data=df, x="신장(5Cm단위)", hue="성별코드")

plt.figure(figsize=(15,4))
sns.countplot(data=df, x="체중(5Kg 단위)", hue="성별코드")

plt.figure(figsize=(15,4))
sns.countplot(data=df, x="체중(5Kg 단위)", hue="음주여부")

 

barplot - 수치형 / 범주형 데이터 시각화

 

*ci : 신뢰구간

  • 95 : 95%의 신뢰구간 지정
  • none : 신뢰구간 표시하지 않기
  • sd : 표준편차
#연령대코드와 총 콜레스테롤 보기
#hue로 색상을 다르게 표현한다. (음주여부)
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="총콜레스테롤", hue="음주여부")

#hue > 흡연상태
plt.figure(figsize=(15,4))
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="총콜레스테롤", hue="흡연상태")

#트리글리세라이드(중성지방)에 따른 연령대코드(5세단위)를 움주여부에 따라 barplot로 그리기
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="트리글리세라이드", hue="음주여부", ci="sd")

#음주여부와 체중(5Kg 단위)을 성별에 따라 보기
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5Kg 단위)", hue="성별코드")

#연령대코드(5세단위)에 따른 체중(5Kg 단위)을 음주여부에 따라 barplot으로 그리기
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5Kg 단위)", hue="음주여부")

 

linepot, pointplot
#연령대코드(5세단위)에 따른 체중(5Kg 단위)을 성별코드에 따라 lineplot으로 그린다.
plt.figure(figsize=(15,4))
sns.lineplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5Kg 단위)", hue="성별코드")

#연령대코드(5세단위)에 따른 신장(5Cm단위)을 성별코드에 따라 lineplot으로 그린다.
plt.figure(figsize=(15,4))
sns.lineplot(data=df_sample, x="연령대코드(5세단위)", y="신장(5Cm단위)", hue="성별코드", ci="sd")

#연령대코드(5세단위)에 따른 체중(5Kg 단위)을 음주여부에 따라 pointplot, lineplot으로 그린다.
plt.figure(figsize=(15,4))
sns.barplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5Kg 단위)", hue="음주여부", ci="sd")
sns.lineplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5Kg 단위)", hue="음주여부", ci="sd")
sns.pointplot(data=df_sample, x="연령대코드(5세단위)", y="체중(5Kg 단위)", hue="음주여부", ci="sd")

#연령대코드(5세단위)에 따른 신장(5Cm단위)을 성별코드에 따라 pointplot으로 그린다.
plt.figure(figsize=(15,4))
sns.pointplot(data=df_sample, x="연령대코드(5세단위)", y="신장(5Cm단위)", hue="성별코드", ci="sd")

#연령대코드(5세단위)에 따른 혈색소를 음주여부에 따라 lineplot으로 그린다.
plt.figure(figsize=(15,4))
sns.lineplot(data=df, x="연령대코드(5세단위)", y="혈색소", hue="음주여부", ci=None)

 

boxplot, violinplot, swarmplot, lmplot

 

* swarmplot : 범주형 데이터를 산점도로 시각화할 때 사용한다. 

#boxplot으로 신장(5Cm단위)에 따른 체중(5Kg 단위)을 그리며, 성별코드에 따라 다른 색상으로 표현되게 한다.
plt.figure(figsize=(15,4))
sns.boxplot(data=df, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="성별코드")

#violinplot 신장 (5Cm단위)에 따른 체중 (5Kg단위)을 그리며 음주여부에 따라 다른 색상으로 표현되게 한다.
plt.figure(figsize=(15,4))
sns.violinplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부")

#violinplot의 split 기능 사용하기
plt.figure(figsize=(15,4))
sns.violinplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부", split=True)

#violinplot 연령대코드(5세단위)에 따른 혈색소를 그리며 음주여부에 따라 다른 색상으로 표현되게 한다.
plt.figure(figsize=(15,4))
sns.violinplot(data=df_sample, x="연령대코드(5세단위)",y="혈색소", hue="음주여부", split=True)

#swarmplot으로 신장(5Cm단우)에 따른 체중(5Kg 단위)을 그리며, 음주여부에 따라 다른 색상으로 표현되게 한다.
#점을 하나씩 찍기 때문에 데이터가 많을 경우 오래걸린다.
plt.figure(figsize=(15,4))
sns.violinplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부")
sns.swarmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)")

#swarmplot으로 연령대코드(5세단위)에 따른 음주여부를 그리며, 성별코드에 따라 다른 색상으로 표현되게 한다.
#점을 하나씩 찍기 때문에 데이터가 많을 경우 오래걸린다.
plt.figure(figsize=(15,4))
sns.swarmplot(data=df_sample, x="연령대코드(5세단위)", y="혈색소", hue="성별코드")

#lmplot으로 그리기
sns.lmplot(data=df_sample, x="연령대코드(5세단위)", y="혈색소", hue="음주여부", col="성별코드")

 

 

수치형 데이터 시각화 

 

1) scatterplot - 산점도

  • 수치형 vs 수치형 데이터의 상관관계를 볼 때 주로 사용
  • 점의 크기를 데이터의 수치에 따라 다르게 볼 수 있다.
#scatterplot으로 (혈청지오티)AST, (혈청지오티)ALT을 그리고 음주여부에 따라 다른 색상으로 표현되게 한다.
plt.figure(figsize=(8,7))
sns.scatterplot(data=df_sample, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="음주여부", size="체중(5Kg 단위)")

 

2) lmplot - 상관관계 보기

#lmplot으로 신장(5Cm단위)에 따른 체중(5Kg 단위)을 그리며 음주여부에 따라 다른 색상으로 표현되게 한다.
sns.lmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="음주여부", col="성별코드")

#lmplot으로 col 기능을 이용해 음주여부에 따라 서브플롯 그리기
sns.lmplot(data=df_sample, x="신장(5Cm단위)", y="체중(5Kg 단위)", hue="성별코드", col="음주여부")

#lmplot으로 수축기, 이완기혈압을 그리고 음주여부에 따라 다른 색상으로 표현되게 한다. 
sns.lmplot(data=df_sample, x="수축기혈압", y="이완기혈압", hue="음주여부")

#lmplot으로 (혈청지오티)AST, (혈청지오티)ALT을 그리고 음주여부에 따라 다른 색상으로 표현되게 한다.  
sns.lmplot(data=df_sample, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="음주여부", robust=True)

 

3) 이상치 다루기

  • 이상치가 있으면 데이터가 자세히 보이지 않거나 이상치로 인해 회귀선이 달라지기도 한다.
  • 시각화를 통해 이상치를 제거하고 이상치만 따로 모아 보도록 한다. 
#(혈청지오티)AST와 (혈청지오티)ALT가 400 이하인 값만 데이터프레임 형태로 추출해서
#df_ASLT 변수에 담는다. 
df_ASLT = df_sample[(df_sample['(혈청지오티)AST'] < 400) & (df_sample['(혈청지오티)ALT'] < 400)] 

#이상치를 제거한 (혈청지오티)AST와 (혈청지오티)ALT를 lmplot으로 그리고
#음주여부에 따라 다른 색으로 표현한다.
sns.lmplot(data=df_ASLT, x="(혈청지오티)AST", y="(혈청지오티)ALT", hue="음주여부", ci=None)

#(혈청지오티)AST와 (혈청지오티)ALT가 200 이상인 값만 데이터프레임 형태로 추출해서
#df_ASLT 변수에 담는다. 
df_ASLT_high = df[(df['(혈청지오티)AST'] > 200) | (df['(혈청지오티)ALT'] > 200)] 

#df_ASLT_high 데이터 프레임에 담겨진 혈청지오티가 높은 데이터만 따로 보기
df_ASLT_high

#(혈청지오티)AST와 8000 이상인 값만 데이터프레임 형태로 추출
df_ASLT_high_8000 = df_ASLT_high[df_ASLT_high["(혈청지오티)AST"] > 8000]
df_ASLT_high_8000.iloc[:, 4:27]

 

수치형 데이터 분포 표현하기 > displot

 

* distplot : 결측치가 있으면 안 됨!

 
#수치형 데이터로 된 칼럼을 찾기 위해 컬럼명만 따로 출력하기
df.columns

#총콜레스테롤에 따른 distplot 그리기
#notnull : 결측치가 아닌 값만 가져오기 
df_chol = df.loc[df["총콜레스테롤"].notnull(), "총콜레스테롤"]
sns.displot(df_chol)
#이상치때문에 한쪽으로 몰려서 보이는 상태 

#음주여부가 1인 값에 대한 총콜레스테롤을 distplot으로 그리기
sns.distplot(df.loc[
    df["총콜레스테롤"].notnull() & (df["음주여부"] == 1),
    "총콜레스테롤"])
    
#음주여부가 0인 값에 대한 총콜레스테롤을 distplot으로 그리기
sns.distplot(df.loc[
    df["총콜레스테롤"].notnull() & (df["음주여부"] == 0),
    "총콜레스테롤"])
    
#음주여부 값에 대한 총콜레스테롤을 distplot으로 그리며 하나의 그래프에 표시되도록 한다. 
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[df_sample["음주여부"] == 1, "감마지티피"]
s_0 = df_sample.loc[df_sample["음주여부"] == 0, "감마지티피"]
sns.kdeplot(s_1, label="음주 중")
sns.kdeplot(s_0, label="음주 안 함")

 

상관분석
columns=['연령대코드(5세단위)','신장(5Cm단위)','체중(5Kg 단위)', '허리둘레', '시력(좌)', 
         '시력(우)', '청력(좌)', '청력(우)', '수축기혈압','이완기혈압','식전혈당(공복혈당)',
       '총콜레스테롤', '트리글리세라이드', 'HDL콜레스테롤', 'LDL콜레스테롤',
       '혈색소', '요단백', '혈청크레아티닌', '(혈청지오티)AST', '(혈청지오티)ALT', 
       '감마지티피', '흡연상태','음주여부']
columns

 

1) 상관계수 구하기

#샘플컬럼만 가져와서 df_small이라는 데이터프레임에 담은 뒤 상관계수를 구한다.
df_small = df_sample[columns]
df_corr = df_small.corr()
df_corr

#키에 대한 상관계수가 특정 수치 이상인 데이터 보기
df_corr.loc[df_corr["신장(5Cm단위)"]>0.3,"신장(5Cm단위)"]

#음주여부에 대한 상관계수가 특정 수치 이상인 데이터 보기
df_corr.loc[df_corr["음주여부"] > 0.25, "음주여부"]
# df_corr["음주여부"].sort_values()

#혈색소에 대한 상관계수가 특정 수치 이상인 데이터 보기
df_corr["혈색소"].sort_values(ascending=False).head(5)

#감마지티피 대한 상관계수가 특정 수치 이상인 데이터 보기
df_corr["감마지티피"].sort_values(ascending=False).head(5)

 

2) heatmap

#위에서 구한 상관계수를 heatmap을 통해 표현하기
plt.figure(figsize=(20,7))
sns.heatmap(df_corr, annot=True, fmt=".2f", cmap="Blues")

mask = np.triu(np.ones_like(df_corr, dtype=np.bool))

plt.figure(figsize=(20,7))
sns.heatmap(df_corr, annot=True, fmt=".2f", cmap="Blues", mask=mask)