例項講解統計學基礎知識(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})