Hard skills/Python (32)

데이터 분석 대회 Kaggle에 나왔던 타이타닉 데이터로 로지스틱 회귀분석 연습을 해보았습니다. 데이터를 통해 성별, 나이, 객실 등급이 승객의 생존에 어떤 영향을 끼쳤는지 분석해 볼 수 있습니다.



알아보고 싶은 것은 "성별(Sex), 나이(Age), 객실등급(Pclass), 요금?(Fare) 가 생존에 어떻게 어느정도의 영향을 미쳤는가?" 입니다.


=============================================================================================

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 
# 2015. 8. 5 
 
import pandas as pd
import statsmodels.api as sm
import pylab as pl
import numpy as np
import test2
 
df = pd.read_csv("c:/train2.csv"# read file
 
print df.head()
 
cols_to_keep = ['Survived''Age''Fare'# 분류할 수 없는 컬럼들
 
# 분류할 수 있는 컬럼들은 더미 컬럼를 만든다.
dummy_Pclass = pd.get_dummies(df['Pclass'], prefix='Pclass')
dummy_Sex = pd.get_dummies(df['Sex'], prefix='Sex')
 
# 더미를 데이터에 이어 붙인다.
data = df[cols_to_keep].join(dummy_Pclass.ix[:,'Pclass_2':]) # Pclass_2 부터 이어 붙임. 이래야 분석에 편리함
data = data.join(dummy_Sex.ix[:,'Sex_male':]) # Sex_male만 이어 붙임
 
data['intercept'= 1.0
 
# 지금까지의 데이터 확인
print data.head()
 
 
# 출력창에 다음과 같이 뜸
#   Survived  Age     Fare  Pclass_2  Pclass_3  Sex_male  intercept
#0         0   22   7.2500         0         1         1          1
#1         1   38  71.2833         0         0         0          1
#2         1   26   7.9250         0         1         0          1
#3         1   35  53.1000         0         0         0          1
#4         0   35   8.0500         0         1         1          1
 
 
# logistic regression
train_cols = data.columns[1:] # train_cols는 설명 변수
logit = sm.Logit(data['Survived'], data[train_cols]) # Survived는 목적 변수
 
# fit the model
result = logit.fit() 
 
print result.summary() # 분석결과 출력
 
#==============================================================================
#                 coef    std err          z      P>|z|      [95.0% Conf. Int.]
#------------------------------------------------------------------------------
#Age           -0.0330      0.007     -4.457      0.000        -0.048    -0.019
#Fare           0.0007      0.002      0.340      0.734        -0.003     0.005
#Pclass_2      -1.0809      0.286     -3.778      0.000        -1.642    -0.520
#Pclass_3      -2.2794      0.280     -8.142      0.000        -2.828    -1.731
#Sex_male      -2.6049      0.188    -13.881      0.000        -2.973    -2.237
#intercept      3.4772      0.418      8.318      0.000         2.658     4.297
#==============================================================================
 
# odds ratios only
print np.exp(result.params) # 오즈 비(Odds Ratio) 출력
 
#Age           0.967515
#Fare          1.000714
#Pclass_2      0.339281
#Pclass_3      0.102351
#Sex_male      0.073911
#intercept    32.367967
 
data["predict"= result.predict(data[train_cols])
print data.head()
 
# 최종결과 (predict가 생존확률)
#   Survived  Age     Fare  Pclass_2  Pclass_3  Sex_male  intercept   predict
#0         0   22   7.2500         0         1         1          1  0.106363
#1         1   38  71.2833         0         0         0          1  0.906625
#2         1   26   7.9250         0         1         0          1  0.585365
#3         1   35  53.1000         0         0         0          1  0.913663
#4         0   35   8.0500         0         1         1          1  0.071945
cs




분석 결과 정리


coef(편회귀계수)의 부호만을 봤을 때, 나이가 많을 수록, 여자보다는 남자일 수록, 1등급보다는 2등급, 3등급일 수록, 요금이 적을 수록 생존확률이 낮아졌다. 또한 coef의 절대값으로 미루어보면 성별이 생존여부에 가장 큰 영향을 미치는 것을 알 수 있었다.



용어


Odds Ratio 

Odds Ratio란 Odds의 비율이다. Odds란 성공/실패와 같이 상호 배타적이며 전체를 이루고 있는 것들의 비율을 의미한다. 예를 들어 남자 승객의 경우 577명중 109명이 생존했다. 이 경우 Odds = P(생존)/P(사망) = (109/577)/(468/577) = 0.19/0.81 = 0.23

여자 승객의 경우 314명중 233명이 생존했다. 이 경우 Odds = P(생존)/P(사망) = (233/314)/(81/314) = 2.87

따라서 Odds Ratio = 0.23/2.87 = 약 0.08


http://blog.yhathq.com/posts/logistic-regression-and-python.html


알고 싶은 것 : GPA, GRE, 모교 우선순위(prestige) 가 대학원 입학 여부에 어떻게 영향을 미치는가?

---------------------------------------------------------------------------------------------------------------------------

위의 블로그의 내용을 요약한 글입니다. 정리한 글은 위의 블로그에 더욱 자세하게 설명되어 있습니다.
환경 : python 2.7, eclipse pydev

1. 데이터 읽기
 
1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
import statsmodels.api as sm
import pylab as pl
import numpy as np
 
 
print df.head()
 
df.columns = ["admit""gre""gpa""prestige"# df의 column 이름 바꾸기
print df.columns
 
cs


2. 데이터 요약하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
print df.describe() # 빈도수, 평균, 분산, 최솟값, 최댓값, 1/4분위수, 중위값, 1/4분위수를 나타냄
 
#             admit         gre         gpa   prestige
# count  400.000000  400.000000  400.000000  400.00000
# mean     0.317500  587.700000    3.389900    2.48500
# std      0.466087  115.516536    0.380567    0.94446
# min      0.000000  220.000000    2.260000    1.00000
# 25%      0.000000  520.000000    3.130000    2.00000
# 50%      0.000000  580.000000    3.395000    2.00000
# 75%      1.000000  660.000000    3.670000    3.00000
# max      1.000000  800.000000    4.000000    4.00000
 
print df.std() # 분산 출력
 
# admit      0.466087
# gre      115.516536
# gpa        0.380567
# prestige   0.944460
 
print pd.crosstab(df['admit'], df['prestige'], rownames=['admit'])
 
# prestige   1   2   3   4
# admit                   
# 0         28  97  93  55
# 1         33  54  28  12
 
df.hist()
pl.show() # pl.show()를 해야 화면에 띄워준다! 결과는 아래와 같다. 모든 컬럼에 대해 히스토그램을 그림
cs

3. 더미변수로 고치기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
dummy_ranks = pd.get_dummies(df['prestige'], prefix='prestige')
print dummy_ranks.head()
 
#    prestige_1  prestige_2  prestige_3  prestige_4
# 0           0           0           1           0
# 1           0           0           1           0
# 2           1           0           0           0
# 3           0           0           0           1
# 4           0           0           0           1
 
cols_to_keep = ['admit''gre''gpa']
data = df[cols_to_keep].join(dummy_ranks.ix[:, 'prestige_2':])
print data.head()
#    admit  gre   gpa  prestige_2  prestige_3  prestige_4
# 0      0  380  3.61           0           1           0
# 1      1  660  3.67           0           1           0
# 2      1  800  4.00           0           0           0
# 3      1  640  3.19           0           0           1
# 4      0  520  2.93           0           0           1
 
data['intercept'= 1.0
 
cs

4. 회귀분석을 시행한다.

1
2
3
4
5
6
train_cols = data.columns[1:]
logit = sm.Logit(data['admit'], data[train_cols])
result = logit.fit()
print result.summary()
 
 
cs
              Logit Regression Results                           
          ==============================================================================
          Dep. Variable:                  admit   No. Observations:                  400
          Model:                          Logit   Df Residuals:                      394
          Method:                           MLE   Df Model:                            5
          Date:                Sun, 03 Mar 2013   Pseudo R-squ.:                 0.08292
          Time:                        12:34:59   Log-Likelihood:                -229.26
          converged:                       True   LL-Null:                       -249.99
                                                  LLR p-value:                 7.578e-08
          ==============================================================================
                           coef    std err          z      P>|z|      [95.0% Conf. Int.]
          ------------------------------------------------------------------------------
          gre            0.0023      0.001      2.070      0.038         0.000     0.004
          gpa            0.8040      0.332      2.423      0.015         0.154     1.454
          prestige_2    -0.6754      0.316     -2.134      0.033        -1.296    -0.055
          prestige_3    -1.3402      0.345     -3.881      0.000        -2.017    -0.663
          prestige_4    -1.5515      0.418     -3.713      0.000        -2.370    -0.733
          intercept     -3.9900      1.140     -3.500      0.000        -6.224    -1.756
          ==============================================================================

coef에 주목한다. gre:0.0023 gpa :0.840, prestige_2 : -0.6754 등등...
coef(편회귀계수)의 값이 양수이면 그 컬럼의 값이 커질수록 목적변수가 TRUE일 확률 즉, admit=1일 확률이 높아진다.
반대로 coef의 값이 음수이면 그 컬럼의 값이 커질수록 목적변수가 FALSE일 확률 즉, admin=0일 확률이 높아진다.

즉 GRE나 GPA가 커질수록 대학원에 입학할 확률은 커지고 prestige_2, prestige_3이 커질수록 대학원에 입학할 확률은 작아진다. 
이러한 경향은 pretige가 낮아질수록 심해진다.


5. odds ratio

1
2
3
4
5
6
7
print np.exp(result.params)
# gre 1.002267
# gpa 2.234545
# prestige_2 0.508931
# prestige_3 0.261792
# prestige_4 0.211938
# intercept 0.018500
cs