1. 程式人生 > >例項講解統計學基礎知識(1):統計學基礎概念

例項講解統計學基礎知識(1):統計學基礎概念

下面將從具體的例項入手,用Python並結合統計學知識對資料進行探索分析,從而瞭解資料分析所用到的一些統計學概念。

前言

資料分析步驟

資料分析一般包括以下步驟:

  • 提出有價值的問題,好的問題就像是瞄準了正確的靶心,才能使後續的動作有意義。
  • 收集原始資料,資料來源可能是豐富多樣的,格式也可能不盡相同。
  • 清洗資料,理順雜亂的原始資料,並修正資料中的錯誤,這一步比較繁雜,但確是整個分析的基石。
  • 進行探索式分析,對整個資料集有個全面的認識,以便後續選擇何種分析策略。
  • 分析資料,這裡常常用到機器學習、資料探勘、深度學習等演算法。
  • 得出結論,視覺化結果,並使用報告、圖表等形式展現出來,與他人交流。

例項

  • 問題:當今美國社會中富人比一般人是更胖嗎?
  • 重要指標:家庭收入水平income,用來區分富人和普通人;BMI指數,其定義是體重(kg)除以身高(m)的平方,用於衡量胖瘦。

統計學基礎概念

總體VS樣本

總體是我們感興趣的目標的資料集。在我們關於“美國的富人會更胖嗎”這個問題下,總體是全部美國人的資料,顯然資料量非常龐大,難以全部獲取。那麼如何解決呢?於是就有了樣本,即在總體中取一子集,我們使用的BRFSS資料集就是一個樣本資料。可見總體往往是很大的,因為不可能完整獲取有時只是概念上的,所以我們常常需要採用樣本觀測到的資料來推測總體的性質。當然,在有了大規模分散式儲存和計算能力的今天,也許總體資料的取得也不再是難事了,這正是大資料的魅力所在。

引數VS統計量

用來描述總體特性的測量數稱為總體的引數,而用來描述樣本特性的測量數稱為樣本統計量。在我們的問題中,全體美國人BMI指數的平均值是引數,而BRFSS資料集中BMI指數的平均值則是統計量。統計學中時常使用樣本的統計量來對總體引數進行估計,在後續講到引數估計時我們會詳細展開。

因果性VS相關性

統計學中常說相關性並不意味著因果性,而生活中我們卻常常錯把相關性的關係當成因果關係。比如公雞總是在早上天亮的時候打鳴,那你能說是公雞打鳴導致了天亮嗎?

實驗VS調研

那麼在統計學中我們就得不到因果關係嗎?也不是的。一般的調研資料得到的都是相關性關係,比如我們後續會研究的BRFSS調研資料。要想得到因果關係的證明,需要設計非常嚴格的實驗才行。比如研究某項新葯對某個疾病是否有療效,就要設計一項統計學實驗,其中又需要了解如下概念:

控制組VS對照組

首先需要將實驗物件隨機分為兩組,控制組服用新葯,對照組不服用新葯。

獨立變數VS依賴變數

是否服用新葯是獨立變數(independent variables),而觀測到的服藥後的療效,是相應的依賴變數(dependent variables)。我們往往需要分析這兩者的關係,來判斷新葯是否有療效。

藥物VS安慰劑

對於實驗物件,也許他們因為心理上相信藥物有效而產生好轉的徵兆,為了避免這類心理上的影響,兩組實驗物件都需要服藥,只不過控制組服用的是真正需要測試的藥物,而對照組服用的是沒有效果的安慰劑而已。

雙盲實驗

不僅受試者會受到心理的干擾,實驗的觀察測量人員也會受到主觀偏見的影響。所以在實驗中,無論是實驗物件還是實驗人員,都不知道哪組是控制組,而哪組又是對照組,這被稱為雙盲實驗。

資料採集與清洗

原始資料是ASCII格式的壓縮包,需要採用pandas.read_fwf() 來讀取。清洗時不僅要正確提取所需變數,還需要對資料進行恰當轉換使之成為我們可以理解的量。下面將資料提取和清洗的程式碼存入brfss.py中。

import pandas as pd
import numpy as np

class FixedWidthVariables(object):
    """Represents a set of variables in a fixed width file."""

    def __init__(self, variables, index_base=0):
        """Initializes.
        variables: DataFrame
        index_base: are the indices 0 or 1 based?
        Attributes:
        colspecs: list of (start, end) index tuples
        names: list of string variable names
        """
        self.variables = variables

        # note: by default, subtract 1 from colspecs
        self.colspecs = variables[['start', 'end']] - index_base

        # convert colspecs to a list of pair of int
        self.colspecs = self.colspecs.astype(np.int).values.tolist()
        self.names = variables['name']

    def ReadFixedWidth(self, filename, **options):
        """Reads a fixed width ASCII file.
        filename: string filename
        returns: DataFrame
        """
        df = pd.read_fwf(filename,
                             colspecs=self.colspecs, 
                             names=self.names,
                             **options)
        return df



def ReadBrfss(filename='LLCP2015ASC.zip', compression='zip', nrows=None):
    """Reads the BRFSS data.
    filename: string
    compression: string
    nrows: int number of rows to read, or None for all
    returns: DataFrame
    """
    var_info = [
        ('sex', 120, 120, int),
        ('age', 1974, 1975, int),
        ('edu', 158, 158, int),
        ('marital', 157, 157, int),
        ('employ', 172, 172, int),
        ('income', 175, 176, int),        
        ('health', 90, 90, int),             
        ('bmi', 1988, 1991, int),
        ('height', 1980, 1982, int),
        ('weight', 1983, 1987, int),    
        ('exercise', 227, 227, int),
        ('workhour', 608, 609, int),
        ('exemin', 2119, 2123, int),
        ('fruit', 2050, 2050, int),
        ('vegetable', 2051, 2051,int),
    ]
    columns = ['name', 'start', 'end', 'type']
    variables = pd.DataFrame(var_info, columns=columns)
    variables.end += 1
    dct = FixedWidthVariables(variables, index_base=1)

    df = dct.ReadFixedWidth(filename, compression=compression, nrows=nrows)
    CleanBrfssFrame(df)
    return df


def CleanBrfssFrame(df):
    """Recodes BRFSS variables.
    df: DataFrame
    """
    # sex
    df.sex = df.sex.replace({1:'M', 2:'F'})

    # income
    df.income = df.income.replace({77:np.nan, 99:np.nan})

    # health
    df.health = df.health.replace({7:np.nan, 9:np.nan})

    # bmi
    df.bmi /= 100

    # height
    df.height /= 100

    # weight
    df.weight /= 100

    # exercise
    df.exercise = df.exercise.replace({1:True, 2:False, 7:np.nan, 9:np.nan})

    # workhour
    df.workhour = df.workhour.replace({97:np.nan, 98:0, 99:np.nan})

    # fruit
    df.fruit = df.fruit.replace({1:True, 2:False, 9:np.nan})

    # vegetable
    df.vegetable = df.vegetable.replace({1:True, 2:False, 9:np.nan})