轉載於:點擊打開鏈接
數據因爲存在數據錯誤,數據缺失,離羣值的存在,所以需要對數據進行清洗
1.數據錯誤:
錯誤類型
– 髒數據或錯誤數據
• 比如, Age = -2003
– 數據不正確
• ‘0’ 代表真實的0,還是代表缺失
– 數據不一致
• 比如收入單位是萬元,利潤單位是元,或者一個單位是
美元,一個是人民幣
– 數據重複
2.缺失值處理:
處理原則
–缺失值少於20%
•連續變量使用均值或中位數填補
•分類變量不需要填補,單算一類即可,或者用衆數填補
–缺失值在20%-80%
•填補方法同上
•另外每個有缺失值的變量生成一個指示啞變量,參與後續的建模
–缺失值在大於80%
•每個有缺失值的變量生成一個指示啞變量,參與後續的建模,原始變量不使用。
3.離羣值
3.1單變量離羣值處理:
.繪圖。
在圖中找出離羣的異常值,根據情況對其進行刪除或者對數據進行變換從而在數值上使其不離羣或者不明顯。
學生化(標準化)
•用變量除以他們的標準誤就可得到學生化數值
建議的臨界值:
–|SR| >2 ,用於觀察值較少的數據集
–|SR| >3,用於觀察值較多的數據集
3.2多變量離羣值
1.繪圖。
在圖中找出明顯的離羣值
2.聚類法確定離羣值(不要對原有數據進行改變)
聚類效果評判指標:(羣內方差(距離)最小化,羣間方差(距離)最大化;這裏方差可以理解爲一種距離(歐式距離的平方—歐式距離))
瞭解清洗後,接下來,就來學習一下Python的數據清洗吧!
現在有一份心臟病患者的數據,經過問卷調查之後,最終錄入數據如下:
- Age:年齡
- Areas:來自哪裏,有A/B/C/D四個地區
- ID:患者的唯一識別編號
- Package:每天抽幾包煙,缺失的爲-9,代表不抽菸
- SHabit:睡眠習慣,1-早睡早起;2-晚睡早起;3-早睡晚起;4-晚睡晚起
爲了學習方便,假設這裏就這些變量吧。
看完這個變量說明我不淡定了,這個數據存在很多問題啊!Age是年齡?158是什麼鬼??還有6歲小孩,每天抽1包煙?ID是唯一編號嗎?爲什麼有3個1號、2個5號、2個9號、2個10號?
這個數據問題太多了,因此我要逐一來清洗一下,順便學一下數據清洗方面的知識。
1. 刪除重複
3個1號、2個5號、2個9號、2個10號。這是數據錄入中經常出現的問題——重複錄入了,所以首先我要把那麼多佔空間又沒用的重複數據剔除。
介紹兩個方法:data.duplicated() 和 data.drop_duplicates(),前者標記出哪些是重複的(true),後者直接將重複刪除。
所以drop.duplicates直接就將重複值刪除了,默認保留第一條。
以上是按照“有兩行數據,這兩行數據的所有變量值都一樣,這麼這兩行就算重複數據”,但有時候我們會只根據一個變量來剔除重複,比如值根據Areas這個變量,那麼A/B/C/D四個地區只會保留第一條,傳入take_last=True則保留最後一個:
A/B/C/D每個地區值保留一條數據了。
2. 異常值檢測
在第一步剔除重複值之後。得到了無重複數據的data_noDup:
第二步,我想檢測一下數據中有沒有異常值。首先可以用 describe() 進行一個描述分析,在第五天的學習中(第5天:Pandas,露兩手)已經學過如何對數據進行描述:
有兩個變量值得我們注意,一個是age,最大值158、最小值6,肯定有問題,另一個是package,最小值是-9,存在缺失。
用 data[條件] 的方式可以看一下有多少age大於100、age小於10,、package爲-9的:
好了,檢測完畢,現在來處理這些異常值。
3. 替換
我要把異常的年齡替換成缺失,把package等於-9的替換成0(換成0是因爲,不抽菸其實也就是抽菸數量爲0,這樣還能少一些缺失值)。
替換的方式有2種,字典,或者替換關係組成的數組:
(1)data.replace([A, B], [A_R, B_R]),如果這裏替換之後的值A_R和B_R是一樣的,那麼[A_R,B_R]直接是A_R就可以了
(2)data.replace({A:A_R, B:B_R}),這是字典的方式。
所以,這裏想要將age的6、158替換成缺失,就應該爲:
data_noDup[‘Age’].replace([158, 6], np.nan)
將package的-9替換成0:
data_noDup[‘Package’].replace(-9, 0)
替換之後的數據命名爲data_noDup_rep:
4. 數據映射
接下來的一些處理,是爲了變量能夠更加便於分析,首先是要進行數據映射。什麼是映射呢?以Areas爲例,Areas取四個地區:A/B/C/D, 這四個地區在分析的時候並沒有什麼意義,但A/B/C爲城市,D爲農村,這個很有意義,所以我要根據areas創建新變量CType:U-城市、R-農 村,映射關係如下:
方法就是寫一個映射字典,把A/B/C變成U,把D變成R:
areas_to_ctype={‘A’:’U’,’B’:’U’,’C’:’U’,’D’:’R’}
然後使用 map(映射字典) 去創建新變量CType:
data_noDup_rep[‘CType’]=data[‘Areas’].map(areas_to_ctype)
其實用替換也可以,但是替換是在原列上替換,而映射自己可以新建一個變量。
5. 數值變量類型化
接下來還要處理的變量是年齡Age,需要分成四組,
- 0:30歲以下,也就是0到30歲
- 1:30-40歲
- 2:40-50歲
- 3:50歲以上,不妨設爲50-100歲
這個問題如果用映射MAP的話就麻煩了,每一個年齡都要寫一個映射。使用 cut 函數來分割,就可以自己分割成幾個組。
1)首先要設置幾個分割點:0、30、40、50、100:cutPoint=[0,30, 40, 50,80]
2)接着,用 cut(data, cutPoint) 的格式對age按照cutPoint進行劃分:pd.cut(data_noDup_rep[‘Age’],cutPoint)
3)最後,將這個賦給新變量ageGroup:data_noDup_rep[‘ageGroup’] =pd.cut(data_noDup_rep[‘Age’],cutPoint)
這樣很不好看有木有?怎麼把四個組分別用0、1、2、3來表示呢?
設定一個組標籤groupLabel=[0,1,2,3],指定 labels=groupLable 即可。
data_noDup_rep[‘ageGroup’] =pd.cut(data_noDup_rep[‘Age’],cutPoint, labels=groupLabel)
一個問題來了,依稀記得之前做過一個項目,樣本量有7000,年齡分組是按照分位數來分的,那再python中能否實現?
可以的,用 qcut(data, n) 就可以,按照分位數分n組,比如分2組,那麼就按照中位數來分,分4組,就按照四分位數來分。對這個例子我分兩組:
data_noDup_rep[‘ageGroup’] =pd.qcut(data_noDup_rep[‘Age’],2)
6. 創建啞變量
啞變量一般用於兩種情況:一是變量值是無序並列的,比如例子中的SHabit,四個選項1、2、3、4是並列的;另一種就是多選題,也需要生成啞變量。
以本例中的SHabit(睡眠情況)爲例,四個取值是並列的,沒有順序,因此我們要把這1個問題變成4個:
SHabit(睡眠習慣,1-早睡早起;2-晚睡早起;3-早睡晚起;4-晚睡晚起)
變成:
SHabit_1:是否早睡早起?(0-否,1-是)
SHabit_2:是否晚睡早起?(0-否,1-是)
SHabit_3:是否早睡晚起?(0-否,1-是)
SHabit_4:是否晚睡晚起?(0-否,1-是)
使用 get.dummies( data[‘SHabit’] ) 就可以直接搞定:
生成了四個變量。要把它合併入原數據data_noDup_rep中去,只要用 merge 就可以了(上一文剛剛介紹過數據的合併,戳複習→第6天:數據合併)
data_noDup_rep_dum =pd.merge(data_noDup_rep, pd.get_dummies(data_noDup_rep[‘SHabit’]),right_index=True, left_index=True)
(注:因爲合併鍵值是索引,因此要用right_index=True和left_index=True)
一個問題:變量名1、2、3、4太醜了!
可以在get_dummies函數中加 prefix=’’ 選項爲名字加一個前綴:
data_noDup_rep_dum =pd.merge(data_noDup_rep, pd.get_dummies(data_noDup_rep[‘SHabit’], prefix=’SHabit’ ), right_index=True, left_index=True)
變量比較多,所以換行顯示了。還有一種情況,如果SHabit是多選呢?每個人的睡眠習慣不止一種,像這樣:
這樣的多選題數據,在分析中肯定一點用沒有,處理的方法也是生成啞變量,如何生成?將在【第8天:數據清洗(2)文本分析】中學習,除此之外,還要學習如何進行分列處理、如何處理文本數據中的空白,如何使用正則表達式。