用Python玩转统计数据:取样、计算相关性、拆分训练模型和测试
導讀:本文會介紹一些技術,幫你更好地理解數據,以及探索特征之間的關系。
本文使用Python建立對數據的理解。我們會分析變量的分布,捋清特征之間的關系。最后,你會學習給樣本分層,并將數據集拆分成測試集與訓練集。
作者:托馬茲·卓巴斯(Tomasz Drabas)
如需轉載請聯系大數據(ID:hzdashuju)
01 生成描述性的統計數據
要完全理解任何隨機變量的分布,我們需要知道其平均數與標準差、最小值與最大值、中位數、四分位數、偏度和峰度。
1. 準備
要實踐本技巧,你只需裝好pandas模塊。此外沒有要求了。
2. 怎么做
下面的代碼可以快速達成對數據的初步理解。假設數據已從CSV文件讀出,并存于csv_read變量(data_describe.py文件)中:
[
'beds',?'baths',?'sq_tf',?'price',?'s_price',
'n_price',?'s_sq__ft',?'n_sq__ft',?'b_price',
'p_price',?'d_Condo',?'d_Multi-Family',
'd_Residential',?'d_Unkown'
]
].describe().transpose()
#?加上偏度,眾數與峰度
csv_desc['skew']?=?csv_read.skew(numeric_only=True)
csv_desc['mode']?=?csv_read.mode(numeric_only=True).transpose()
csv_desc['kurtosis']?=?csv_read.kurt(numeric_only=True)
3. 原理
pandas有個很管用的.describe()方法,它替我們做了大部分的工作。這個方法能生成我們想要的大部分描述變量;輸出看起來是這樣的(為清晰做了相應簡化):
count?981.000000
mean?2.914373
std?1.306502
min?0.000000
25%?2.000000
50%?3.000000
75%?4.000000
max?8.000000
DataFrame對象的索引標明了描述性統計數據的名字,每一列代表我們數據集中一個特定的變量。不過,我們還缺偏度、峰度和眾數。為了更方便地加入csv_desc變量,我們使用.transpose()移項了.describe()方法的輸出結果,使得變量放在索引里,每一列代表描述性的變量。
你也可以手動計算平均數、標準差及其他描述性的統計數據。可用的方法列表見:
http://pandas.pydata.org/pandas-docs/stable/api.html#api-dataframe-stats
有了基礎的統計數據,我們可以補上其他的。要留意的是,.skew(...)和.kurt(...)方法以類似的格式返回數據,而.mode(...)不然;.mode(...)方法返回的數據要進行調整,以便和.describe()方法的輸出格式保持一致。
4. 更多
描述性的統計數據也可用SciPy和NumPy計算得到。當然,比起pandas來不那么直觀(data_describe_alternative.py文件)。
首先加載兩個模塊。
import?bumpy?as?np
然后從CSV文件讀取數據:
csv_read?=?np.genfromtxt(
r_filenameCSV,
delimiter=',',
names=True,
#?只有數字列
usecols=[4,5,6,8,11,12,13,14,15,16,17,18,19,20]
)
.genfromtxt(...)方法以文件名作為第一個(也是唯一必需的)參數。指定分隔符是一個好做法;本例中分隔符是',',也可以是\t。names參數指定為True,意味著變量名存于第一行。最后,usecols參數指定文件中哪些列要存進csv_read對象。
最終可以計算出要求的數據:
.genfromtxt(...)方法創建的數據是一系列元組。.describe(...)方法只接受列表形式的數據,所以得先(使用列表表達式)將每個元組轉換成列表。
這個方法的輸出可以說對用戶不太友好:
5. 參考
查閱SciPy中的文檔,了解所有統計函數:
http://docs.scipy.org/doc/scipy/reference/stats.html#statistical-functions
02 探索特征之間的相關性
兩個變量之間的相關系數用來衡量它們之間的關系。系數為1,我們可以說這兩個變量完全相關;系數為-1,我們可以說第二個變量與第一個變量完全負相關;系數0意味著兩者之間不存在可度量的關系。
這里要強調一個基礎事實:不能因為兩個變量是相關的,就說兩者之間存在因果關系。
要了解更多,可訪問:
https://web.cn.edu/kwheeler/logic_causation.html
1. 準備
要實踐本技巧,你要先裝好pandas模塊。此外沒有要求了。
2. 怎么做
我們將測算公寓的臥室數目、浴室數目、樓板面積與價格之間的相關性。再一次,我們假設數據已經在csv_read對象中了。下面是代碼(data_correlations.py文件):
coefficients?=?['pearson',?'kendall',?'spearman']
csv_corr?=?{}
for?coefficient?in?coefficients:
csv_corr[coefficient]?=?csv_read.corr(method=coefficient).transpose()
3. 原理
pandas可用于計算三種相關度:皮爾遜積矩相關系數、肯達爾等級相關系數和斯皮爾曼等級相關系數。后兩者對于非正態分布的隨機變量并不是很敏感。
我們計算這三種相關系數,并且將結果存在csv_corr變量中。DataFrame對象csv_read調用了.corr(...)方法,唯一要指定的參數是要使用的計算方法。結果如下所示:
4. 參考
你也可以使用NumPy計算皮爾遜相關系數:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.corrcoef.html
03 數據取樣
有時候數據集過大,不方便建立模型。出于實用的考慮(不要讓模型的估計沒有個盡頭),最好從完整的數據集中取出一些分層樣本。
本文從MongoDB讀取數據,用Python取樣。
1. 準備
要實踐本技巧,你需要PyMongo、pandas和NumPy。其他沒有什么要準備的。
2. 怎么做
有兩種做法:確定一個抽樣的比例(比如說,20%),或者確定要取出的記錄條數。下面的代碼展示了如何提取一定比例的數據(data_sampling.py文件):
client?=?pymongo.MongoClient()
db?=?client['packt']
real_estate?=?db['real_estate']
#?讀取數據
sales?=?pd.DataFrame.from_dict(
list(?real_estate.find(
{'beds':?{'$in':?[2,?3,?4]}?},
{'_id':?0,?'zip':?1,?'city':?1,?'price':?1,?'beds':?1,?'sq__ft':?1}
)
)
)
#?取樣
sample?=?pd.DataFrame()
for?bed?in?[2,?3,?4]:
sample?=?sample.append(
sales[sales.beds?==?bed].sample(frac=strata_frac),
ignore_index=True
)
3. 原理
首先確定取樣的比例,即strata_frac變量。從MongoDB取出數據。MongoDB返回的是一個字典。pandas的.from_dict(...)方法生成一個DataFrame對象,這樣處理起來更方便。
要獲取數據集中的一個子集,pandas的.sample(...)方法是一個很方便的途徑。不過這里還是有一個陷阱:所有的觀測值被選出的概率相同,可能我們得到的樣本中,變量的分布并不能代表整個數據集。
在這個簡單的例子中,為了避免前面的陷阱,我們遍歷臥室數目的取值,用.sample(...)方法從這個子集中取出一個樣本。我們可以指定frac參數,以返回數據集子集(臥室數目)的一部分。
我們還使用了DataFrame的.append(...)方法:有一個DataFrame對象(例子中的sample),將另一個DataFrame附加到這一個已有的記錄后面。ignore_index參數設為True時,會忽略附加DataFrame的索引值,并沿用原有DataFrame的索引值。
4. 更多
有時,你會希望指定抽樣的數目,而不是占原數據集的比例。之前說過,pandas的 .sample(...)方法也能很好地處理這種場景(data_sampling_alternative.py文件)。
首先,我們指定要從原數據集中抽樣的記錄數目:
要保持不同臥室數目的取值比例與原數據集一致,我們首先計算每個桶中該放的記錄數:
strata_expected_counts?=?sales['beds'].value_counts()?/?ttl_cnt?*?strata_cnt
DataFrame的.count()方法會計算整個數據集中的總數目。然后,我們可以分別計算出各臥室數目下的比例,乘上strata_cnt變量,就得到了各自的記錄條數。.value_counts()方法返回的是指定列(例子中的beds)中,每個值的數目。然后將數據集中每條記錄除以ttl_cnt再乘以想要的樣本大小。
抽樣可以使用.sample(...)方法。不過,我們這次不指定frac參數了,而是指定要提取的記錄數n:
sample?=?sample.append(
sales[sales.beds?==?bed]?\
.sample(n=np.round(strata_expected_counts[bed])),
ignore_index=True
)
04 將數據集拆分成訓練集、交叉驗證集和測試集
要建立一個可信的統計模型,我們需要確信它精確地抽象出了我們要處理的現象。要獲得這個保證,我們需要測試模型。要保證精確度,我們訓練和測試不能用同樣的數據集。
本技法中,你會學到如何將你的數據集快速分成兩個子集:一個用來訓練模型,另一個用來測試。
1. 準備
要實踐本技巧,你需要pandas、SQLAlchemy和NumPy。其他沒有什么要準備的。
2. 怎么做
我們從PostgreSQL數據庫讀出數據,存到DataFrame里。通常我們劃出20%~40%的數據用于測試。本例中,我們選出1/3的數據(data_split.py文件):
test_size?=?0.33
#?輸出樣本的文件名
w_filenameTrain?=?'../../Data/Chapter02/realEstate_train.csv'
w_filenameTest?=?'../../Data/Chapter02/realEstate_test.csv'
#?用一個變量標記訓練樣本
data['train']?=?np.random.rand(len(data))?<?(1?-?test_size)
#?區分訓練集和測試集
train?=?data[data.train]
test?=?data[~data.train]
3. 原理
我們從指定劃分數據的比例與存儲數據的位置開始:兩個存放訓練集和測試集的文件。
我們希望隨機選擇測試數據。這里,我們使用NumPy的偽隨機數生成器。.rand(...)方法生成指定長度(len(data))的隨機數的列表。生成的隨機數在0和1之間。
接著我們將這些數字與要歸到訓練集的比例(1-test_size)進行比較:如果數字小于比例,我們就將記錄放在訓練集(train屬性的值為True)中;否則就放到測試集中(train屬性的值為False)。
最后兩行將數據集拆成訓練集和測試集。~是邏輯運算“否”的運算符;這樣,如果train屬性為False,那么“否”一下就成了True。
4. 更多
SciKit-learn提供了另一種拆分數據集的方法。我們先將原始的數據集分成兩塊,一塊是因變量y,一塊是自變量x:
x?=?data[['zip',?'beds',?'sq__ft']]
y?=?data['price']
然后就可以拆了:
x_train,?x_test,?y_train,?y_test?=?sk.train_test_split(
x,?y,?test_size=0.33,?random_state=42)
.train_test_split(...)方法幫我們將數據集拆成互補的子集:一個是訓練集,另一個是測試集。在每個種類中,我們有兩個數據集:一個包含因變量,另一個包含自變量。
延伸閱讀《數據分析實戰》
點擊上圖了解及購買
轉載請聯系微信:togo-maruko
推薦語:通過大量的現實案例,詳細講解數據分析相關的各種方法。
據統計,99%的大咖都完成了這個神操作
▼
更多精彩
在公眾號后臺對話框輸入以下關鍵詞
查看更多優質內容!
PPT?|?報告?|?讀書?|?書單
大數據?|?揭秘?|?人工智能?|?AI
Python?|?機器學習?|?深度學習?|?神經網絡
可視化?|?區塊鏈?|?干貨?|?數學
猜你想看
最全攻略:數據分析師必備Python編程基礎知識
王興:上天、入地、全球化,是互聯網下半場的三條路
輸在學歷的起跑線上?沒關系,10本書助你技能爆表升職加薪
2019升職加薪必備:你一定要修煉的產品思維
Q:?你還知道哪些處理數據的技巧?
歡迎留言與大家分享
覺得不錯,請把這篇文章分享給你的朋友
轉載 / 投稿請聯系:baiyu@hzbook.com
更多精彩,請在后臺點擊“歷史文章”查看
點擊閱讀原文,了解更多
總結
以上是生活随笔為你收集整理的用Python玩转统计数据:取样、计算相关性、拆分训练模型和测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何成为一名合格的数据科学家?这5个要点
- 下一篇: 写给中学生的算法入门:学代码之前看这篇就