Python數(shù)據(jù)預(yù)處理

數(shù)據(jù)預(yù)處理包括數(shù)據(jù)的清洗坊罢、合并、重塑與轉(zhuǎn)換知市,解決數(shù)據(jù)缺失傻盟、極端值、數(shù)據(jù)格式不統(tǒng)一等問(wèn)題嫂丙,本文通過(guò)介紹Pandas中專(zhuān)門(mén)用于進(jìn)行數(shù)據(jù)預(yù)處理的函數(shù)及方法來(lái)進(jìn)行數(shù)據(jù)預(yù)處理的標(biāo)準(zhǔn)流程娘赴。


0. 數(shù)據(jù)清洗

數(shù)據(jù)清洗是一項(xiàng)復(fù)雜的工作,該過(guò)程目的在于提高數(shù)據(jù)的質(zhì)量跟啤,將臟數(shù)據(jù)清理干凈诽表,使數(shù)據(jù)具有完整性、唯一性隅肥、權(quán)威性竿奏、合法性、一致性等特點(diǎn)腥放。Pandas常見(jiàn)的數(shù)據(jù)清洗操作有空值和缺失值的處理泛啸、重復(fù)值的處理、異常值的處理秃症、統(tǒng)一數(shù)據(jù)格式等候址。

0.1 空值和缺失值的處理

空值一般表示數(shù)據(jù)未知、不適用或?qū)⒃谝院筇砑訑?shù)據(jù)种柑。缺失值是指數(shù)據(jù)集中某個(gè)或某些屬性不完整主要原因有機(jī)械原因和人為原因岗仑,機(jī)械原因往往因?yàn)闄C(jī)器故障而人為原因可能由于人為隱瞞或錄入失誤而引起的【矍耄空值使用None表示荠雕,缺失值使用NaN表示,處理空值和缺失值通常有如下四個(gè)函數(shù):

函數(shù)名 函數(shù)效果
isnull() 檢查空值或缺失值
notnull() 檢查空值或缺失值
dropna() 刪除含有空值或缺失值的行或列
fillna() 填充空值或缺失值
0.1.1 isnull()notnull()

isnull()notnull()參數(shù)都是只有一個(gè)良漱,表示檢查空值對(duì)象舞虱,不同之處在于isnull()如果檢測(cè)到NoneNaN則標(biāo)記為Truenotnull()檢測(cè)到NoneNaN則標(biāo)記為False,例如:

import pandas as pd
from numpy import NaN
data = pd.DataFrame(
    [[1, 2, 3, NaN], [2, 4, NaN, NaN], [NaN, NaN, NaN, NaN], [1, 2, 6, 7]],
    columns=['A', 'B', 'C', 'D'])
print(data)
print(pd.isnull(data))
print(pd.notnull(data))

輸出:

       A      B      C      D
0  False   True  False   True
1  False  False  False   True
2  False   True  False  False
3   True  False  False   True
       A      B     C      D
0   True  False  True  False
1   True   True  True  False
2   True  False  True   True
3  False   True  True  False
0.1.2 dropna()

該方法作用是刪除含有空值或缺失值的行或列母市。

語(yǔ)法:
pandas.dropna(axis=0,how='any',thresh=None,subset=None,inplace=False)
  • axis:確定過(guò)濾行的行或列矾兜,默認(rèn)為0。取值為0index時(shí)刪除包含缺失值或空值的行患久;取值為1columns時(shí)刪除包含缺失值或空值的列椅寺。
  • how:確定過(guò)濾的標(biāo)準(zhǔn)浑槽,默認(rèn)為any,取值為any時(shí),則存在NaNNone則刪除該行或該列返帕;取值為all時(shí)桐玻,則所有值都為NaNNone是才刪除該行或該列。
  • thresh:表示有效數(shù)據(jù)的最小要求荆萤,如果傳入了2镊靴,則是要求該行或該列至少有兩個(gè)非NaNNone時(shí)將其保留。
  • subset:表示在特定子集中的尋找NaNNone
  • inplace:表示是否在原數(shù)據(jù)上操作默認(rèn)為False链韭,如果設(shè)為True則在原數(shù)據(jù)操作偏竟,如果設(shè)為False則修改原數(shù)據(jù)的副本返回新的數(shù)據(jù)。
實(shí)例:
import pandas as pd
from numpy import NaN
data = pd.DataFrame(
    [[1, 2, 3, NaN], [2, 4, NaN, NaN], [NaN, NaN, NaN, NaN], [1, 2, 6, 7]],
    columns=['A', 'B', 'C', 'D'])

# 默認(rèn)參數(shù)
print(data.dropna())

# 當(dāng)一行/列全部都為NaN時(shí)刪除該行/列
print("\n", data.dropna(how='all'))

# 直接對(duì)原始數(shù)據(jù)操作
data.dropna(inplace=True)
print("\n修改后的數(shù)據(jù)為:\n", data)

輸出為:

     A    B    C    D
3  1.0  2.0  6.0  7.0

      A    B    C    D
0  1.0  2.0  3.0  NaN
1  2.0  4.0  NaN  NaN
3  1.0  2.0  6.0  7.0

修改后的數(shù)據(jù)為:
      A    B    C    D
3  1.0  2.0  6.0  7.0
0.1.3 fillna()

該方法可實(shí)現(xiàn)空值或缺失值的填充敞峭。

語(yǔ)法:
pandas.fillna(value=None,methon=None,axis=None,inplace=False,limit=None,downcast=None,**kwargs)
  • value:用于填充的數(shù)值
  • methon:表示填充方式踊谋,默認(rèn)為None另外支持一下取值
    • pad/ffill:將最后一個(gè)有效數(shù)據(jù)向后傳播,也就是說(shuō)用缺失值前面的一個(gè)值代替缺失值旋讹。
    • backfill/bfill:將最后一個(gè)有效值向前傳播殖蚕,也就是說(shuō)用缺失值后面的一個(gè)值代替缺失值。
  • limit:可以連續(xù)填充的最大數(shù)據(jù)量沉迹,默認(rèn)為None

注意:methodvalue參數(shù)不能同時(shí)使用睦疫。

實(shí)例:
import pandas as pd
from numpy import NaN
data = pd.DataFrame(
    [[1, 2, 3, NaN], [2, 4, NaN, NaN], [NaN, NaN, NaN, NaN], [1, 2, 6, 7]],
    columns=['A', 'B', 'C', 'D'])

# 常數(shù)填充缺失值
print("用常數(shù)6填充缺失值:\n", data.fillna(value="6"))

# 向下填充缺失值(前向填充)
print("\n前向填充缺失值:\n", data.fillna(method="ffill"))

# 指定列填充缺失值
print("\n用常數(shù)10填充A列缺失值,用常數(shù)20填充B列缺失值:\n", data.fillna({'A': 10, 'B': 20}))

輸出為:

用常數(shù)6填充缺失值:
    A  B  C  D
0  1  2  3  6
1  2  4  6  6
2  6  6  6  6
3  1  2  6  7

前向填充缺失值:
      A    B    C    D
0  1.0  2.0  3.0  NaN
1  2.0  4.0  3.0  NaN
2  2.0  4.0  3.0  NaN
3  1.0  2.0  6.0  7.0

用常數(shù)10填充A列缺失值胚股,用常數(shù)20填充B列缺失值:
       A     B    C    D
0   1.0   2.0  3.0  NaN
1   2.0   4.0  NaN  NaN
2  10.0  20.0  NaN  NaN
3   1.0   2.0  6.0  7.0

0.2 重復(fù)值的處理

當(dāng)數(shù)據(jù)中出現(xiàn)了重復(fù)值笼痛,大多數(shù)情況需要?jiǎng)h除裙秋,例如下表中:

id name height sex
0 1 zz 160
1 2 yxy 160
2 3 zxy 170
3 4 wcc 170
4 4 wcc 170

顯然索引為34的數(shù)據(jù)完全相同需要進(jìn)行刪除琅拌,對(duì)于重復(fù)值的處理,Pandas提供了以下兩個(gè)函數(shù):

函數(shù) 函數(shù)效果
duplicated() 標(biāo)記是否有重復(fù)值
drop_duplicates() 刪除重復(fù)值
0.2.1 duplicated()重復(fù)值標(biāo)記函數(shù)
語(yǔ)法:
duplicated(subset=None,keep='first')
  • subset:用于識(shí)別重復(fù)的列標(biāo)簽或列標(biāo)簽序列摘刑,默認(rèn)識(shí)別所有列標(biāo)簽进宝。
  • keep:刪除重復(fù)值并保留第一次出現(xiàn)的項(xiàng),取值如下:
    • first:從前向后查找枷恕,除了第一次出現(xiàn)的項(xiàng)其余相同的均標(biāo)記為重復(fù)党晋。(默認(rèn)值)
    • last:從后往前查找,除了最后一次出現(xiàn)的項(xiàng)其余相同的均標(biāo)記為重復(fù)徐块。
    • False:所有相同的標(biāo)記均標(biāo)記為重復(fù)未玻。
實(shí)例:
import pandas as pd
data = pd.DataFrame(
    [[1, 'zz', 160, '男'], [2, 'yxy', 160, '男'], [3, 'zxy', 170, '女'],
     [4, 'wcc', 170, '男'], [4, 'wcc', 170, '男']],
    columns=['id', 'name', 'height', 'sex'])
data_p = pd.DataFrame([
    data.duplicated(),
    data.duplicated(keep="last"),
    data.duplicated(['height'])
],
                      index=['無(wú)參數(shù)', '從后向前查找', '指定height列'])
print(data_p)

輸出為:

               0      1      2      3      4
無(wú)參數(shù)        False  False  False  False   True
從后向前查找     False  False  False   True  False
指定height列  False   True  False   True   True
0.2.2 drop_duplicates()重復(fù)值刪除函數(shù)
語(yǔ)法:
drop_duplicates(subset=None,keep="first",inplace=False)
實(shí)例:
import pandas as pd
data = pd.DataFrame(
    [[1, 'zz', 160, '男'], [2, 'yxy', 160, '男'], [3, 'zxy', 170, '女'],
     [4, 'wcc', 170, '男'], [4, 'wcc', 170, '男']],
    columns=['id', 'name', 'height', 'sex'])
print(data.drop_duplicates())

輸出為:

   id name  height sex
0   1   zz     160   男
1   2  yxy     160   男
2   3  zxy     170   女
3   4  wcc     170   男

0.3 異常值的處理

異常值指的是樣本中的個(gè)別值,其數(shù)值明顯偏離它所屬樣本的其余觀測(cè)值:

異常值

如圖胡控,藍(lán)色圈出來(lái)的點(diǎn)明顯高于其他值扳剿。對(duì)于異常值的檢測(cè)通常使用3σ原則(拉依達(dá)準(zhǔn)則)箱型圖檢測(cè)。

0.3.1 基于3σ原則檢測(cè)異常值

3σ原則又稱(chēng)拉依達(dá)原則昼激,它是指假設(shè)一組檢測(cè)數(shù)據(jù)中只含有隨機(jī)誤差庇绽,對(duì)其進(jìn)行計(jì)算處理得到標(biāo)準(zhǔn)偏差锡搜,按一定概率確定一個(gè)區(qū)間,凡是超過(guò)這個(gè)區(qū)間的誤差都是粗大誤差瞧掺,在此誤差范圍內(nèi)的數(shù)據(jù)應(yīng)予以剔除耕餐,在正態(tài)分布概率公式中,σ表示標(biāo)準(zhǔn)差辟狈,μ表示平均數(shù),f(x)表示正態(tài)分布函數(shù)肠缔,表達(dá)式如下:
f(x)=\frac{1}{\sqrt{2\pi\sigma}}e^{(-\frac{(x-\mu)^2}{2\sigma^2})}
其中正態(tài)函數(shù)的分布函數(shù)圖如下所示:

正態(tài)函數(shù)
  • 數(shù)值分布在(μ-σμ+σ)中的概率為68.27%
  • 數(shù)值分布在(μ-2σ哼转,μ+2σ)中的概率為95.44%
  • 數(shù)值分布在(μ-3σ桩砰,μ+3σ)中的概率為99.70%

通過(guò)原則,可以定義如下函數(shù):

import numpy as np


# ser1表示傳入DataFrame的某一列
def three_sigma(ser1):
    # 求平均值
    mean_value = ser1.mean()
    # 求標(biāo)準(zhǔn)差
    std_value = ser1.std()
    # 位于(μ-3σ,μ+3σ)區(qū)間內(nèi)的數(shù)據(jù)是正常的释簿,不在該區(qū)間的數(shù)據(jù)是異常的
    # ser1中的數(shù)值小于μ-3σ或大于μ+3σ均為異常值
    # 一旦發(fā)現(xiàn)異常值就標(biāo)注為T(mén)rue亚隅,否則標(biāo)注為False
    rule = (mean_value - 3 * std_value > ser1) | (mean_value + 3 * std_value < ser1)
    # 返回異常值的位置索引
    index = np.arange(ser1.shape[0])[rule]
    # 獲取異常數(shù)據(jù)
    outrange = ser1.iloc[index]
    return(outrange)

對(duì)于一組數(shù)據(jù)例如:1,2,3,4,5,1000,2,3,4,5,3,8,23,12,66,通過(guò)3σ原則來(lái)進(jìn)行檢測(cè):

import pandas as pd
data = pd.DataFrame({"A": [1, 2, 3, 4, 5, 1000, 2, 3, 4, 5, 3, 8, 23, 12, 66]})
print(three_sigma(data['A']))

檢測(cè)結(jié)果為:

5    1000
Name: A, dtype: int64
0.3.2 基于箱型圖檢測(cè)異常值

箱型圖是一種用作顯示一組數(shù)據(jù)分散情況的統(tǒng)計(jì)圖庶溶,在箱型圖中煮纵,異常值被定義為小于Ql-1.5IQR或大于Qu+1.5IQR的值。其中:

  • Ql稱(chēng)為下四分位數(shù)偏螺,表示全部觀察值中有四分之一的數(shù)據(jù)取值比他小
  • Qu稱(chēng)為上四分位數(shù)行疏,表示全部觀察值中有四分之一的數(shù)據(jù)取值比他大
  • IQR稱(chēng)為四分位數(shù)的間距,是上四分位數(shù)Qu與下四分位數(shù)Ql之差套像,其間包含了全部觀察值的一半酿联。
箱型圖

離散點(diǎn)表示的是異常值,上界表示除異常值以外數(shù)據(jù)中最大值夺巩;下界表示除異常值以外數(shù)據(jù)中最小值贞让。

箱型圖根據(jù)實(shí)際的數(shù)據(jù)進(jìn)行繪制,對(duì)數(shù)據(jù)沒(méi)有任何要求柳譬,箱型圖判斷異常值的標(biāo)準(zhǔn)是以四分位數(shù)和四分位距為基礎(chǔ)喳张。在Pandas中提供了一個(gè)boxplot()方法用于繪制箱型圖:

import pandas as pd
import matplotlib.pyplot as plt

data = pd.DataFrame({
    'A': [1, 2, 3, 4],
    'B': [2, 3, 5, 2],
    'C': [1, 4, 7, 4],
    'D': [1, 5, 30, 3]
})

data.boxplot(column=['A', 'B', 'C', 'D'])
plt.show()
output

使用vscodepycharm進(jìn)行可視化需要使用繪圖庫(kù),如果需要直接顯示可以通過(guò)使用Jupyter進(jìn)行快速編輯美澳,安裝教程如下:

通過(guò)在Jupyter中輸入:

import pandas as pd
data = pd.DataFrame({
    'A': [1, 2, 3, 4],
    'B': [2, 3, 5, 2],
    'C': [1, 4, 7, 4],
    'D': [1, 5, 30, 3]
})
data.boxplot(column=['A', 'B', 'C', 'D'])

即可達(dá)到實(shí)時(shí)顯示的目的:

Jupyter

可以看出根據(jù)檢出結(jié)果異常值被檢測(cè)出,對(duì)于異常值制跟,通常會(huì)使用以下四種方式處理異常值:

  • 刪除異常值記錄
  • 使用具體值進(jìn)行替換舅桩,例如使用前后兩個(gè)觀測(cè)值的平均值進(jìn)行修正
  • 不處理,直接在具有異常值的數(shù)據(jù)集中統(tǒng)計(jì)分析
  • 視為缺失值雨膨,利用缺失值的處理方法修正異常值

如果需要對(duì)異常值進(jìn)行替換擂涛,可以使用replace()函數(shù)。

replace()

函數(shù)語(yǔ)法:

replace(to_replace=None,value=None,inplace=False,limit=None,regex=False,method='pad')
  • to_replace:表示查找被替換的方式
  • value:用來(lái)替換任何匹配to_replace的值哥放,默認(rèn)為None
  • limit:表示前向或后向填充的最大尺寸間隙
  • regex:接收布爾值或與to_replace相同的類(lèi)型歼指,默認(rèn)為False爹土,表示是否將to_replacevalue解釋為正則表達(dá)式。

實(shí)例:

import pandas as pd
data = pd.DataFrame({
    'A': [1, 2, 3, 4],
    'B': [2, 3, 5, 2],
    'C': [1, 4, 7, 4],
    'D': [1, 5, 30, 3]
})
data.replace(to_replace=30, value=3, inplace=True)
print(data)

通過(guò)replace方法將data中的異常值30直接在原數(shù)據(jù)集中替換為3踩身,注意胀茵,replace()方法中的to_replace參數(shù)的傳入值也可為列表list

輸出:

   A  B  C  D
0  1  2  1  1
1  2  3  4  5
2  3  5  7  3
3  4  2  4  3

0.4 更改數(shù)據(jù)類(lèi)型

在處理數(shù)據(jù)時(shí)可能會(huì)遇到數(shù)據(jù)類(lèi)型不一致的問(wèn)題,對(duì)于數(shù)據(jù)類(lèi)型的統(tǒng)一有如下三種方式:

  • 創(chuàng)建時(shí)指定數(shù)據(jù)類(lèi)型
  • astype()方法
  • numberic()方法
0.4.1 創(chuàng)建時(shí)指定數(shù)據(jù)類(lèi)型

使用dtype參數(shù)挟阻,例如:

import pandas as pd
data = pd.DataFrame({"A": ['1', '2', '3'], "B": ['4', '5', '6']}, dtype='int')
print(data.dtypes)

可以看出輸入的對(duì)象是字符型巩步,但是通過(guò)指定dtype最終的對(duì)象為int型驻民。

A    int32
B    int32
dtype: object
0.4.2 astype()方法
語(yǔ)法:
astype(dtype,copy=True,errors='raise',** kwargs)
  • dtype:數(shù)據(jù)類(lèi)型
  • copy:是否建立副本好渠,默認(rèn)為True
  • errors:錯(cuò)誤采取的處理方式文虏,默認(rèn)為raise(允許引發(fā)異常),還可以設(shè)置為ignore(抑制異常)
實(shí)例:
import pandas as pd
data = pd.DataFrame({"A": ['1.1', '2.2', '3'], "B": ['4', '5', '6']}, dtype='float')
print(data.dtypes)
print(data['A'].astype(dtype='int'))
輸出:
A    float64
B    float64
dtype: object
0    1
1    2
2    3
Name: A, dtype: int32
0.4.3 to_numeric()

astype()方法存在局限性坷备,通過(guò)to_numeric()函數(shù)可以將傳入?yún)?shù)轉(zhuǎn)換為數(shù)值類(lèi)型熄浓。

語(yǔ)法:
pandas.to_numeric(arg,error='raise',downcast=None)
  • arg:表示要轉(zhuǎn)換的數(shù)據(jù),可以是list,tuple,Series
  • errors:錯(cuò)誤采取的處理方式

to_numeric函數(shù)無(wú)法直接操作DataFrame對(duì)象

實(shí)例:
import pandas as pd
data = pd.Series(['1', '1.2', '3'])
print(pd.to_numeric(data).dtypes)
輸出:
float64

1. 數(shù)據(jù)合并

1.1 軸向堆疊數(shù)據(jù)

通過(guò)使用concat()函數(shù)可以沿著一條軸對(duì)多個(gè)對(duì)象進(jìn)行堆疊省撑,語(yǔ)法格式為:

pandas.concat(objs,axis=0,join='outer',join_axes=None,ignore_index=False,keys=None,levels=None,names=None,verify_integrity=False,sort=None,copy=True)
  • axis:表示連接的軸向赌蔑,默認(rèn)為0,還可以設(shè)置為1
  • join:表示連接方式竟秫,inner表示內(nèi)連接娃惯,outer表示外連接,默認(rèn)外連接
  • ignore_index:接收布爾值肥败,默認(rèn)為False趾浅,如果設(shè)置為True,則表示清除現(xiàn)有索引并重置索引值
  • keys:接收序列馒稍,表示添加最外層索引
  • levels:用于構(gòu)建MultiIndex的特定級(jí)別(唯一)
  • names:在設(shè)置了keyslevel參數(shù)后皿哨,用于創(chuàng)建分層級(jí)別的名稱(chēng)
  • verify_integerity:檢查新的連接軸是否包含重復(fù)值。接收布爾值筷黔,當(dāng)設(shè)置為True時(shí)往史,如果有重復(fù)的軸將會(huì)拋出錯(cuò)誤,默認(rèn)為False
1.1.1 橫向堆疊佛舱、縱向堆疊、內(nèi)連接挨决、外連接
堆疊方式

橫向堆疊以為標(biāo)準(zhǔn)请祖,相同名稱(chēng)的行保存為一行,而縱向堆疊以為標(biāo)準(zhǔn)脖祈,相同名稱(chēng)的列保存為一列肆捕;內(nèi)連接是將兩個(gè)DataFrame對(duì)象中都有的列或行進(jìn)行堆疊連接,而外連接是將兩個(gè)DataFrame對(duì)象所有的列和行進(jìn)行堆疊連接盖高。

橫向堆疊默認(rèn)不考慮列索引而縱向堆疊默認(rèn)不考慮行索引慎陵,缺失值使用NaN填充

實(shí)例:
import pandas as pd
data1 = pd.DataFrame(
    {
        "A": [0, 1, 2, 3],
        "B": [4, 5, 6, 7],
        "C": [8, 9, 10, 11]
    }, dtype=int)
data2 = pd.DataFrame({
    "B": [12, 13, 14],
    "C": [15, 16, 17],
    "D": [18, 19, 20]
},
                     dtype=int)
# 縱向外連接
data3 = pd.concat([data1, data2], join='outer', axis=0)
print(data3)
輸出:
     A   B   C     D
0  0.0   4   8   NaN
1  1.0   5   9   NaN
2  2.0   6  10   NaN
3  3.0   7  11   NaN
0  NaN  12  15  18.0
1  NaN  13  16  19.0
2  NaN  14  17  20.0

1.2 主鍵合并數(shù)據(jù)

主鍵合并類(lèi)似于關(guān)系型數(shù)據(jù)庫(kù)眼虱,根據(jù)一個(gè)或多個(gè)鍵將不同的DataFrame對(duì)象連接起來(lái),大多數(shù)是將兩個(gè)DataFrame對(duì)象中重疊的列作為合并的鍵席纽,Pandas中提供了用于主鍵合并的merge()函數(shù)捏悬,語(yǔ)法為:

pandas.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=False,suffixes=('_x','_y'),copy=True,indicator=False,validate=None)
  • left:參與合并的左側(cè)DataFrame對(duì)象
  • right:參與合并的右側(cè)DataFrame對(duì)象
  • how:表示連接方式,默認(rèn)為inner润梯,該參數(shù)還支持如下取值:
    • left:使用左側(cè)的DataFrame的鍵过牙,類(lèi)似SQL的左外連接
    • right:使用右側(cè)的DataFrame的鍵,類(lèi)似SQL的右外連接
    • outer:使用兩個(gè)DataFrame所有的鍵纺铭,類(lèi)似于SQL全連接
    • inner:使用兩個(gè)DataFrame鍵的交集寇钉,類(lèi)似于SQL內(nèi)連接
  • on:用于連接的列名,必須存在于兩個(gè)DataFrame對(duì)象中
  • left_on:以左側(cè)DataFrame作為連接鍵
  • right_on:以右側(cè)DataFrame作為連接鍵
  • left_index:左側(cè)的行索引用作連接鍵
  • right_index:右側(cè)的行索引用作連接鍵
  • sort:是否排序舶赔,接收布爾值扫倡,默認(rèn)為False
  • suffixes:用于追加到重疊列名的末尾,默認(rèn)為(_x,_y)

在使用merge()函數(shù)進(jìn)行合并時(shí)默認(rèn)使用重疊的列索引作為合并鍵竟纳,并采用內(nèi)連接的方式合并數(shù)據(jù)镊辕。

1.2.1 通過(guò)主鍵合并
通過(guò)主鍵合并

針對(duì)同一個(gè)主鍵存在兩張不同字段的表,根據(jù)主鍵整合到一張表里面蚁袭,例如上圖中左側(cè)兩張表均有索引為key的一列數(shù)據(jù)征懈,兩表通過(guò)key列合并為一個(gè)表。即:

import pandas as pd
top = pd.DataFrame({"key": ['k0', 'k3', 'k4'], "A": [1, 3, 5], "B": [2, 4, 6]})
bottom = pd.DataFrame({
    "key": ['k0', 'k2', 'k3'],
    "C": [7, 9, 11],
    "D": [8, 10, 12]
})
print(pd.merge(top, bottom, on="key"))

輸出:

  key  A  B   C   D
0  k0  1  2   7   8
1  k3  3  4  11  12
1.2.2 多個(gè)主鍵合并
多個(gè)主鍵合并

通過(guò)merge()函數(shù)可以對(duì)含有多個(gè)重疊列的DataFrame對(duì)象進(jìn)行合并揩悄,例如上圖中使用keyB作為合并鍵得到右側(cè)合并結(jié)果:

import pandas as pd
top = pd.DataFrame({"key": ['k0', 'k3', 'k4'], "A": [1, 3, 5], "B": [2, 4, 6]})
bottom = pd.DataFrame({
    "key": ['k0', 'k2', 'k3'],
    "C": [7, 9, 11],
    "D": [8, 10, 12],
    "B": [2, 3, 1]
})
print(pd.merge(top, bottom, on=["key", "B"]))

輸出為:

  key  A  B  C  D
0  k0  1  2  7  8

merge()函數(shù)支持四種合并方式分別為內(nèi)連接(inner)卖哎、外連接(outer)左連接(left)删性、右連接(right)亏娜。函數(shù)中的how默認(rèn)參數(shù)為inner,不同合并方式解釋如下蹬挺。(下列操作均針對(duì)于key為鍵值)

連接方式
  • 內(nèi)連接(inner):匹配兩個(gè)DataFrame對(duì)象中均有的鍵值并合并
  • 外連接(outer):合并兩個(gè)DataFrame對(duì)象中所有的鍵值维贺,缺失值用NaN填充
  • 左連接(left):以merge函數(shù)中第一個(gè)出現(xiàn)的DataFrame對(duì)象的指定鍵值為標(biāo)準(zhǔn)進(jìn)行連接,第一個(gè)出現(xiàn)的DataFrame表中數(shù)據(jù)將會(huì)全部顯示巴帮,而第二個(gè)出現(xiàn)的DataFrame對(duì)象只會(huì)顯示與重疊數(shù)據(jù)行索引相同的數(shù)據(jù)溯泣,合并后缺失數(shù)據(jù)用NaN填充
  • 右連接(right):以merge函數(shù)中第二個(gè)出現(xiàn)的DataFrame對(duì)象的指定鍵值為標(biāo)準(zhǔn)進(jìn)行連接,第二個(gè)出現(xiàn)的DataFrame表中數(shù)據(jù)將會(huì)全部顯示榕茧,而第一個(gè)出現(xiàn)的DataFrame對(duì)象只會(huì)顯示與重疊數(shù)據(jù)行索引相同的數(shù)據(jù)垃沦,合并后缺失數(shù)據(jù)用NaN填充
示例代碼:
import pandas as pd
left = pd.DataFrame({
    'key': ['K0', 'K1', 'K2'],
    'A': ['A0', 'A1', 'A2'],
    'B': ['B0', 'B1', 'B2']
})
right = pd.DataFrame({
    'key': ['K0', 'K1', 'K2', 'K3'],
    'B': ['B0', 'B1', 'B2', 'B3'],
    'C': ['C0', 'C1', 'C2', 'C3'],
    'D': ['D0', 'D1', 'D2', 'D3']
})
# 左連接
data_left = pd.merge(left, right, how='left', on='key')
# 右連接
data_right = pd.merge(left, right, how='right', on='key')
# 內(nèi)連接
data_inner = pd.merge(left, right, how='inner', on='key')
# 外連接
data_outer = pd.merge(left, right, how='outer', on='key')

如果兩張表行索引和列索引均沒(méi)有重疊部分,可以通過(guò)將merge()函數(shù)的left_indexright_index均設(shè)置為True即可用押,例如:

import pandas as pd
left = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']}, index=['a', 'b'])
right = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']})
data = pd.merge(left, right, how='outer', left_index=True, right_index=True)
print(data)

輸出為:

     A    B    C    D
a   A0   B0  NaN  NaN
b   A1   B1  NaN  NaN
0  NaN  NaN   C0   D0
1  NaN  NaN   C1   D1

1.3 根據(jù)行索引合并數(shù)據(jù)

1.3.1 join()方法

join()方法能夠通過(guò)索引或者指定的列來(lái)連接DataFrame肢簿。

語(yǔ)法:
join(other,on=None,how='left',lsuffix='',rsuffix='',sort=False)
  • on:用于連接的列名
  • lsuffix:接收字符串,用于在左側(cè)重疊的列名后添加后綴
  • rsuffix:接收字符串,用于在右側(cè)重疊的列名后添加后綴
  • sort:接收布爾值池充,根據(jù)連接鍵對(duì)合并的數(shù)據(jù)進(jìn)行排序桩引,默認(rèn)為False
實(shí)例:
import pandas as pd
left = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']}, index=['a', 'b'])
right = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']})
data = left.join(right, how="outer")
print(data)
輸出:
     A    B    C    D
a   A0   B0  NaN  NaN
b   A1   B1  NaN  NaN
0  NaN  NaN   C0   D0
1  NaN  NaN   C1   D1

1.4 合并重疊數(shù)據(jù)

在處理數(shù)據(jù)時(shí),當(dāng)一個(gè)DataFrame對(duì)象出現(xiàn)了缺失值收夸,對(duì)于這些缺失數(shù)據(jù)如果想要通過(guò)其他的DataFrame對(duì)象中的數(shù)據(jù)填充坑匠,可以通過(guò)combine_first()方法填充缺失數(shù)據(jù)。

語(yǔ)法:
combine_first(other)
  • other:用于接收填充缺失值的對(duì)象
實(shí)例:
合并重疊數(shù)據(jù)
import pandas as pd
from numpy import NaN
left = pd.DataFrame({
    'key': ['K0', 'K1', 'K2', 'K3'],
    'A': ['A0', NaN, 'A2', 'A3'],
    'B': [NaN, 'B1', NaN, 'B3']
})
right = pd.DataFrame({
    'A': ['C0', 'C1', 'C2'],
    'B': ['D0', 'D1', 'D2']
},
                     index=[1, 2, 0])
print(left.combine_first(right))
輸出:
    A   B key
0  A0  D2  K0
1  C0  B1  K1
2  A2  D1  K2
3  A3  B3  K3

使用combine_first方法合并兩個(gè)DataFrame對(duì)象時(shí)咱圆,必須確保他們的行索引和列索引有重疊部分

2. 數(shù)據(jù)重塑

Pandas中大多數(shù)情況DataFrame對(duì)象更便于操作笛辟,因?yàn)?code>DataFrame對(duì)象很容易獲取每行或每列的數(shù)據(jù)。但是有時(shí)候需要將DataFrame對(duì)象轉(zhuǎn)換為Series對(duì)象序苏,因此需要對(duì)數(shù)據(jù)進(jìn)行重塑手幢。

2.1 重塑層次化索引

重塑層次化索引的操作主要是stack()方法和unstack()方法,前者是將數(shù)據(jù)的列旋轉(zhuǎn)為行忱详,后者是將數(shù)據(jù)的行旋轉(zhuǎn)成列围来。

2.1.1 stack()方法
語(yǔ)法:
DataFrame.stack(level=-1,dropna=True)
  • level:表示操作的內(nèi)層索引,若設(shè)置為0匈睁,表示操作外層索引监透,默認(rèn)為-1
  • dropna:表示是否將旋轉(zhuǎn)后的缺失值刪除,默認(rèn)為True(過(guò)濾缺失值)
實(shí)例:
重塑
import pandas as pd
data = pd.DataFrame({"A": ['A0', 'A1', 'A2'], "B": ['B0', 'B1', 'B2']})
result = data.stack()
print(result)

輸出:

0  A    A0
   B    B0
1  A    A1
   B    B1
2  A    A2
   B    B2

通過(guò):

print(type(result))

可查看結(jié)果為:

<class 'pandas.core.series.Series'>
2.1.2 unstack方法
語(yǔ)法:
DataFrame.unstack(level=-1,fill_value=None)
  • fill_value:若產(chǎn)生了缺失值航唆,則可以設(shè)置這個(gè)參數(shù)用來(lái)替換NaN
實(shí)例:

將上例中還原:

print(result.unstack())
輸出:
    A   B
0  A0  B0
1  A1  B1
2  A2  B2

可以使用stack對(duì)多層索引進(jìn)行重塑胀蛮。

多層索引
import pandas as pd
import numpy as np
data = pd.DataFrame(np.array([[26, 20, 22, 26], [30, 25, 24, 20]]),
                    index=['男生人數(shù)', '女生人數(shù)'],
                    columns=[['一樓', '一樓', '二樓', '二樓'],
                             ['A教室', 'B教室', 'A教室', 'B教室']])
result = data.stack()
print(result)

輸出:

          一樓  二樓
男生人數(shù) A教室  26  22
     B教室  20  26
女生人數(shù) A教室  30  24
     B教室  25  20

2.2 軸向旋轉(zhuǎn)

2.2.1 pivot方法

pivot方法提供的功能是根據(jù)給定行索引或列索引重新組織一個(gè)DataFrame對(duì)象。

語(yǔ)法:
DataFrame.pivot(index=None,columns=None,values=None)
  • index:用于創(chuàng)建新DataFrame對(duì)象的行索引糯钙,如果未設(shè)置粪狼,則使用原DataFrame對(duì)象的索引。
  • columns:列索引
  • values:值
實(shí)例:
出售日期 商品名稱(chēng) 價(jià)格(元)
2017年5月25日 榮耀9青春版 999
2017年5月25日 小米6x 1399
2017年5月25日 OPPO A1 1399
2017年6月18日 榮耀9青春版 800
2017年6月18日 小米6x 1200
2017年6月18日 OPPO A1 1250

將上述表格轉(zhuǎn)化為下表:

商品名稱(chēng)/出售日期 榮耀9青春版 小米6x OPPO A1
2017年5月25日 999 1399 1399
2017年6月18日 800 1200 1250
import pandas as pd
data = pd.read_excel('./ProductInfo.xlsx')
result = data.pivot(index="出售日期", columns="商品名稱(chēng)", values="價(jià)格(元)")
print(result)

3. 數(shù)據(jù)轉(zhuǎn)換

當(dāng)數(shù)據(jù)進(jìn)行清洗之后任岸,需要對(duì)數(shù)據(jù)進(jìn)行一些合理的轉(zhuǎn)換再榄,使這些數(shù)據(jù)更符合分析的要求。

3.1 重命名軸索引

重命名軸索引是數(shù)據(jù)分析中比較常見(jiàn)的操作享潜,可以通過(guò)rename()方法重命名個(gè)別列索引或行索引的標(biāo)簽或名稱(chēng)困鸥。

3.1.1 語(yǔ)法格式:
rename(mapper=None,index=None,columns=None,axis=None,copy=True,inplace=False,level=None)
  • index,columns:表示待轉(zhuǎn)換的行索引和列索引
  • axis:表示軸的名稱(chēng),可以使用indexcolumns剑按,也可以使用數(shù)字0或1
  • copy:表示是否復(fù)制底層的數(shù)據(jù)疾就,默認(rèn)為False
  • inplace:默認(rèn)為False,表示是否返回新的Pandas對(duì)象吕座,如果設(shè)置為True虐译,則會(huì)忽略復(fù)制的值
  • level:表示級(jí)別的名稱(chēng),默認(rèn)為None吴趴。對(duì)于多級(jí)索引,只重命名指定的標(biāo)簽。
3.1.2 實(shí)例

將下列表格列索引更改為a,b,c

A B C
0 1 2 3
1 4 5 6
2 7 8 9
3 10 11 12
import pandas as pd
data = pd.DataFrame({
    "A": [1, 4, 7, 10],
    "B": [2, 5, 8, 11],
    "C": [3, 6, 9, 12]
})
result = data.rename(str.lower, axis="columns")
print(result)
3.1.3 輸出
    a   b   c
0   1   2   3
1   4   5   6
2   7   8   9
3  10  11  12
3.1.4 其他說(shuō)明

使用rename()方法也可以對(duì)行索引進(jìn)行重命名:

result_s = result.rename(index={1: 'a', 2: 'b'})
print(result_s)

輸出:

    a   b   c
0   1   2   3
a   4   5   6
b   7   8   9
3  10  11  12

3.2 離散化連續(xù)數(shù)據(jù)

有時(shí)候我們需要將數(shù)據(jù)進(jìn)行離散化锣枝,可以使用cut()函數(shù)厢拭。

3.2.1 函數(shù)語(yǔ)法:
pandas.cut(x,bins,right=True,labels=None,retbins=False,precision=3,include_lowest=False,duplicates='raise')
  • x:表示要分箱的數(shù)組,必須是一維的
  • bins:接收int和序列類(lèi)型的數(shù)據(jù)
  • right:是否包含右端點(diǎn)撇叁,默認(rèn)包含
  • labels:用于生成區(qū)間的標(biāo)簽
  • retbins:是否返回bin
  • precision:精度供鸠,默認(rèn)保留三位小數(shù)
  • include_lowest:是否包含左端點(diǎn)
3.2.2 實(shí)例
import pandas as pd
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 32]
bins = [0, 18, 25, 35, 60, 100]
cuts = pd.cut(ages, bins)
print(cuts)
3.2.3 輸出
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (35, 60], (25, 35], (60, 100], (35, 60], (25, 35]]
Length: 11
Categories (5, interval[int64]): [(0, 18] < (18, 25] < (25, 35] < (35, 60] < (60, 100]]

3.3 啞變量處理類(lèi)別型數(shù)據(jù)

在Pandas中,可以使用get_dummies()函數(shù)對(duì)類(lèi)別特征進(jìn)行啞變量處理陨闹。語(yǔ)法如下:

pandas.get_dummies(data,prefix=None,prefix_sep='_',dummy_na=False,columns=None,sparse=False,drop_first=False,dtype=None)
  • data:可接收數(shù)組楞捂,DataFrameSerise對(duì)象,表示啞變量處理的數(shù)據(jù)
  • prefix:表示列名的前綴趋厉,默認(rèn)為None
  • prefix_sep:用于附加前綴作為分隔符寨闹,默認(rèn)為_
  • dummy_na:表示是否為NaN值添加一列,默認(rèn)為False
  • sparse:表示虛擬列是否是稀疏的君账,默認(rèn)為False
  • drop_first:是否通過(guò)從k個(gè)分類(lèi)級(jí)別中刪除第一個(gè)級(jí)來(lái)獲得k-1個(gè)分類(lèi)級(jí)別繁堡,默認(rèn)為False

例如:

import pandas as pd
data = pd.DataFrame({"職業(yè)": ["工人", "學(xué)生", "司機(jī)", "教師", "導(dǎo)游"]})
print(pd.get_dummies(data, prefix=['col_']))

輸出為:

   col__司機(jī)  col__學(xué)生  col__導(dǎo)游  col__工人  col__教師
0        0        0        0        1        0
1        0        1        0        0        0
2        1        0        0        0        0
3        0        0        0        0        1
4        0        0        1        0        0
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市乡数,隨后出現(xiàn)的幾起案子椭蹄,更是在濱河造成了極大的恐慌,老刑警劉巖净赴,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绳矩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡玖翅,警方通過(guò)查閱死者的電腦和手機(jī)翼馆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烧栋,“玉大人写妥,你說(shuō)我怎么就攤上這事∩笮眨” “怎么了珍特?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)魔吐。 經(jīng)常有香客問(wèn)我扎筒,道長(zhǎng),這世上最難降的妖魔是什么酬姆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任嗜桌,我火速辦了婚禮,結(jié)果婚禮上辞色,老公的妹妹穿的比我還像新娘骨宠。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布层亿。 她就那樣靜靜地躺著桦卒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匿又。 梳的紋絲不亂的頭發(fā)上方灾,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音碌更,去河邊找鬼裕偿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛痛单,可吹牛的內(nèi)容都是我干的嘿棘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼桦他,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蔫巩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起快压,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤圆仔,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蔫劣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坪郭,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年脉幢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了歪沃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嫌松,死狀恐怖沪曙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萎羔,我是刑警寧澤液走,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站贾陷,受9級(jí)特大地震影響缘眶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜髓废,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一巷懈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧慌洪,春花似錦顶燕、人聲如沸凑保。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愉适。三九已至犯助,卻和暖如春癣漆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背剂买。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工惠爽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瞬哼。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓婚肆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坐慰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子较性,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容