干货:4个小技巧助你搞定缺失、混乱的数据(附实例代码)
導讀:數據工作者經常會遇到各種狀況,比如你收集到的數據并不像你期待的那樣完整、干凈。此前我們講解了用OpenRefine搞定數據清洗,本文進一步探討用pandas和NumPy插補缺失數據并將數據規范化、標準化。
?
作者:托馬茲·卓巴斯(Tomasz Drabas)
如需轉載請聯系大數據(ID:hzdashuju)
?
本文將使用一個數據集,包含985項真實的房產交易。這些交易是連續5天內在Sacramento發生的。數據下載自:
?
http://samplecsvs.s3.amazonaws.com/Sacramentorealestatetransactions.csv
?
數據已轉成多種格式,放在GitHub代碼庫的Data/Chapter01文件夾中。
?
https://github.com/drabastomek/practicalDataAnalysisCookbook.git
?
?
01 插補缺失值
?
數據的收集工作很棘手。收集工具壞了,調查問卷上某些問題人們不想回答,或者文件被損壞了;這些還只是數據集可能不全的一小部分原因。如果想使用這個數據集,我們有兩個選擇:忽略缺失的數據,或者用一些值替代。
?
1. 準備
?
要實踐本技巧,你要先裝好pandas模塊。
?
2. 怎么做
?
csv_read DataFrame可供使用。要插補缺失值,你只需要使用下面的代碼(data_imput.py文件):
?
#?估算平均數以替代空值
csv_read['price_mean']?=?csv_read['price']?\
.fillna(
csv_read.groupby('zip')['price'].transform('mean')
)
?
3. 原理
?
pandas的.fillna(...)方法幫我們處理了所有重活。這是DataFrame對象的一個方法,將要估算的值作為唯一必須傳入的參數。
?
查閱pandas文檔中.fillna(...)的部分,了解可傳入的其他參數。文檔位于:
?
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.fillna.html
?
在我們的處理過程中,我們假設每個郵編可能會有不同的均價。這就是我們用.groupby(...)方法對數據分組的原因。房產的價格重度依賴于房間的數目,這個推論也是成立的;如果我們的數據集更大,我們還能考慮beds這個變量。
?
.groupby(...)方法返回一個GroupBy對象。其.transform(...)方法高效地對郵編分組,在我們的例子中,分組的依據是各郵編價格數據的平均數。
?
現在,.fillna(...)方法簡單地用這個平均數替代缺失的觀測數據即可。
?
4. 更多
?
插補數據不是填補缺失值的唯一方法。數據對稱分布且沒有異常值時,才會返回一個合理的值;如果分布比較偏,平均值是有偏差的。衡量集中趨勢更好的維度是中位數。我們前面的例子只需要改一個小地方:
?
#?估算中位數以替代空值
csv_read['price_median']?=?csv_read['price']?\
.fillna(
csv_read.groupby('zip')['price'].transform('median')
)
?
?
02 將特征規范化、標準化
?
為了提高計算效率,我們將特征規范化(或標準化),這樣不會超出計算機的限制。探索模型中變量之間的相互作用時也建議這么處理。
?
計算機是有限制的:整型值是有上限的(盡管目前在64位機器上這不是個問題),浮點型的精確度也有上限。
?
數據規范化是讓所有的值落在0到1的范圍內(閉區間)。數據標準化是移動其分布,使得數據的平均數是0、標準差是1。
?
1. 準備
?
要實踐本技巧,你要先裝好pandas模塊。
?
其他沒有什么要準備的了。
?
2. 怎么做
?
要實現規范化與標準化,我們定義了兩個輔助函數(data_standardize.py文件):
?
def?normalize(col):
'''
規范化
'''
return?(col?-?col.min())?/?(col.max()?-?col.min())
def?standardize(col):
'''
標準化
'''
return?(col?-?col.mean())?/?col.std()
?
3. 原理
?
要規范化數據,即讓每個值都落在0和1之間,我們減去數據的最小值,并除以樣本的范圍。統計學上的范圍指的是最大值與最小值的差。normalize(...)方法就是做的前面描述的工作:對數據的集合,減去最小值,除以范圍。
?
標準化的過程類似:減去平均數,除以樣本的標準差。這樣,處理后的數據,平均數為0而標準差為1。standardize(...)方法做了這些處理:
?
csv_read['n_price_mean']?=?normalize(csv_read['price_mean'])
csv_read['s_price_mean']?=?standardize(csv_read['price_mean'])
?
?
03 分級數據
?
當我們想查看數據分布的形狀,或將數據轉換為有序的形式時,數據分級就派上用場了。
?
1. 準備
?
要實踐本技巧,你要先裝好pandas和NumPy模塊。
?
2. 怎么做
?
可以用下面的代碼(data_binning.py文件)對數據分級(比如處理成直方圖):
?
#?根據線性劃分的價格的范圍,創建價格的容器
bins?=?np.linspace(
csv_read['price_mean'].min(),
csv_read['price_mean'].max(),
6
)
#?將容器應用到數據上
csv_read['b_price']?=?np.digitize(
csv_read['price_mean'],
bins
)
?
3. 原理
?
第一步是創建容器。對于價格數據(缺失值用估算的平均數填補),我們創建了六個容器,在最小值和最大值之間均勻分配。.linspace(...)方法做了這點工作:創建長度為6的NumPy數組,其中每個元素比前一個大固定的差值。比如,.linspace(0, 6, 6)生成數組[0., 1.2, 2.4, 3.6, 4.8, 6.]。
?
NumPy對線性代數來說是個強大的數字處理庫。可輕松處理大型數組和矩陣,還提供了極其豐富的函數操作數據。想了解更多,可訪問:
?
http://www.numpy.org
?
.digitize(...)方法對指定列中的每個值,都返回所屬的容器索引。第一個參數是要分級的列,第二個參數是容器的數組。
?
使用DataFrame的.value_counts()得到每個容器中的記錄計數,counts_b = csv_read['b_price'].value_counts()。
?
4. 更多
?
有時候我們不會用均勻間隔的值,我們會讓每個桶中擁有相同的數目。要達成這個目標,我們可以使用分位數。
?
分位數與百分位數有緊密的聯系。區別在于百分位數返回的是給定百分數的值,而分位數返回的是給定分位點的值。想了解更多,可訪問:
?
https://www.stat.auckland.ac.nz/~ihaka/787/lectures-quantiles-handouts.pdf
?
我們想把列拆成十分位數,即10個(差不多)相等的容器。要做到這點,我們可以使用下面的代碼(你可以一眼看出其和之前方法的相似之處):
?
#?根據十分位數創建容器
decile?=?csv_read['price_mean'].quantile(np.linspace(0,?1,?11))
#?將容器應用到數據上
csv_read['p_price']?=?np.digitize(
csv_read['price_mean'],
decile
)
?
.quantile(...)方法可以傳一個(0到1之間的)數字,來表明要返回的分位數(例如,0.5是中位數,0.25和0.75是上下四分位數)。它也可以傳入一個分位的列表,返回相應的值的數組。.linspace(0, 1, 11)方法會生成這個數組:
?
[?0.,?0.1,?0.2,?0.3,?0.4,?0.5,?0.6,?0.7,?0.8,?0.9,?1.]
?
所以,.quantile(...)方法會以price_mean列的最小值開始,直到最大值,返回十分位數的列表。
?
?
04 編碼分類變量
?
為數據的探索階段準備的最后一步就是分類變量了。有些軟件包在背后做了這個工作,但最好還是理解這步處理的時機與做法。
?
統計模型只能接受有序的數據。分類變量(有時根據上下文可表示為數字)不能直接在模型中使用。要使用它們,我們要先進行編碼,也就是給它們一個唯一的數字編號。這解釋了什么時候做。至于如何做—應用下述技巧即可。
?
1. 準備
?
要實踐本技巧,你要先裝好pandas模塊。
?
其他沒有什么要準備的了。
?
2. 怎么做
?
pandas又提供了一個方法,幫我們做完所有事(data_dummy_code.py文件):
?
#?根據房產類型處理的簡單代碼
csv_read?=?pd.get_dummies(
csv_read,
prefix='d',
columns=['type']
)
?
3. 原理
?
.get_dummies(...)方法將分類變量轉換為簡單的變量。比如,考慮一個變量,以三種水平中的某一種作為值:
?
1?One
2?Two
3?Three
?
需要用三列進行編碼:
?
1?One?1?0?0
2?Two?0?1?0
3?Three?0?0?1
?
有時可用兩列。如果有一個水平等效于null的話,我們可以這樣做:
?
1?One?1?0?
2?Two?0?1?
3?Three?0?0?
?
.get_dummies(...)方法的第一個參數是DataFrame對象。columns參數指定了代碼要處理的DataFrame的列(或某些列,因為可以傳入列表)。通過指定前綴,我們告訴方法生成的列名以d打頭;本例中生成的列會叫d_Condo。下劃線是默認的,可以通過指定prefix_sep參數更改。
?
.get_dummies(...)方法的完整參數列表,參見:
?
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.get_dummies.html
?
關于作者:托馬茲·卓巴斯(Tomasz Drabas),微軟數據科學家,致力于解決高維特征空間的問題。他有超過13年的數據分析和數據科學經驗:在歐洲、澳大利亞和北美洲三大洲期間,工作領域遍及高新技術、航空、電信、金融和咨詢。
本文摘編自《數據分析實戰》,經出版方授權發布。
?
延伸閱讀《數據分析實戰》
點擊上圖了解及購買
轉載請聯系微信:togo-maruko
?
推薦語:通過大量的現實案例,詳細講解數據分析相關的各種方法。
?
?
據統計,99%的大咖都完成了這個神操作
▼
?
?
更多精彩
?
在公眾號后臺對話框輸入以下關鍵詞
查看更多優質內容!
?
PPT?|?報告?|?讀書?|?書單
大數據?|?揭秘?|?人工智能?|?AI
Python?|?機器學習?|?深度學習?|?神經網絡
可視化?|?區塊鏈?|?干貨?|?數學
?
猜你想看
?
-
NumPy入門攻略:手把手帶你玩轉這款強大的數據分析和計算工具
-
谷歌最新開源前端框架了解一下?前端小白都能看懂的8本書
-
入門科普:一文看懂機器學習3種類型的概念、根本差別及應用
-
只需4步,微軟數據科學家教你用OpenRefine搞定數據清洗
?
?
Q:?你都遇到過哪些不完整的數據?
歡迎留言與大家分享
覺得不錯,請把這篇文章分享給你的朋友
轉載 / 投稿請聯系:baiyu@hzbook.com
更多精彩,請在后臺點擊“歷史文章”查看
點擊閱讀原文,了解更多
總結
以上是生活随笔為你收集整理的干货:4个小技巧助你搞定缺失、混乱的数据(附实例代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 73页PPT,教你从0到1构建用户画像系
- 下一篇: 婚姻大数据:姐弟恋最靠谱,男同学们,小姐