乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      7步搞定數(shù)據(jù)清洗-Python數(shù)據(jù)清洗指南

       LibraryPKU 2019-07-21

      重磅干貨,第一時(shí)間送達(dá)

      作者:KOALA https://zhuanlan.zhihu.com/p/60241672

      臟數(shù)據(jù)就是在物理上臨時(shí)存在過(guò),但在邏輯上不存在的數(shù)據(jù)。

      數(shù)據(jù)清洗是整個(gè)數(shù)據(jù)分析過(guò)程的第一步,就像做一道菜之前需要先擇菜洗菜一樣。數(shù)據(jù)分析師經(jīng)常需要花費(fèi)大量的時(shí)間來(lái)清洗數(shù)據(jù)或者轉(zhuǎn)換格式,這個(gè)工作甚至?xí)颊麄€(gè)數(shù)據(jù)分析流程的80%左右的時(shí)間。

      在這篇文章中,我嘗試簡(jiǎn)單地歸納一下用Python來(lái)做數(shù)據(jù)清洗的7步過(guò)程,供大家參考。

      一、數(shù)據(jù)預(yù)處理

      一、數(shù)據(jù)預(yù)處理

      1. 部署環(huán)境,導(dǎo)入分析包和數(shù)據(jù)

      #導(dǎo)入數(shù)據(jù)分析包
      import pandas as pd
      import numpy as np
      #導(dǎo)入csv數(shù)據(jù)
      #dtype = str,最好讀取的時(shí)候都以字符串的形式讀入,不然可能會(huì)使數(shù)據(jù)失真
      #比如一個(gè)0010008的編號(hào)可能會(huì)讀取成10008

      fileNameStr = './Actual transactions from UK retailer.csv'
      DataDF = pd.read_csv(fileNameStr,encoding = 'ISO-8859-1',dtype = str)

      # encoding = 'ISO-8859-1' -- 用什么解碼,一般會(huì)默認(rèn)系統(tǒng)的編碼,如果是中文就用 'utf-8'
      DataDF = pd.read_csv(fileNameStr,encoding = 'utf-8',dtype = str)

      2. 嘗試去理解這份數(shù)據(jù)集

      我們可以通過(guò)對(duì)數(shù)據(jù)集提問(wèn)來(lái)判斷這份數(shù)據(jù)能不能滿足解答我們的問(wèn)題,數(shù)據(jù)是否干凈需不需要進(jìn)一步處理,問(wèn)題包括但不限于:

      數(shù)據(jù)集多少數(shù)據(jù)?
      包含了什么字段?字段格式是什么?
      字段分別代表什么意義
      字段之間的關(guān)系是什么?可以用做什么分析?或者說(shuō)能否滿足了對(duì)分析的要求?
      有沒(méi)有缺失值;如果有的話,缺失值多不多?
      現(xiàn)有數(shù)據(jù)里面有沒(méi)有臟數(shù)據(jù)?尤其需要注意人工輸入的數(shù)據(jù),經(jīng)常會(huì)出現(xiàn)名稱寫(xiě)錯(cuò),多輸入空格等等的情況

      3. 下面我們就結(jié)合代碼來(lái)看一下數(shù)據(jù)

      #1 從宏觀一點(diǎn)的角度去看數(shù)據(jù):查看dataframe的信息
      DataDF.info()

      也可以用這兩條來(lái)看:

      #1.1查看每一列的數(shù)據(jù)類型
      DataDF.dtypes

      #1.2有多少行,多少列
      DataDF.shape
      # 2.檢查缺失數(shù)據(jù)
      # 如果你要檢查每列缺失數(shù)據(jù)的數(shù)量,使用下列代碼是最快的方法。
      # 可以讓你更好地了解哪些列缺失的數(shù)據(jù)更多,從而確定怎么進(jìn)行下一步的數(shù)據(jù)清洗和分析操作。

      DataDF.isnull().sum().sort_values(ascending=False)
      # 3.是抽出一部分?jǐn)?shù)據(jù)來(lái),人工直觀地理解數(shù)據(jù)的意義,盡可能地發(fā)現(xiàn)一些問(wèn)題
      DataDF.head()

      可以看到:

      1)Country和UnitPrice都出現(xiàn)了NaN值,需要去掉

      2)InvoiceDate的時(shí)間出現(xiàn)具體時(shí)分,可以刪去

      3)Description大概率是人工填寫(xiě)的數(shù)據(jù),一般都會(huì)有比較多格式問(wèn)題。

      猜測(cè)會(huì)存在有標(biāo)點(diǎn)符號(hào)摻雜/大小寫(xiě)不一致等問(wèn)題,所以進(jìn)一步這些人工填寫(xiě)數(shù)據(jù)的去重項(xiàng)拎出來(lái)研究一下

      # 查看這個(gè)商品名稱的去重項(xiàng)
      DataDF['Description'].unique()
      # 設(shè)置輸出全部的內(nèi)容
      # threshold就是設(shè)置超過(guò)了多少條,就會(huì)呈現(xiàn)省略
      #(比如threshold=10的意思是超過(guò)10條就會(huì)省略)
      np.set_printoptions(threshold=np.inf)

      發(fā)現(xiàn)有很多空格的問(wèn)題

      根據(jù)第一步數(shù)據(jù)預(yù)處理后,整理一下該數(shù)據(jù)集有下列問(wèn)題需要處理:

      1)調(diào)整數(shù)據(jù)類型:由于一開(kāi)始用到了str來(lái)導(dǎo)入,打算后期再更換格式,需要調(diào)整數(shù)據(jù)類型。

      2)修改列名:該數(shù)據(jù)的名稱不易于理解,需要改列名

      3)選擇部分子集:因?yàn)橛胁糠至性跀?shù)據(jù)分析中不需要用到

      4)可能存在邏輯問(wèn)題需要篩選:比如Unit Price為負(fù)

      5)格式一致化:Description可能會(huì)存在有標(biāo)點(diǎn)符號(hào)摻雜/大小寫(xiě)不一致/空格重復(fù)出現(xiàn)等問(wèn)題

      6)消滅空值:CustomerID、Description、Country和UnitPrice都出現(xiàn)了NaN值,需要去掉

      于是下面就開(kāi)始后續(xù)的數(shù)據(jù)清洗6步

      二、調(diào)整數(shù)據(jù)類型

      數(shù)據(jù)類型調(diào)整前
      #字符串轉(zhuǎn)換為數(shù)值(整型)
      DataDF['Quantity'] = DataDF['Quantity'].astype('int')
      #字符串轉(zhuǎn)換為數(shù)值(浮點(diǎn)型)
      DataDF['UnitPrice'] = DataDF['UnitPrice'].astype('float')

      日期調(diào)整前(為求簡(jiǎn)便這里用已經(jīng)剔除分秒,剔除的辦法后面在格式一致化的空格分割再詳細(xì)說(shuō))
      #數(shù)據(jù)類型轉(zhuǎn)換:字符串轉(zhuǎn)換為日期
      #errors='coerce' 如果原始數(shù)據(jù)不符合日期的格式,轉(zhuǎn)換后的值為空值NaT

      DataDF.loc[:,'InvoiceDate']=pd.to_datetime(DataDF.loc[:,'InvoiceDate'],
      format='%d/%m/%Y',
      errors='coerce')

      #!!?? format 是你[原始數(shù)據(jù)]中日期的格式

      %y 兩位數(shù)的年份表示(00-99
      %Y 四位數(shù)的年份表示(000-9999
      %m 月份(01-12
      %d 月內(nèi)中的一天(0-31
      %H 24小時(shí)制小時(shí)數(shù)(0-23
      %I 12小時(shí)制小時(shí)數(shù)(01-12
      %M 分鐘數(shù)(00-59
      %S 秒(00-59
      日期類型調(diào)整后
      數(shù)據(jù)類型調(diào)整完畢

      三、修改列名

      修改前
      #建立字典字典:舊列名和新列名對(duì)應(yīng)關(guān)系
      colNameDict = {'InvolceDate':'SaleDate','StockCode':'StockNo'}

      #!! ??一定要舊列名放在冒號(hào)前
      #每組對(duì)應(yīng)關(guān)系以[逗號(hào)]隔開(kāi)

      salesDf.rename(columns = colNameDict,inplace=True)
      修改后

      四、選擇部分子集

      這是一個(gè)8列*541909行的數(shù)據(jù)集。

      #選擇子集,選擇其中一列
      subDataDF1=DataDF['InvoiceDate']
      #選擇子集,選擇其中兩列
      subDataDF1=DataDF[['InvoiceDate','UnitPrice']]
      利用切片篩選數(shù)據(jù)功能 df.loc

      https://pandas./pandas-docs/stable/reference/api/pandas.DataFrame.loc.html#pandas.DataFrame.loc


      loc這個(gè)代碼有點(diǎn)像Excel里面的鼠標(biāo)左鍵,可以隨意拉動(dòng)你需要的數(shù)據(jù)進(jìn)行切片。

      以逗號(hào)作為隔開(kāi)的界限,左邊為index,右邊為column

      subDataDF1=DataDF.loc[:,'InvoiceDate']
      subDataDF1
      #單一個(gè)冒號(hào)意味著不作限制的全選
      subDataDF2=DataDF.loc[0:9,:]
      subDataDF2
      subDataDF3=DataDF.loc[1:9,'StockCode':'CustomerID']
      subDataDF3


      五、邏輯問(wèn)題需要篩選

      還是Dataframe.loc這個(gè)函數(shù)的知識(shí)點(diǎn)。

      由于loc還可以判斷條件是否為True

      DataDF.loc[:,'UnitPrice']>0

      一般來(lái)說(shuō)價(jià)格不能為負(fù),所以從邏輯上來(lái)說(shuō)如果價(jià)格是小于0的數(shù)據(jù)應(yīng)該予以篩出

      #刪除異常值:通過(guò)條件判斷篩選出數(shù)據(jù)
      #查詢條件
      querySer=DataDF.loc[:,'Quantity']>0
      #應(yīng)用查詢條件
      print('刪除異常值前:',DataDF.shape)
      DataDF=DataDF.loc[querySer,:]
      print('刪除異常值后:',DataDF.shape)

      六、格式一致化

      1. 大小寫(xiě)/去除空格

      將我們數(shù)據(jù)中所有的Descrption改成大寫(xiě):

      DataDF['Description']= DataDF['Description'].str.upper()

      類似的代碼還有 字符串修改方法:

      str().
      upper()
      lower()
      title()
      lstrip()
      strip()

      DataDF['Description']= DataDF['Description'].str.strip()

      2. 去除字符串符號(hào) 去亂碼

      3. 空格分割

      #定義函數(shù):分割I(lǐng)nvoiceDate,獲取InvoiceDate
      #輸入:timeColSer InvoiceDate這一列,是個(gè)Series數(shù)據(jù)類型
      #輸出:分割后的時(shí)間,返回也是個(gè)Series數(shù)據(jù)類型

      def splitSaletime(timeColSer):
      timeList=[]
      for value in timeColSer:
      #例如2018/01/01 12:50,分割后為:2018-01-01
      dateStr=value.split(' ')[0]
      timeList.append(dateStr)
      #將列表轉(zhuǎn)行為一維數(shù)據(jù)Series類型
      timeSer=pd.Series(timeList)
      return timeSer

      最后再賦值回去

      DataDF.loc[:,'InvoiceDate']=splitSaletime(DataDF.loc[:,'InvoiceDate'])

      七、處理缺失值

      python缺失值有3種:

      1)Python內(nèi)置的None值

      2)在pandas中,將缺失值表示為NA,表示不可用not available。

      3)對(duì)于數(shù)值數(shù)據(jù),pandas使用浮點(diǎn)值NaN(Not a Number)表示缺失數(shù)據(jù)。后面出來(lái)數(shù)據(jù),如果遇到錯(cuò)誤:說(shuō)什么float錯(cuò)誤,那就是有缺失值,需要處理掉

      所以,缺失值有3種:None,NA,NaN

      那None和NaN有什么區(qū)別呢:

      None是Python的一種數(shù)據(jù)類型,

      NaN是浮點(diǎn)類型

      兩個(gè)都用作空值

      1、去除缺失值

      # 再一次提醒檢查缺失數(shù)據(jù)

      DataDF.isnull().sum().sort_values(ascending=False)

      去除缺失值的知識(shí)點(diǎn):

      DataFrame.dropna

      DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

      # 默認(rèn)(axis=0)是逢空值剔除整行,設(shè)置關(guān)鍵字參數(shù)axis=1表示逢空值去掉整列
      # 'any'如果一行(或一列)里任何一個(gè)數(shù)據(jù)有任何出現(xiàn)Nan就去掉整行,
      ‘a(chǎn)ll’一行(或列)每一個(gè)數(shù)據(jù)都是Nan才去掉這整行

      DataDF.dropna(how='any')
      DataDF.dropna(how='all')

      # 更精細(xì)的thresh參數(shù),它表示留下此行(或列)時(shí),要求有多少[非缺失值]
      DataDF.dropna(thresh = 6 )

      2、填充缺失內(nèi)容:某些缺失值可以進(jìn)行填充,方法有以下四種:

      1) 以業(yè)務(wù)知識(shí)或經(jīng)驗(yàn)推測(cè)(默認(rèn)值)填充缺失值

      2) 以同一指標(biāo)的計(jì)算結(jié)果(均值、中位數(shù)、眾數(shù)等)填充缺失值

      3) 用相鄰值填充缺失值

      4) 以不同指標(biāo)的計(jì)算結(jié)果填充缺失值

      去除缺失值的知識(shí)點(diǎn):

      DataFrame.fillna

      https://pandas./pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html#pandas.DataFrame.fillna

      1) 用默認(rèn)值填充- df.fillna(' ')

      我們應(yīng)該去掉那些不友好的 NaN 值。但是,我們應(yīng)該用什么值替換呢?這個(gè)時(shí)候可能要結(jié)合你對(duì)這個(gè)數(shù)據(jù)集的理解,看填充什么數(shù)據(jù)才是比較合適,以下是一下常用的方法。

      在這個(gè)數(shù)據(jù)集中,我們大致判斷CustomerID如果是不太重要的,就我們可以用使用''空字符串或其他默認(rèn)值。

      DataDF.Country= DataDF.Country.fillna('Not Given')

      上面,我們就將“country”整個(gè)列使用“”空字符串替換了,或者,我們也可以輕易地使用“Not Given”這樣的默認(rèn)值進(jìn)行替換。

      如果想了解更多 fillna() 的詳細(xì)信息參考 pandas.DataFrame.fillna

      pandas.

      2) 以同一指標(biāo)的計(jì)算結(jié)果(均值、中位數(shù)、眾數(shù)等)填充缺失值

      平均值- df.fillna(df.mean())

      使用數(shù)字類型的數(shù)據(jù)有可能可以通過(guò)這樣的方法來(lái)去減少錯(cuò)誤。

      比如,這個(gè)案例里面的價(jià)格。如果用0或者'Not Given'等來(lái)去填充都不太合適,但這個(gè)大概的價(jià)格是可以根據(jù)其他數(shù)據(jù)估算出來(lái)的。

      DataDF.UnitPrice = DataDF.UnitPrice.fillna(DataDF.UnitPrice.mean())

      3)除此,還有一種常見(jiàn)的方法,就是用相鄰的值進(jìn)行填充,

      這在時(shí)間序列分析中相當(dāng)常見(jiàn),用前面相鄰的值向后填充,也可以用后面相鄰的值向前填充。

      print(DataDF)
      print(DataDF.UnitPrice.fillna(method='ffill')) # 前向后填充
      print(DataDF.UnitPrice.fillna(method='bfill')) # 后向前填充
      填充后

      4) 以不同指標(biāo)的計(jì)算結(jié)果填充缺失值

      關(guān)于這種方法年齡字段缺失,但是有屏蔽后六位的身份證號(hào)可以推算具體的年齡是多少。

      參考來(lái)源:

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多