07_Data_Analysis

11_탐색적 데이터 분석_국가별 음주 데이터 분석

chuu_travel 2025. 3. 19. 17:47
728x90
탐색적 데이터 분석
- 국가별 음주 데이터 분석

 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

drinks.csv

...

데이터 파악

drinks = pd.read_csv("./data/drinks.csv")
drinks.head()

 

 

drinks.shape
(193, 6)

 

drinks.dtypes
country                          object
beer_servings                     int64
spirit_servings                   int64
wine_servings                     int64
total_litres_of_pure_alcohol    float64
continent                        object
dtype: object

 

 

drinks.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 193 entries, 0 to 192
Data columns (total 6 columns):
 #   Column                        Non-Null Count  Dtype  
---  ------                        --------------  -----  
 0   country                       193 non-null    object 
 1   beer_servings                 193 non-null    int64  
 2   spirit_servings               193 non-null    int64  
 3   wine_servings                 193 non-null    int64  
 4   total_litres_of_pure_alcohol  193 non-null    float64
 5   continent                     170 non-null    object 
dtypes: float64(1), int64(3), object(2)
memory usage: 9.2+ KB

 

drinks.describe()

 

  • 피처
    • country: 국가 정보
    • beer/spirit/wine servings : beer/spirit/wine 소비량
    • total_litres_of_pure_alcohol : 총 알코올 소비량
    • continent: 국가의 대륙 정보

 

데이터 속성 탐색

  • 상관 분석
    • 두 변수 간의 선형적 관계를 상관 계수로 표현하는 것(상관계수가 0.3~0.7사이의 값이면 관계가 있다고 볼 수 있음)
    • 상관계수는 공분산의 개념을 포함함
      • 공분산
        • 2개의 확률변수에 대한 상관 정도
        • 2개의 변수 중 하나의 값이 상승하는 경향을 보일 때 다른 값도 상승하는 경향을 수치로 나타낸 것
        • 공분산 만으로 상관관계를 구한다면 두 변수의 단위 크기에 영향을 받음
          • 큰 단위의 데이터라면 공분산이 커짐
    • 따라서 상관계수는 공분산을 -1과 1사이의 값으로 변환한 것
  • 상관관계를 통계적으로 탐색하는 방법
    • 단순 상관 분석: 피처가 2개일 때의 상관 계수를 계산
    • 다중 상관 분석: 피처가 여러개 일 때 상호간의 연관성 분석

 

beer_servings, wine_servings 의 상관 계수 구하기

drinks[["beer_servings", "wine_servings"]].corr() # corr()로 상관계수를 구할 수 있다

 

 

다중 상관 분석

drinks.columns
Index(['country', 'beer_servings', 'spirit_servings', 'wine_servings',
       'total_litres_of_pure_alcohol', 'continent'],
      dtype='object')

 

cor_cols = drinks.columns[1:5]
cor_cols
Index(['beer_servings', 'spirit_servings', 'wine_servings',
       'total_litres_of_pure_alcohol'],
      dtype='object')

 

drinks_corr = drinks[cor_cols].corr()
drinks_corr

 

 

heatmap 시각화

# 그래프 출력을 위해 컬럼명 축약
cols_label = ["beer", "spirit", "wine", "alcohol"]

sns.heatmap(drinks_corr.values, cbar = True, annot = True, square = True, fmt = ".2f",
            annot_kws = {"size" : 15}, yticklabels = cols_label, xticklabels = cols_label,
            cmap = "Oranges")

plt.show()

 

 

산점도 시각화

sns.pairplot(drinks[cor_cols])
plt.show()

 

  • total_litres_of_pure_alcohol 피처가 대체적으로 다른 모든 피처와 강한 상관관계가 있는 것으로 보임
  • 특히 beer_servings 와의 상관성이 가장 높음

 

 

데이터 전처리

continent 결측치 대체

drinks.isna().sum()
country                          0
beer_servings                    0
spirit_servings                  0
wine_servings                    0
total_litres_of_pure_alcohol     0
continent                       23
dtype: int64

 

drinks["continent"].unique()
array(['AS', 'EU', 'AF', nan, 'SA', 'OC'], dtype=object)
drinks[drinks["continent"] == "SA"] # South America가 있는데 North America가 없음

 

 

drinks[drinks["continent"].isna()]

 

 

drinks["continent"] = drinks["continent"].fillna("NA")
drinks["continent"].value_counts()
continent
AF    53
EU    45
AS    44
NA    23
OC    16
SA    12
Name: count, dtype: int64

 

 

데이터 탐색

 

각 대륙별 비율 확인

continents = drinks["continent"].value_counts()
plt.pie(continents.values, labels = continents.index, autopct = "%.0f%%", shadow = True)
plt.show()

 

 

대륙별 spirit_servings의 통계 정보 확인

# 대륙별 spirit_servings의 평균, 최소, 최대, 합계 확인
stat = drinks.groupby("continent")["spirit_servings"].agg(["mean", "min", "max", "sum"])
stat

 

# seaborn의 색감 설정
sns.set(style = "whitegrid")
n_groups = len(stat)
idx = np.arange(n_groups)

rects1 = plt.bar(idx, stat["mean"], width = 0.1, color = "r", label = "Mean")
rects2 = plt.bar(idx + 0.1 , stat["min"], width = 0.1, color = "g", label = "Min")
rects3 = plt.bar(idx + 0.2 , stat["max"], width = 0.1, color = "b", label = "Max")
rects4 = plt.bar(idx + 0.3 , stat["sum"], width = 0.1, color = "y", label = "Sum")

plt.xticks(idx, stat.index)
plt.legend()
plt.show()

 

 

 

전체 평균보다 더 많은 알코올을 섭취하는 대륙

alc_mean = drinks["total_litres_of_pure_alcohol"].mean()
alc_mean
4.717098445595855
con_mean = drinks.groupby("continent")["total_litres_of_pure_alcohol"].mean()
con_mean
continent
AF    3.007547
AS    2.170455
EU    8.617778
NA    5.995652
OC    3.381250
SA    6.308333
Name: total_litres_of_pure_alcohol, dtype: float64

 

con_mean[con_mean > alc_mean]
continent
EU    8.617778
NA    5.995652
SA    6.308333
Name: total_litres_of_pure_alcohol, dtype: float64

 

# 전체 평균도 시각화해주기 위해서 대륙 리스트에 mean 추가
continents = con_mean.index.tolist()
continents.append("mean")

alc = con_mean.tolist()
alc.append(alc_mean)

# x_pos = np.arange(len(con_mean))
x_pos = np.arange(len(continents))

# plt.bar(x_pos, con_mean, alpha = 0.5)
bar_list = plt.bar(x_pos, alc, alpha = 0.5)

# 마지막 바 만 빨간색으로 변경
bar_list[-1].set_color("r")

# 평균선 그리기
plt.plot([0, len(continents) - 1], [alc_mean, alc_mean], "k--")

# plt.xticks(x_pos, con_mean.index)
plt.xticks(x_pos, continents)
plt.show()

 

continents
['AF', 'AS', 'EU', 'NA', 'OC', 'SA', 'mean']

 

con_mean.tolist()
[3.0075471698113208,
 2.1704545454545454,
 8.617777777777778,
 5.995652173913044,
 3.38125,
 6.308333333333334]

 

 

평균 beer_servings가 가장 높은 대륙

drinks.groupby("continent")["beer_servings"].mean()
continent
AF     61.471698
AS     37.045455
EU    193.777778
NA    145.434783
OC     89.687500
SA    175.083333
Name: beer_servings, dtype: float64
# 최댓값의 인덱스
drinks.groupby("continent")["beer_servings"].mean().idxmax()
'EU'

 

group_beer = drinks.groupby("continent")["beer_servings"].sum()
group_beer
continent
AF    3258
AS    1630
EU    8720
NA    3345
OC    1435
SA    2101
Name: beer_servings, dtype: int64

 

continents.index("EU")
2

 

 

continents = group_beer.index.tolist()
x_pos = np.arange(len(group_beer))

bar_list = plt.bar(x_pos, group_beer, alpha = 0.5)
bar_list[continents.index("EU")].set_color("r")

plt.xticks(x_pos, continents)
plt.show()

 

 

통계 분석

  • 지금까지의 분석은 통찰을 발견하는 데 있어서는 유용했지만 분석가의 주관에 따라 분석된 내용이기 때문에 타당성을 입증하기 어려움
  • 타당성을 위해서는 통계적으로 검정하는 과정이 필요
  • t검정(t-test)
    • 두 집단 간 평균의 차이에 대한 검정
    • 모집단의 평균을 모를 때 현재의 데이터만으로 두 집단의 차이에 대해 검정할 수 있음
    • 단, 두 집단의 데이터 개수가 비슷하고, 정규 분포인 경우에 신뢰도가 높음
  1. 정규성 검정
  2. 등분산성 검정(데이터가 퍼져있는 정도가 두 집단이 같은가)
  3. T-test

 

 

아프리카와 유럽 간의 맥주 소비량 차이 검정

# 파이썬에서 통계를 쓸 때 scipy를 많이 씀
from scipy import stats
af = drinks[drinks["continent"] == "AF"]
eu = drinks[drinks["continent"] == "EU"]
# 정규성 검정
af_shapiro = stats.shapiro(af["beer_servings"])
eu_shapiro = stats.shapiro(eu["beer_servings"])
print(af_shapiro)
print(eu_shapiro)
ShapiroResult(statistic=0.6982116200099862, pvalue=3.84314570688321e-09)
ShapiroResult(statistic=0.9592717067348022, pvalue=0.1145794783307496)
# 등분산성 검정
levene_result = stats.levene(af["beer_servings"], eu["beer_servings"])
levene_result
LeveneResult(statistic=6.015144059118397, pvalue=0.015989187968374834)
# H0 : 정규성 만족, 등분산성 만족
# H1 : 정규성 만족X, 등분산성 만족X
# t-test
t_result = stats.ttest_ind(af["beer_servings"], eu["beer_servings"], equal_var = False)
t_result
TtestResult(statistic=-7.143520192189803, pvalue=2.9837787864303205e-10, df=84.40013075489844)

 

  • statistic(t-test의 검정 통계량) : 절댓값이 클수록 두 집단간의 평균이 크다
    • 그 자체로는 아무 의미 없으며 p-value 와 함께 해석해야함
    • 귀무가설과의 차이를 뜻함
  • p-value(유의확률)
    • 가설이 얼마나 믿을만 한 것인지를 나타내는 지표
    • 데이터를 새로 샘플링했을 때 귀무 가설이 맞다는 전제 하에 현재 나온 통계값 이상이 나올 확률
      • 즉, p-value가 낮으면 귀무 가설이 일어날 확률이 낮기 때문에 귀무 가설을 기각하게 됨
        • 보통 그 기준은 0.05나 0.01을 기준으로 함
  • 귀무가설
    • 처음부터 버릴 것을 예상하는 가설
    • 가설이 맞지 않다는 것을 증명하기 위해 수립하는 가설
    • 반대되는 가설을 대립 가설이라고 부르며, 귀무 가설이 거짓인 경우에 대안으로 참이 되는 가설임

 

분석 내용

  • t-test 의 귀무가설 : "두 집단의 평균이 같다"
  • p-value가 0.01이하로 나타나 귀무 가설이 기각되었음
  • 따라서 "아프리카와 유럽 대륙 간의 맥주 소비량 차이"는 통계적으로 매우 유의미하다
    • 두 집단의 평균은 다르다
728x90

'07_Data_Analysis' 카테고리의 다른 글

13_T-Test  (0) 2025.03.19
12_T-Test, ANOVA 개요  (0) 2025.03.19
10_탐색적 데이터 분석  (0) 2025.03.19
09_데이터 분석의 이해  (4) 2025.03.17
08_분포 시각화  (0) 2025.03.17