#!/usr/bin/env python
# coding: utf-8

# 통계적 사고 (2판) 연습문제 ([thinkstats2.com](thinkstats2.com), [think-stat.xwmooc.org](http://think-stat.xwmooc.org))<br>
# Allen Downey / 이광춘(xwMOOC)

# In[1]:


get_ipython().run_line_magic('matplotlib', 'inline')
from __future__ import print_function, division

import numpy as np
import random

import first
import normal
import thinkstats2
import thinkplot


# ## 연습문제 14.1
# 
# 5.4 절에서, 성인 체중분포는 근사적으로 로그정규분포임을 알아냈다.
# 한가지 가능한 설명은 매년 성인이 느는 체중은 현재 체중에 비례한다는 것이다.
# 이런 경우, 성인 체중은 많은 숫자의 복잡한 요인의 곱이 된다:
# 
# 
# $ w = w_0 f_1 f_2 ... f_n$
# 
# 
# 여기서, $w$는 성인체중, $w_0$는 출생체중,
# $f_i$는 $i$ 년도에 대한 체중 증가 요인이다.
# 
# 
# 곱에 대해 로그를 취하면, 요인에 로그를 취한 합으로 바뀐다:
# 
# $log w = log w_0 + log f_1 + log f_2 + ... + log f_n$
# 
# 
# 그래서, 중심극한정리에 의해서, 
# $\log w$의 분포는 근사적으로 큰 $n$에 대해 근사적으로 정규분포가 된다.
# 이는 $w$의 분포가 로그정규분포라는 것을 함의를 갖는다.
# 
# 이런 현상을 모형화하는데, $f$에 대한 일리있어 보이는 분포를 고르고 나서,
# 출생체중 분포로 부터 난수를 고르고, $f$ 분포로부터 요인 시퀀스를 고르고,
# 곱을 계산함으로써 성인체중 표본을 생성한다.
# 로그정규 분포로 수렴하는데 $n$ 값이 얼마나 필요할까?
# 

# In[3]:


def GenerateAdultWeight(birth_weights, n):
    """Generate a random adult weight by simulating annual gain.

    birth_weights: sequence of birth weights in lbs
    n: number of years to simulate

    returns: adult weight in lbs
    """
    bw = random.choice(birth_weights)
    factors = np.random.normal(1.09, 0.03, n)
    aw = bw * np.prod(factors)
    return aw


def PlotAdultWeights(live):
    """Makes a normal probability plot of log10 adult weight.

    live: DataFrame of live births

    """
    birth_weights = live.totalwgt_lb.dropna().values
    aws = [GenerateAdultWeight(birth_weights, 40) for _ in range(1000)]
    log_aws = np.log10(aws)
    thinkstats2.NormalProbabilityPlot(log_aws)
    thinkplot.Show(xlabel='standard normal values',
                   ylabel='adult weight (log10 lbs)')

thinkstats2.RandomSeed(17)


live, firsts, others = first.MakeFrames()
PlotAdultWeights(live)


# $n=40$ 표본을 갖는 분포가 가장 작은 체중에 대해서 제외하고 근사적으로 로그정규분포를 따른다.
# 
# 실제 분포는 로그정규분포에서 벗어나는데 이유는 다른 연령에 사람과 섞여있고, 매년 증가하는 체중에 상관관계가 있기 때문이다.

# ## 연습문제 14.2 
# 
# 14.6절에서, 중심극한정리를 사용해서 
# 동일 모집단에서 양쪽 표본이 추출되었다는 귀무가설 아래,
# 평균간에 차이, $\delta$, 표집분포를 알아냈다.
# 
# 이 분포를 사용해서 추정값 표준오차와 신뢰구간도 알아낼 수 있다.
# 하지만, 이 방식은 근사적으로 맞다.
# 좀더 정확성을 기하기 위해서, 표본이 다른 모집단에서 추출되었다는
# 대립가설 아래 $\delta$ 표집분포를 계산해야 된다.
# 
# 이 분포를 계산하고, 이를 사용해서 평균 사이 차이에 대한 
# 표준오차와 90% 신뢰구간을 계산하시오.

# In[4]:


def PlotPregLengths(live, firsts, others):
    """Plots sampling distributions under the null and alternate hypotheses.
    live, firsts, others: DataFrames
    """
    print('prglngth example')
    delta = firsts.prglngth.mean() - others.prglngth.mean()
    print(delta)

    dist1 = normal.SamplingDistMean(live.prglngth, len(firsts))
    dist2 = normal.SamplingDistMean(live.prglngth, len(others))
    dist = dist1 - dist2
    print('null hypothesis', dist)
    print(dist.Prob(-delta), 1 - dist.Prob(delta))

    thinkplot.PrePlot(2)
    thinkplot.Plot(dist, label='null hypothesis')

    dist1 = normal.SamplingDistMean(firsts.prglngth, len(firsts))
    dist2 = normal.SamplingDistMean(others.prglngth, len(others))
    dist = dist1 - dist2
    print('estimated params', dist)
    print(dist.Percentile(5), dist.Percentile(95))

    thinkplot.Plot(dist, label='estimated params')
    thinkplot.Show(xlabel='difference in means (weeks)',
                   ylabel='CDF')

PlotPregLengths(live, firsts, others)    


# 귀무가설 아래 표집분포가 0을 중심으로 모여있다.
# 
# 귀무가설아래 표집분포가 관측차이 0.078을 갖고 모여있다.
# 
# 두 분포의 분산은 매우 유사하다.

# ## 연습문제 14.3 
# 최신 논문에서, 스타인과 동료들은 학생공학팀 안에서 성별 고정관념에 따른 작업 배정을 완화하려는 의도로 개입 효과를 조사했다.
# 
# 개입 전과 후에 대해서, 학생들이 7점 척도로 학급 프로젝트 각 측면에 대한 기여도를 
# 평가하는 설문에 응답했다.
# 
# 개입 전에는, 남자 학생이 여자 학생보다 프로젝트의 프로그래밍 측면에 대해서
# 더 높은 점수를 보고했다; 평균적으로 남자가 0.28 표준오차를 갖는 3.57
# 점수를 보고했다. 여자는 평균적으로 0.32 표준오차를 갖는 1.91을 보고했다.
# 
# 성별 격차(평균에 있어 차이)에 대한 표집분포를 계산하고,
# 통계적으로 유의적인지 검정하라.
# 추정한 평균에 대한 표준오차만 주어졌기 때문에,
# 표집분포를 식별하는데 표본크기를 알 필요는 없다.
# 
# 개입후에, 성별격차가 더 적어졌다:
# 남자에 대한 평균점수는 3.44 (표준오차 0.16); 여자에 대한 평균점수 3.18 (표준오차 0.16).
# 다시, 성별격차에 대한 표집분포를 계산하고 검정하라.
# 
# 마지막으로 성별격차에 변화를 추정하라; 이 변화에 대한 표집분포는 무엇이고,
# 통계적으로 유의적인가?

# In[6]:


def TestIntervention():
    """Tests whether reported changes are statistically significant.
    """
    male_before = normal.Normal(3.57, 0.28**2)
    male_after = normal.Normal(3.44, 0.16**2)

    female_before = normal.Normal(1.91, 0.32**2)
    female_after = normal.Normal(3.18, 0.16**2)

    diff_before = female_before - male_before
    print('mean, p-value', diff_before.mu, 1-diff_before.Prob(0))
    print('CI', diff_before.Percentile(5), diff_before.Percentile(95))
    print('stderr', diff_before.sigma)

    diff_after = female_after - male_after
    print('mean, p-value', diff_after.mu, 1-diff_after.Prob(0))
    print('CI', diff_after.Percentile(5), diff_after.Percentile(95))
    print('stderr', diff_after.sigma)

    diff = diff_after - diff_before
    print('mean, p-value', diff.mu, diff.Prob(0))
    print('CI', diff.Percentile(5), diff.Percentile(95))
    print('stderr', diff.sigma)

TestIntervention()


# 1. 개입전 성별격차는 1.66 점 (p-값 5e-5)
# 1. 개입후 성별격차는 0.26 점 (p-값 유의적이지 않음)
# 1. 성별격차에 변화 1.4점 (p-값 0.002 유의적)

# In[ ]: