본문 바로가기
데이터 분석 및 시각화

[데이터분석] t-test,상관분석

by 바다의 공간 2024. 8. 20.

통계분석을 통한 가설검정 (t-test) 두 변수의 평균에 차이가 있는지 검정

 

# t-test(t-검정)은 주 변수(데이터군)의 평균에 통계적으로 유의한 차이가 있는지 알아볼 때 사용하는 통계분석 기법

- 중요한것은 피벨류의 값이고 유의하다라는것은 우연히 차이날 확률이 작다는것이고 우연이 아니다 라는걸로 해석할 수 있습니다.

# scipy패키지의 ttest_ind()를 통해 t-검정을 수행 (scipy라이브러리 설치 필요)

# t-test.py

# t-test (t-검정)
# 두 변수(=두 데이터군)의 평균을 기준으로 유사도를 검증하는 통계분석 기법
# scipy 라이브러리를 사용

def p(str):
    print(str, '\n')

# compact자동차와 suv자동차의 도시연비 t검정
import pandas as pd
mpg = pd.read_csv('../assets/mpg.csv')
mpg.info()

## 기술 통계 분석
# category가 compact이거나 suv
# category가 같은것들 그룹핑
# n변수에는 category의 개수, mean변수에는 cty의 평균값
mpg_agg = mpg.query('category in ["compact", "suv"]') \
    .groupby('category', as_index=False) \
    .agg(n=('category', 'count'), mean=('cty', 'mean'))
p(mpg_agg)

# category별로 도시연비(cty) 분리
compact = mpg.query('category=="compact"')['cty']
suv = mpg.query('category=="suv"')['cty']
print(compact, suv)

# t-test
from scipy import stats
# equal_var=True : 집단 간 분산이 같다고 가정
# p-value가 0.05보다 작다 = 유의확률이 작다 = 통계적으로 유의하다 = 상관 있다
p(stats.ttest_ind(compact, suv, equal_var=True))

# 실습 : 일반휘발유(fl:r)와 고급휘발유(fl:p)의 도시연비(cty) t-test

## 기술 통계 분석

# r, p 추출하기
# fl별 분리
# 빈도 구하기
# cty 평균 구하기
mpg_fl = mpg.query('fl in ["r", "p"]') \
    .groupby('fl', as_index=False) \
    .agg(n=('fl', 'count'), mean=('cty', 'mean'))
p(mpg_fl)
regular = mpg.query('fl=="r"')['cty'] # 일반휘발유
premium = mpg.query('fl=="p"')['cty'] # 고급휘발유

# t-test
# p-value가 0.05보다 크다 = 유의확률이 크다 = 통계적으로 유의하지 않다 = 상관도가 적다
p(stats.ttest_ind(regular, premium, equal_var=True))

 

 

이렇게 pvalud값이 0.05보다 크다면 통계적으로 상관도가 적다는것입니다.

 


전체적으로 다시 복습하자면

t-검정 이라는 통계기법을 사용해서 소형차와 suv연비가 정말로 다른건지 아니면 우연히 차이가 난건지에 대한 데이터분석을 해보려고하는겁니다.

 

1. 데이터를 불러옵니다.

필요한 외부라이브로리는 판다스라서 판다스를 불러오고

pd.read_csv('경로')를 이용해서 파일을 읽어줍니다.

그 다음 .info()를 이용해서 간단한 파일정보를 알아봅니다.

확인할수있는것은 데이터 크기, 열, 행의 개수정도를 알 수 있습니다.

 

2. 첫번째 비교 : 소형차(compact)와 suv 도시 연비비교

 

2-1. 소형차와 suv그룹만들

compact와 suv차종의 데이터만 필요하고 나머지는 딱히 필요가 없겠죠?

그러니 compact, suv 종끼리 그룹바이를 해서 평균 연비를 계산해보려 합니다.

mpg.query('category in ["compact", "suv"]')

  • query()는 데이터를 조건에 맞게 필터링해주는 함수입니다. 여기서는 category 열이 "compact"(소형차) 또는 "suv"(SUV)인 데이터만 골라내고 있어요.
  • 즉, 소형차와 SUV만 선택하는 과정이라고 보면 됩니다.

groupby('category', as_index=False)

  • groupby()는 데이터를 특정 기준으로 묶어주는 함수입니다. 여기서는 category를 기준으로 소형차와 SUV를 각각 묶고 있어요. 묶인 데이터들끼리 계산을 쉽게 할 수 있죠.
  • as_index=False는 그룹을 묶을 때 인덱스로 사용하지 말라는 뜻이에요. 즉, 데이터프레임 형태로 계속 유지하겠다는 의미입니다.

.agg(n=('category', 'count'), mean=('cty', 'mean'))

  • agg() 함수는 그룹별로 원하는 계산(예: 합계, 평균 등)을 할 수 있게 해줍니다.
  • 여기서는 두 가지 계산을 하고 있어요:
    1. n=('category', 'count'): 각 그룹(소형차, SUV)에 몇 대의 차량이 있는지 세고 있어요.
    2. mean=('cty', 'mean'): 각 그룹의 도시 연비(cty)의 평균을 계산하고 있습니다.

결과적으로, 이 코드는 소형차와 SUV의 개수와 그들의 평균 도시 연비를 보여줍니다.

 

 

2.2. 소형차와 SUV의 연비 데이터 따로 저장하기

 

이 부분에서는 소형차와 SUV 각각의 연비 데이터를 따로 나누어 저장합니다.

mpg.query('category=="compact"')['cty']

  • 이 코드는 query()를 사용해 category가 "compact"인 데이터, 즉 소형차의 데이터만 선택한 다음, 그 중에서도 cty(도시 연비) 열만 따로 저장하는 거예요.
  • 마찬가지로 mpg.query('category=="suv"')['cty']는 SUV의 도시 연비 데이터만 선택해서 저장합니다.

이렇게 나눠진 데이터를 나중에 비교 분석할 수 있습니다.

 

2.3. 두 그룹의 연비 차이를 비교(t-검정)

 

이 코드는 scipy 라이브러리의 ttest_ind() 함수를 사용해 두 그룹(소형차와 SUV)의 평균 연비가 통계적으로 다른지 비교하는 부분입니다.

stats.ttest_ind(compact, suv, equal_var=True)

  • ttest_ind()는 두 그룹의 평균이 통계적으로 다른지 확인하는 함수예요. 여기서는 소형차와 SUV의 연비 평균이 차이가 나는지 알아봅니다.
  • equal_var=True는 두 그룹의 데이터가 비슷한 분산(데이터의 흩어짐 정도)을 가지고 있다고 가정한다는 뜻이에요. 보통 초급 단계에서는 이렇게 설정합니다.
  • 이 함수는 두 그룹의 평균 차이가 통계적으로 유의미한지를 알려주는 p-value라는 결과를 반환합니다. 이 p-value가 0.05보다 작으면 "소형차와 SUV의 평균 연비 차이는 우연이 아니고, 정말로 다르다"고 결론을 내릴 수 있어요.

3. 일반휘발유와 고급휘발유 차량의 도시 연비 비교하기

이제 두 번째 비교인 연료 종류에 따른 연비 차이를 분석해봅시다.

3.1. 일반휘발유와 고급휘발유 그룹 만들기

 
mpg_fl = mpg.query('fl in ["r", "p"]') \ .groupby('fl', as_index=False) \ .agg(n=('fl', 'count'), mean=('cty', 'mean')) print(mpg_fl)
 

여기서는 연료가 일반휘발유(r)나 고급휘발유(p)인 차량들을 추출해서 그들의 평균 연비를 계산하고 있습니다.

mpg.query('fl in ["r", "p"]')

  • query()를 사용해 연료(fl)가 "r"(일반휘발유) 또는 "p"(고급휘발유)인 데이터만 골라내고 있어요.

groupby('fl', as_index=False)

  • groupby()로 연료 종류별로 차량을 묶습니다. 즉, 일반휘발유 차량끼리, 고급휘발유 차량끼리 묶어서 계산할 수 있도록 준비하는 거죠.

.agg(n=('fl', 'count'), mean=('cty', 'mean'))

  • agg() 함수로 각 그룹의 차량 수(n)와 도시 연비 평균(mean)을 계산하고 있습니다.

3.2. 각 그룹의 연비 데이터 따로 저장하기

regular = mpg.query('fl=="r"')['cty'] premium = mpg.query('fl=="p"')['cty']

이 부분에서는 일반휘발유와 고급휘발유 차량의 도시 연비 데이터를 각각 따로 저장합니다.

3.3. 두 그룹의 연비 차이를 비교(t-검정)

 
print(stats.ttest_ind(regular, premium, equal_var=True))

마찬가지로, ttest_ind() 함수로 두 그룹(일반휘발유와 고급휘발유 차량)의 평균 연비가 통계적으로 다른지 확인합니다. 결과로 나오는 p-value가 0.05보다 크다면 "두 그룹의 평균 연비 차이는 우연일 가능성이 크다"고 결론을 내릴 수 있어요.

 


통계분석을 통한 가설검정 (상관분석)

 

연속 변수가 서로 관련이 있는지 검정

# 상관분석 (correlation analysis) 연속 변수가 서로 관련이 있는지 검정하는 통계 분석 기법

 

# 상관계수 (correlation coefficient)

* 변수의 관련도를 0~1의 값으로 표시하며 1에 가까울수록 상관성이 큼

* 양수면 정비례, 음수면 반비례

 

# 상관행렬 (correlation matrix)

* 변수들 간의 상관계수를 행렬로 표시

* DataFrame의 corr()메소드를 통해 상관행렬을 생성

상관행렬

 

 

# 상관계수와 유의확률은 scipy의 stats.pearsonr()을 이용해 구함

 

# 히트맵(상관행렬을 도식화)은 seaborn의 heatmap()을 이용해 그림 (mtcars.csv를 assets폴더에 복사)

 

 

#correlationanalysis.py

# 상관분석 :  두 변수간의 관계를 분석 (주로 연속된 값에 대한 관계)


def p(str):
    print(str, '\n')


#economics 데이터 불러오기
import pandas as pd
economics = pd.read_csv('../assets/economics.csv')
economics.info()

#상관행렬 만들기
p(economics[['unemploy', 'pce']].corr()) #실업자수, 개인소비지출

#상관분석(상관계수, 유의확률<p-value>)
# 상관계수는 -1~1의 값: 1이나 -1에 가까울수록 상관도가 높다.
#                   : 양수는 정비례, 음수는 반비례 관계이다.

from scipy import stats
p(stats.pearsonr(economics['unemploy'], economics['pce']))
#상관계수 == 0.614517614193208(정비례),  p-value((6.773527303290177e-61))= 상관도가 높다

## 상관행렬 히트맵 만들기

# mtcars 데이터 불러오기
mtcars = pd.read_csv('../assets/mtcars.csv')
p(mtcars.head())

# 상관행렬 만들기
car_cor =  mtcars.corr()
# 소수점 둘째자리 반올림
car_cor = round(car_cor, 2)
p(car_cor)

#그래프 설정
import matplotlib.pyplot as plt
plt.rcParams.update({
    "figure.dpi": '120', #해상도
    'figure.figsize': [7.5, 5.5], #화면크기
})

#히드맵 그리기
import seaborn as sns
# # annot=True 상관계수 표시, cmap:컬러맵
# sns.heatmap(car_cor, annot=True, cmap='RdBu')
# plt.show()

#대각행렬 제거용 mask 만들기
import numpy as np
mask = np.zeros_like(car_cor) #0으로 채운 행렬
p(mask)

#오른쪽 위 대각행렬을 1로 바꾸기
mask[np.triu_indices_from(mask)] = 1
p(mask)

#mask 적용된 히트맵 표시
# sns.heatmap(data=car_cor, annot=True, cmap='RdBu', mask=mask)
# plt.show()

# 빈 행, 빈 열, 히트맵에서 제거
mask_new = mask[1:, :-1] #행렬에서 첫 행, 마지막 열 제거
cor_new = car_cor.iloc[1:, -1]

# 히트맵 만들기
sns.heatmap(data=cor_new, annot=True, cmap='RdBu', mask=mask_new)
plt.show()

#히트맵 세부 설정 옵션
sns.heatmap(
    data = cor_new, #데이터
    anoot = True, #상관계수 표시
    cmap = 'RdBu', #컬러맵 설정
    mask = mask_new, #mask설정
    linewidths=.5, #경계구분선 두께
    vmax = 1, #가장 진한 파랑색으로 표현할 최대값
    vmin = -1, #가장 진한 빨간색으로 표현할 최소값
    cbar_kws= {'shrink': .5} #범례 크기
)
plt.show()

 

 

자세하게 코드 복습을 해보자면 

1. 데이터 불러오기와 간단한 정보 확인

 
import pandas as pd economics = pd.read_csv('../assets/economics.csv') economics.info()

pd.read_csv()

  • 이 함수는 CSV 파일을 불러와서 economics라는 변수에 데이터를 저장합니다. 여기서는 경제 데이터(economics.csv)를 불러오고 있어요.

economics.info()

  • info() 함수는 불러온 데이터의 간단한 정보를 보여줍니다. 예를 들어, 몇 개의 행과 열이 있는지, 각 열이 어떤 데이터 타입을 가지고 있는지 등을 확인할 수 있어요.

2. 상관 행렬 만들기

이제 두 변수 간의 상관관계를 계산해보는 단계입니다. 상관관계는 두 값이 어떻게 함께 변하는지를 나타내요. 예를 들어, 실업자가 많아질수록 소비지출이 줄어드는지, 아니면 늘어나는지를 알아보는 거예요.

 
p(economics[['unemploy', 'pce']].corr())

economics[['unemploy', 'pce']].corr()

  • corr() 함수는 상관 행렬을 계산합니다. 상관 행렬은 여러 변수 간의 상관관계를 보여줘요.
  • 여기서는 실업자 수(unemploy)와 개인소비지출(pce) 간의 상관관계를 계산하고 있어요.
  • 상관관계의 값은 -1에서 1 사이의 값이에요. 1에 가까울수록 두 변수는 강하게 양의 상관관계를 가지며, -1에 가까울수록 강한 음의 상관관계를 가집니다. 0에 가까우면 상관관계가 거의 없다는 뜻이에요.

3. 상관 분석 (상관계수와 유의확률)

이제 두 변수 간의 상관계수와 p-value를 구해보는 단계입니다. 상관계수는 두 변수 간의 관계 강도를 나타내고, p-value는 그 관계가 통계적으로 의미 있는지 확인하는 값이에요.

 
from scipy import stats p(stats.pearsonr(economics['unemploy'], economics['pce']))

stats.pearsonr()

  • pearsonr() 함수는 두 변수 간의 피어슨 상관계수를 계산해줍니다. 피어슨 상관계수는 -1에서 1 사이의 값이며, 두 변수 간의 선형 관계를 측정해요.
  • 여기서는 실업자 수(unemploy)와 개인소비지출(pce) 간의 피어슨 상관계수를 계산하고 있어요.
  • 이 함수는 상관계수와 p-value를 반환해요.
    • 상관계수: 두 변수 간의 관계 강도를 나타내요. 값이 1에 가까우면 양의 상관관계(정비례), -1에 가까우면 음의 상관관계(반비례)입니다.
    • p-value: 상관관계가 통계적으로 유의미한지 확인하는 값이에요. 보통 p-value가 0.05보다 작으면 상관관계가 있다고 결론을 내릴 수 있어요.

4. 상관 행렬 히트맵 만들기

이제 다른 데이터(mtcars.csv)를 사용해 상관 행렬을 시각적으로 표현하는 히트맵을 만들어볼 거예요. 히트맵은 상관관계를 색깔로 나타낸 그래프입니다.

4.1. 데이터 불러오기와 상관 행렬 계산

 
mtcars = pd.read_csv('../assets/mtcars.csv') p(mtcars.head())

mtcars.head()

  • head() 함수는 데이터의 처음 몇 줄을 보여줍니다. 데이터가 어떻게 생겼는지 확인할 수 있어요.
 
car_cor = mtcars.corr() car_cor = round(car_cor, 2) p(car_cor)

mtcars.corr()

  • 이 함수는 mtcars 데이터의 상관 행렬을 계산합니다. 여러 변수 간의 상관관계를 한 번에 확인할 수 있어요.
  • round(car_cor, 2)는 상관계수 값을 소수점 둘째 자리까지 반올림해 깔끔하게 보여주는 작업이에요.

4.2. 히트맵 그리기

이제 상관 행렬을 히트맵으로 시각화해보겠습니다.

 
import matplotlib.pyplot as plt import seaborn as sns
  • matplotlib.pyplot은 그래프를 그리기 위한 라이브러리이고, seaborn은 데이터를 더 쉽게 시각화할 수 있는 라이브러리예요.
 
plt.rcParams.update({ "figure.dpi": '120', # 해상도 설정 'figure.figsize': [7.5, 5.5], # 그래프 크기 설정 })

plt.rcParams.update()

  • 이 코드는 그래프의 설정을 바꿔요. 해상도(dpi)와 그래프의 크기(figsize)를 설정할 수 있어요.
 
sns.heatmap(car_cor, annot=True, cmap='RdBu') plt.show()

sns.heatmap()

  • heatmap() 함수는 상관 행렬을 시각적으로 표현하는 히트맵을 그려줍니다.
    • annot=True: 각 셀에 상관계수를 표시해줍니다.
    • cmap='RdBu': 히트맵의 색깔 맵을 빨강-파랑(Red-Blue)으로 설정합니다. 양의 상관관계는 파란색, 음의 상관관계는 빨간색으로 표현돼요.
  • plt.show()는 그래프를 화면에 표시합니다.

4.3. 대각선 행렬 제거하기

히트맵에서 대각선 부분은 변수와 자기 자신과의 상관관계라 의미가 없어요. 이를 제거해봅시다.

 
mask = np.zeros_like(car_cor) # 0으로 채운 행렬 생성 p(mask)

np.zeros_like()

  • 이 함수는 주어진 행렬(car_cor)과 같은 크기의 0으로 채워진 행렬을 만들어줍니다. 이 행렬을 mask라고 해요.
 
mask[np.triu_indices_from(mask)] = 1 p(mask)

np.triu_indices_from()

  • 이 함수는 행렬의 오른쪽 위 대각선 부분의 인덱스를 반환해줍니다.
  • 여기서는 mask 행렬의 오른쪽 위 대각선 부분을 1로 바꿔줘요. 이는 히트맵에서 그 부분을 표시하지 않도록 하기 위함이에요.
 
sns.heatmap(data=car_cor, annot=True, cmap='RdBu', mask=mask) plt.show()
  • mask=mask: 오른쪽 위 대각선 부분을 가리도록 mask를 적용해요. 이제 그 부분은 히트맵에서 표시되지 않아요.

4.4. 빈 행과 빈 열 제거하기

히트맵에서 첫 번째 행과 마지막 열을 제거한 새로운 히트맵을 만들 수 있어요.

 
mask_new = mask[1:, :-1] # 첫 행과 마지막 열 제거 cor_new = car_cor.iloc[1:, :-1]

mask[1:, :-1]

  • mask 행렬에서 첫 번째 행과 마지막 열을 제거합니다.
 
sns.heatmap(data=cor_new, annot=True, cmap='RdBu', mask=mask_new) plt.show()
  • 이 히트맵은 앞에서 만든 것과 비슷하지만, 첫 행과 마지막 열이 제거된 상태입니다.

4.5. 히트맵 세부 설정

마지막으로 히트맵을 더 세부적으로 설정할 수 있는 옵션을 추가해볼게요.

 
sns.heatmap( data=cor_new, # 상관 행렬 데이터 annot=True, # 상관계수 표시 cmap='RdBu', # 컬러맵 설정 mask=mask_new, # 대각선 마스크 설정 linewidths=0.5, # 셀 간 경계선 두께 vmax=1, # 파란색으로 표현할 최대값 vmin=-1, # 빨간색으로 표현할 최소값 cbar_kws={'shrink': 0.5} # 범례 크기 조정 ) plt.show()

세부 설정 설명

  • `linewidth

 

 

 

히트맵1
히트맵2,3 의 차이는 carb의 유무

  함수(매소드) 설명(역할)
1 equal_var = True 집단 간 분산이 같다고 가정
2 corr() 상관행렬을 생성
3 round(   , 2) 2번째 자리에서 반올림
4 annot=True 상관계수 표시하겠다는 이야기
5  scipy패키지의 ttest_ind() t_test를 확인할 수 있는 함수
6 query 데이터를 조건에 맞게 필터링해주는 함수입니다.