Python數(shù)據(jù)分析常用API整理

整理歸納在Python中使用對(duì)數(shù)據(jù)處理的常用方法,包括與HDFS文件的讀寫,主要是怕用的時(shí)候記不住,容易搞混,再搜也不爽,好記性不如爛筆頭,寫下來自己用的時(shí)候方便看,而且寫一遍也加深印象。
隨查隨用隨更新

Numpy

ndarray

ndarr1 = np.array([ [1, 2, 3], [4, 5, 6] ])
shape 大小和形狀
dtype 數(shù)據(jù)類型
astype 顯式的轉(zhuǎn)換類型
不同大小的ndarray也可以運(yùn)算,稱之為廣播,比如arr * 2
一維:用[x]進(jìn)行索引,用[x:y]進(jìn)行切片,都是原始數(shù)組的視圖
多維:[x][y]或者[x,y]索引,[x1:x2, y1:y2]切片
布爾型可以直接做索引

按軸進(jìn)行布爾類型list的索引,或者對(duì)每個(gè)元素進(jìn)行單個(gè)布爾索引,比如data1[data1 > 0] = 0

花式索引行和列

arr[ [行1, 行i] ][ :, [列1, 列i] ] 或者
arr[ np.ix_( [行1, 行i], [列1, 列i] ) ]
而且花式索引總是復(fù)制數(shù)據(jù)到新的數(shù)組中,不是切片那種原始數(shù)組的視圖

arr.T 轉(zhuǎn)置
通用函數(shù)

np.sqrt(arr) arr的開平方
np.exp(arr) arr的e的x次方
np.abs(arr) arr的絕對(duì)值
np.square(arr) arr的平方
np.log(arr) ln(arr)
np.log10(arr) log10(arr)
np.isnan arr的各個(gè)元素是否為NaN的bool數(shù)組
np.add(arr1, arr2) arr1 + arr2
np.subtract(arr1, arr2) arr1 - arr2

三元表達(dá)式
np.where(cond, xarr, yarr) 等價(jià)為 xarr if cond else yarr
統(tǒng)計(jì)

arr.sum(axis=?) 按照軸的方向求和
arr.mean 按照軸的方向求平均值
arr.min()和max() 最大和最小值
arr.argmin()和argmax() 最大和最小值的索引
arr.cumsum() 所有元素的累計(jì)和
arr.cumprod() 所有元素的累計(jì)積
排序
np.sort(arr)和arr.sort(),前者是頂級(jí)方法,返回對(duì)arr排序后的副本;后者則是直接對(duì)arr排序。

線性代數(shù)
包括矩陣的點(diǎn)乘,矩陣分解以及行列式等等。
點(diǎn)乘:xarr.dot(yarr)等價(jià)于np.dot(xarr, yarr)
numpy.linalg中有一組標(biāo)準(zhǔn)的矩陣分解運(yùn)算以及諸如求逆和行列式之類。比如如下部分:

diag([一維數(shù)組]) 對(duì)角矩陣,對(duì)角線是輸入的一維數(shù)組
dot 點(diǎn)乘
det 計(jì)算矩陣的行列式
inv 計(jì)算矩陣的逆
qr 計(jì)算QR分解
svd 計(jì)算奇異值分解(SVD)

Pandas

(官網(wǎng))https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html
官網(wǎng)Pandas的API匯總
官網(wǎng)10分鐘對(duì)Pandas的簡介

Series

可以把Series看成是一個(gè)有序的定長字典。
ser = Series([1, 2, 3, 4], index=['d', 'b', 'a', 'c'])
經(jīng)常存在與DataFrame的行與列中。
也可以直接從字典類型的對(duì)象中構(gòu)建。
idx_val_map = {'d':1, 'b':2, 'a':3, 'c':4}
ser = Series(idx_val_map, name='值的名稱')
ser.index.name = '索引的名稱'
ser['a']進(jìn)行索引
再進(jìn)一步,比如對(duì)于二維的DataFrame,取其中一列出來,就是Series,它的name就是這一列的名字,它的index就是DataFrame的index,index的name就是DataFrame中作為index的那一列的名字。

DataFrame

DataFrame的索引是不可更改的。可以添加和刪除,但是不能修改。

  • 構(gòu)造DataFrame
    1.由二維ndarray構(gòu)造,可以給出行標(biāo)和列標(biāo)
    result1 = pd.DataFrame([[1, 0.7], [0, 0.7]], index=pd.Index([135, 136], name='Number'), columns=['Gender', 'Prob'])
    
    2.由字典構(gòu)成,外層字典key是列標(biāo),內(nèi)層字典是行標(biāo)
    需要注意的是字典構(gòu)成的df,需要指定column的順序,否則默認(rèn)會(huì)按照列的字符串名排序
predict_df = pd.DataFrame(data={'svc_y': svc_y, 'dnn_y': dnn_y, 'xgb_y': xgb_y, 'rf_y': rf_y}, columns=['svc_y', 'dnn_y', 'xgb_y' ,'rf_y'])

3.由另一個(gè)DataFrame構(gòu)成
有時(shí)候會(huì)有一種需求是從已經(jīng)有的DataFrame中創(chuàng)建一個(gè)空的Dataframe但是使用的是原來這個(gè)Dataframe的結(jié)構(gòu)。

copy_df = pd.DataFrame.from_items([(name, pd.Series(data=None, dtype=series.dtype)) 
                                    for name, series in original_df.iteritems()])
  • 添加列

    frame['new-col'] = value
    # 需要添加多列時(shí)比較特殊點(diǎn)需要借Dataframe來賦值
    frame[['new-col1', ..., 'new-coln']] = pd.Dataframe(np.random.randint(1,5,[n_rows, n]), index=frame.index)
    
  • 添加行

    s = pd.Series({'Col1':'Value1', 'Col2': 'Value2', 'Col3': Value3})  # 構(gòu)造一行新數(shù)據(jù)
    frame.append(s)
    
  • 刪除列

    del frame['col-name']
    
  • 刪除行

    # 因?yàn)镈ataFrame是列索引的(在frame.items()返回值中可以看出來)所以del只能刪除列,刪除行需要用到drop方法
    frame.drop(frame.index[[1,3]])
    
  • 索引方式
    列索引:frame['col_name']或者frame.col_name
    行索引:frame.ix['row_name']
    點(diǎn)索引:frame.at[行,列] 或者frame.iat[行i,列i],只能索引具體的元素,不能切片
    用整數(shù)位置索引frame.iloc[index(列表), col-index(列表)]
    ix[行, 列]和iloc[行, 列]都可同時(shí)索引行與列,區(qū)別在于ix用的是名字(當(dāng)DataFrame的index沒有設(shè)置時(shí),退化成iloc),iloc用的是整數(shù)位置
    loc: works on labels in the index.
    iloc: works on the positions in the index (so it only takes integers).
    ix: usually tries to behave like loc but falls back to behaving like iloc if the label is not in the index.

    • 總結(jié)
      ['col-name']——是對(duì)列的索引
      [ ['col-name1', 'col-name_i'] ]——兩個(gè)[]是對(duì)多個(gè)列的索引
      [bool類型list]或者[i:j]——是對(duì)行的切片索引
      ix[行,列]——支持對(duì)行和列同時(shí)索引和切片(loc和iloc參考上面)NOTE:ix操作如果有左值,那么就默認(rèn)會(huì)copy,如果沒有左值那么就是對(duì)原始Frame進(jìn)行操作,而loc和iloc默認(rèn)都是對(duì)原始Frame的操作,所以推薦使用loc,如果需要復(fù)制,可以顯式的調(diào)用Frame.copy(). 不過仍要注意的是frame2 = frame1.loc[a:d, :]確實(shí)不是復(fù)制是對(duì)原frame1的切片,但是frame1.loc[ [a, b, c, d], :]則是復(fù)制不是切片了。
      at[行,列]和iat[i,j]——是定位到元素
      所以對(duì)列的bool類型list切片應(yīng)該用ix[:,bool_list],然而對(duì)行的bool類型list切片可以直接[bool_list]
  • 基本功能

    • 重新索引
      reindex,對(duì)索引重新排序,新加的使用缺失值填充。

    • 丟棄指定軸上的項(xiàng)
      frame.drop(['name'], axis=?)

    • 切片
      frame[:2] 這個(gè)是直接按行切片,和常識(shí)有點(diǎn)不太一樣,但是方便實(shí)際操作。
      frame[ ['列1', '列i'] ],這個(gè)是按列切片

    • 過濾
      按照某一列的值過濾:frame[ frame['列'] > 5 ]
      對(duì)于bool類型的list,除了上面的方法,也可以frame.loc[bool_list_X, bool_list_Y]進(jìn)行過濾。

    • 算術(shù)運(yùn)算
      frame1 + frame2 或者 frame1.add(frame2, fill_value=0)
      sub做減法 div是除法 mul是乘法

    • 函數(shù)應(yīng)用和映射
      Numpy的ufuncs也可用于操作pandas對(duì)象

      np.abs(frame)

      還可以自定義函數(shù)(列或行的):

      f = lambda x: x.max() - x.min()
      frame.apply(f, axis=?)

      對(duì)元素的函數(shù)

      format = lambda x: '%.2f' % x
      frame.applymap(format)

      featQuant = sampleDF_feat.quantile(0.999) # 獲得0.999的分位數(shù)
      frameFeatUnderQuant = sampleDF_feat.where(sampleDF_feat <= featQuant, other=0) # 把異常高的數(shù)值排除掉

      總的來說,DataFrame可以用的是apply和applymap,Series可以用的是map:

      apply:是對(duì)DataFrame的具體行或者列進(jìn)行整體操作。比如可以取最大最小值
      applymap:是對(duì)DataFrame的具體每個(gè)元素進(jìn)行操作。
      map:也是對(duì)每個(gè)元素進(jìn)行操作,和applymap類似。

    • 排序
      frame.sort_index(by='name', axis=?, ascending=True)

  • 匯總和計(jì)算描述

    frame.sum(axis=?, skipna=True) 求和
    frame.mean() 平均值
    frame.count()
    frame.min、max
    frame.argmin、argmax 整數(shù)索引位置
    frame.idmin、idmax 名字ID索引位置
    frame.quantile() 計(jì)算樣本的分位數(shù)(0到1),比如frame['col_name'].quantile([q/10 for q in range(1, 11, 1)])
    frame.describe() # 描述各個(gè)列的詳細(xì)統(tǒng)計(jì)信息
    frame.info() # 描述各個(gè)列是否有缺失值和dtype
    frame['col_name'].value_counts() # 計(jì)算得到col_name列上各種取值的個(gè)數(shù)

    • groupby
      這個(gè)操作是對(duì)數(shù)據(jù)做聚合后的操作。
      比如df['col1'].groupby(by=某種依據(jù)),就是在df的'col'列上按照某種依據(jù)來聚合,產(chǎn)生一個(gè)DataFrameGroupBy對(duì)象。這里的某種依據(jù)就是告訴pandas在聚合時(shí)哪幾個(gè)數(shù)據(jù)屬于一類的,比如df的行數(shù)為7,那么某種依據(jù)為['c','s','t','t','s','s','c'],會(huì)把第一行和最后一行歸在一起,第2\5\6行歸在一起,第3\4行歸在一起。
      此時(shí)可以使用mean(),sum(),apply()這樣的操作來得到想要的值。當(dāng)對(duì)df['col1']做groupby時(shí)得到的每一項(xiàng)是Series,此時(shí)apply(lambda x: ...)中的x是Series類型;當(dāng)對(duì)df[['col1',...,'colN']]做groupby時(shí)得到的是Dataframe,此時(shí)apply(lambda x: ...)中的x是DataFrame類型。
      比如對(duì)df['cnt']表示某個(gè)用戶購買某個(gè)物品的個(gè)數(shù),我們想得到每個(gè)用戶各自購買物品占自己購買總數(shù)的比值時(shí):df['cnt'].groupby(df['user_name']).apply(lambda cnts: cnts.apply(lambda n: n / cnts.sum()))
      另外df.groupby(...).agg(func)是指對(duì)df做group之后對(duì)每一列執(zhí)行func,如果不需要對(duì)每列執(zhí)行,則直接使用apply即可。agg的詳細(xì)示例見:官網(wǎng)agg
    • melt
      這個(gè)是讓df按照指定的列消融,比如df有3列,直接melt(),會(huì)得到新的melt_df由index, variable, value這三個(gè)列組成,其中index的范圍是原來的3倍,variable是原來的列名,value是原來對(duì)應(yīng)列的值。
      melt()函數(shù)有幾個(gè)參數(shù):id_vars='不消融的列', value_vars=消融的列l(wèi)ist, var_name='消融后variable的名字', value_name='消融后value的名字'
  • 處理缺失數(shù)據(jù)

    frame.dropna() 丟棄NaN,可以給出閾值進(jìn)行調(diào)節(jié)容忍度
    df.fillna( {'列1': 值1, '列i': 值i}, inplace=True ) 默認(rèn)返回一個(gè)新的對(duì)象
    frame.isnull() 返回與frame一樣大小的布爾值對(duì)象(值為NaN的為True,否則為False)

  • 其他常用

    # 去重
    df.duplicated(keep='first')  # 這個(gè)會(huì)返回列的值重復(fù)與否的布爾值,默認(rèn)對(duì)于重復(fù)值的第一個(gè)為False,其他重復(fù)的為True
    # 得到這個(gè)布爾后可以再進(jìn)行切片去重,不過還有更便捷的方法:
    df['某列'].drop_duplicates(keep='first', inplace=True)  # 這樣直接得到去重后的結(jié)果。
    
  • 從文件中讀取
    frame = pd.read_csv('file.csv', names=col_names, index_col='col_index')
    另外說下,如果csv的文件中是這樣的0,1,2,"string:\"(1,2)\"",那么上面在讀的過程中會(huì)有問題,多讀出一列,需要加上參數(shù)escapechar="\\",也就是:
    frame = pd.read_csv('file.csv', names=col_names, index_col='col_index', escapechar="\\")
    除了讀取本地文件還可以讀取HDFS文件:

    首先需要安裝需要的包:pip install hdfs 官網(wǎng)文檔
    然后代碼中:

    from hdfs import Client
    from hdfs import HdfsError
    
    client = Client('http://name_node.url:50070')  # 輸入要鏈接的NameNode地址。如果是高可用的模式,會(huì)有多個(gè)name node,那么有個(gè)比較笨的方法就是挨個(gè)試,看看那個(gè)可用(也就是處于active狀態(tài))就用哪個(gè)。
    
    print(client.list('/'))  # 可以在這里添加try操作,catch到異常后去嘗試下一個(gè)name node的鏈接。
    
    try:
        with client.read('path/file.csv') as hdfs_in_fs:
            predictDF = pd.read_csv(hdfs_in_fs, names=predict_cols, index_col='Number')
    except HdfsError as e:
        print(e)
    
  • 將Frame寫入文件
    frame.to_csv(path_or_buf='path/file', index=True, header=False, sep='|')
    寫入HDFS文件會(huì)有些麻煩,一是寫的時(shí)候需要權(quán)限,把要寫入的目錄設(shè)置為hdfs dfs -chmod -R 777 write_Dir;二是寫入文件會(huì)遇到TypeError: a bytes-like object is required, not 'str',因?yàn)椴幌衿胀ǖ奈募梢栽趏pen的時(shí)候設(shè)置mode參數(shù),所以還需要做如下操作:

    from hdfs import Client
    from hdfs import HdfsError
    
    client = Client('http://name_node.url:50070')  # 輸入要鏈接的NameNode地址。如果是高可用的模式,會(huì)有多個(gè)name node,那么有個(gè)比較笨的方法就是挨個(gè)試,看看那個(gè)可用(也就是處于active狀態(tài))就用哪個(gè)。
    
    print(client.list('/'))  # 可以在這里添加try操作,catch到異常后去嘗試下一個(gè)name node的鏈接。
    
    try:
        with client.write('path/file' overwrite=True, encoding='utf-8') as hdfs_out_fs:  # 需要設(shè)置encoding不然遇到上面說的TypeError
            predictDF[['Gender', 'Prob']].to_csv(path_or_buf=hdfs_out_fs, index=True, header=False, sep='|')
    except HdfsError as e:
        print(e)
    
  • 另外一種讀寫HDFS文件的方法
    上面的代碼確實(shí)可以讀寫HDFS文件,不過需要修改權(quán)限,這會(huì)出現(xiàn)下面情況:

    可以看到為了允許讀寫,上級(jí)目錄已經(jīng)將權(quán)限更改為全部可讀寫執(zhí)行了,而且新創(chuàng)建的文件夾和文件都是用戶dr.who

    這會(huì)給后續(xù)操作帶來一定的麻煩,比如yarn用戶在程序中對(duì)這個(gè)文件無法修改。因?yàn)橹挥凶x權(quán)限。
    不過還有一個(gè)API可以在python中使用,如果你的HDFS配置支持非安全的HttpFS的話。

    Client API介紹

    上面的使用Client的API是用的WebHDFS。連接的時(shí)候需要指定namenode,而在高可用的模式情況下,可能要多試幾次才知道當(dāng)前哪個(gè)node處于active狀態(tài)。為了避免這兩個(gè)問題,接下來展示另外一個(gè)API InsecureClient來實(shí)現(xiàn)。在接下來的代碼中,使用的是HttpFS方式來讀寫HDFS

    from hdfs import InsecureClient
    
    client = InsecureClient('http://HttpFS_node.url:14000', user='yarn')  # 使用HttpFS所配置的角色主機(jī)域名及REST 端口
    
    print(client.list('/'))  # 無需像之前一樣多次嘗試當(dāng)前輸入的namenode是否可用
    
    with client.read('path/in_file') as hdfs_in_fs:
        with client.write('path/out_file', overwrite=True, encoding='utf-8') as hdfs_out_fs:
            sampleDF = pd.read_csv(hdfs_in_fs, names=, index_col=)
            sampleDF.to_csv(path_or_buf=hdfs_out_fs, index=True, header=False, sep='|')
    

    這個(gè)API的好處是:1、不需要修改權(quán)限,由參數(shù)的指定用戶保證權(quán)限沒問題。2、新寫入的文件權(quán)限也無問題。3、可以支持遠(yuǎn)程讀寫,無需在集群上執(zhí)行,在本地PC上運(yùn)行即可。4、無需知道當(dāng)前active的namenode是哪個(gè),可以通過HttpFS主機(jī)直接連接。

    新建的文件都是用戶yarn的
  • 合并數(shù)據(jù)集

    • pandas.merge
      根據(jù)一個(gè)或多個(gè)鍵將不同的DataFrame中的行連接起來。類似SQL的關(guān)系型數(shù)據(jù)庫的連接操作
      簡單說就是將多個(gè)DataFrame按照指定的各自的列以某種方式(inner,left,right,outer)組合起來。
      除了pd.merge還有frame_left.join(frame_right)這個(gè)方式
      其中join和merge的區(qū)別如下:
    left.join(right, on='col_name') #是將left的col_name列和right的index進(jìn)行比較連接,且默認(rèn)how='left'
    left.merge(right, on='col_name') #是將left和right共有的col_name列進(jìn)行比較連接,且默認(rèn)how='inner'
    # 不過如果right中如果沒有col_name列,那么還是會(huì)和join一樣會(huì)拿index來連接.
    # 另外merge還提供了left_on/right_on/left_index/right_index這些參數(shù)供選擇
    
    • pandas.concat
      沿著一條軸將多個(gè)對(duì)象堆疊在一起
      比如將兩個(gè)frame的行數(shù)據(jù)堆疊起來。
      frame_total = pd.concat([frame1, framei], axis=?, keys=['col1_name', 'coli_name'])
    • 舉栗
      合并Series到Dataframe中:
      purchase_1 = pd.Series({'Name': 'Chris',
                          'Item Purchased': 'Dog Food',
                          'Cost': 22.50})
      purchase_2 = pd.Series({'Name': 'Kevyn',
                          'Item Purchased': 'Kitty Litter',
                          'Cost': 2.50})
      purchase_3 = pd.Series({'Name': 'Vinod',
                          'Item Purchased': 'Bird Seed',
                          'Cost': 5.00})
      df = pd.DataFrame([purchase_1, purchase_2, purchase_3], index=['Store 1', 'Store 1', 'Store 2'])
      
      s = pd.Series({'Name':'Kevyn', 'Item Purchased': 'Kitty Food', 'Cost': 3.00})
      s.name = 'Store 2'
      
      # 合并s到df中
      # 方法1,使用concat函數(shù)
      df = pd.concat([df, s.to_frame().T])
      # 方法2,使用append
      df = df.append(s)
      
  • 打印DataFrame
    打印DataFrame非常簡單直接print就可以了,但是Pandas對(duì)于顯示的行數(shù)、列數(shù)、寬度和長度都有默認(rèn)限制,如果不期望看到...這樣的省略號(hào),或者不期望換行,那么可以如下設(shè)置:
    在最近的pandas版本中,已經(jīng)沒有display.height這個(gè)參數(shù)了,其值可由display.max_rows自動(dòng)推斷得到。

    pd.set_option('display.height',1000)  # 把1000換成None即為無限制,下面均是如此。
    pd.set_option('display.max_rows',500)
    pd.set_option('display.max_columns',500)
    pd.set_option('display.width',1000)
    

    上面的設(shè)置完之后會(huì)對(duì)后面的代碼全部做這個(gè)配置處理,如果想在代碼中動(dòng)態(tài)的改變,還可以這么寫:

    with pd.option_context('display.max_rows', None, 'display.max_columns', None, 'display.width', None):
        logging.info('輸出打印DataFrame:\n{}'.format(data_frame))
    

    這樣在需要長顯示的時(shí)候套上with就可以了,不需要的地方繼續(xù)使用pandas的默認(rèn)設(shè)置。

pandas的通用功能(官鏈)

pandas提供了很多general function來支持很多數(shù)據(jù)操作。比如上面提到過的pandas.melt還有其他經(jīng)常用到的pandas.concat, pandas.merge, pandas.unique等,下面會(huì)介紹一些其他常用的功能:

  • pd.cut
    我們有時(shí)會(huì)需要把連續(xù)數(shù)值轉(zhuǎn)換為類別,比如根據(jù)取值的大小按照某種分隔標(biāo)準(zhǔn)來劃分成類別。
    更明確些,我們可能有兩種劃分依據(jù),在pandas中均能找到對(duì)應(yīng)的函數(shù):1、按照取值來劃分,比如某個(gè)特征取值從0到1,我們希望按照這個(gè)取值范圍分成3等份,那么就可以用pd.cut;2、按照統(tǒng)計(jì)的個(gè)數(shù)來劃分,比如根據(jù)樣本在這個(gè)特征上的取值所統(tǒng)計(jì)的個(gè)數(shù),分為好中差三個(gè)等樣本個(gè)數(shù)的分類,這時(shí)可以用pd.qcut;
    下面簡單介紹下幾個(gè)常用參數(shù)
    pd.cut(x=連續(xù)取值的數(shù)據(jù), bins=整數(shù)N(會(huì)自動(dòng)按照上下限的取值份N等份)/數(shù)組(會(huì)按照數(shù)組指示的間隔來劃分), labels=劃分后的標(biāo)記)
    比如X的取值是0到1,希望按照(0, 0.25](0.25, 0.5](0.5, 0.75](0.75, 1]劃分成4份,且對(duì)應(yīng)的label分別是1到4:
    pd.cut(X, bins=[i*1.0/4 for i in range(0, 4+1)], labels=range(1,4+1))

  • pd.qcut
    介紹幾個(gè)常用的參數(shù)
    pd.cut(x=連續(xù)取值的數(shù)據(jù), q=整數(shù)N(會(huì)自動(dòng)按照統(tǒng)計(jì)分位數(shù)分N等份)/數(shù)組(會(huì)按照數(shù)組指示的間隔來劃分), labels=劃分后的標(biāo)記)
    比如q = [0, .25, .5, .75, 1.] for quartiles
    pd.qcut(range(5), 3, labels=["good", "medium", "bad"])

    ... 
    [good, good, medium, bad, bad]
    Categories (3, object): [good < medium < bad]
    
  • pd.get_dummies
    這個(gè)是對(duì)類別特征做one-hot編碼,比如pd.get_dummies(df, columns=df.columns)
    但是有個(gè)點(diǎn)需要注意下,比如現(xiàn)在有訓(xùn)練集和測(cè)試集,其中訓(xùn)練集中可能某個(gè)類別沒有在測(cè)試集中出現(xiàn),或者測(cè)試集中的某個(gè)類別沒有在訓(xùn)練集中出現(xiàn)。此時(shí)如果分別對(duì)它們做get_dummies就會(huì)出現(xiàn)得到的數(shù)據(jù)集的列對(duì)不起來。
    此時(shí)需要做的是,保證訓(xùn)練集中的列一定都會(huì)出現(xiàn),對(duì)于測(cè)試集中沒有包含訓(xùn)練集的列添加并值為0,對(duì)于測(cè)試集中含有訓(xùn)練集中沒有的去除,并保證兩個(gè)數(shù)據(jù)集的列順序一致。

df_train_onehot = pd.get_dummies(train_df, columns=train_df.columns)
train_oh_cols = df_train_onehot.columns
df_test_onehot = pd.get_dummies(test_df, columns=test_df.columns)
test_oh_cols = df_test_onehot.columns
miss_cols = set(train_oh_cols) - set(test_oh_cols)
for col in miss_cols:
    df_test_onehot[col] = 0
df_test_onehot = df_test_onehot[train_oh_cols]

除了上面這個(gè)做法外,還可以利用sklearn的OneHotEncoder來實(shí)現(xiàn)。
ohe = OneHotEncoder(sparse=False, handle_unknown='ignore')
然后在ohe.fit_transform(train_df)接著ohe.transform(test_df)即可,不過ohe返回的值都是np.ndarray類型,如果需要?jiǎng)t自己命名列的名字。
第一種方法要保存的是訓(xùn)練集的列名,第二種方法則要把fit后的ohe模型保留下來。

Matplotlib

常用作圖方法

import matplotlib.pyplot as plt
%matplotlib inline  # 在ipynb上顯示圖片

plt.plot([4, 3, 2, 1])  # 作圖代碼
plt.show()  # 在python運(yùn)行程序時(shí)顯示

# 啟動(dòng)ipython作圖時(shí)可以: ipython --pylab,這樣就會(huì)自動(dòng)import matplotlib.pyplot as plt而且不用show()就可以輸出圖表。
plt.plot([4, 3, 2, 1])  # 使用ipython --pylab后直接顯示圖圖表

直接用數(shù)據(jù)作圖

  • 對(duì)于numpy的數(shù)組數(shù)據(jù)作圖:
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
plt.plot([1.5, 3.5, -2, 1.6])  # 默認(rèn)對(duì)最后創(chuàng)建的subplot作圖
import numpy as np
from numpy.random import randn
_ = ax1.hist(randn(100), bins=20, color='k', alpha=0.3)  # 直方圖
ax2.scatter(np.arange(30), np.arange(30) + 3 * randn(30))  # 散列圖
默認(rèn)畫圖,直方圖和散列圖
  • 強(qiáng)調(diào)數(shù)據(jù)點(diǎn)
plt.plot(randn(30).cumsum(), 'ko--')  # 等價(jià)于下面語句
plt.plot(randn(30).cumsum(), color='k', linestyle='dashed', marker='o')
強(qiáng)調(diào)數(shù)據(jù)點(diǎn)位置
  • 圖中坐標(biāo)和標(biāo)題設(shè)置
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(randn(1000).cumsum())
ticks = ax.set_xticks([0, 250, 500, 750, 1000])  # 設(shè)置X軸的刻度
labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], rotation=30, fontsize='small')  # 刻度的標(biāo)簽
ax.set_title('My first matplotlib plot')  # 圖的標(biāo)題
ax.set_xlabel('Stages')  # X軸的名稱
設(shè)置坐標(biāo)軸的信息和圖標(biāo)題
  • 添加圖例
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(randn(100).cumsum(), 'k', label='one')  # 創(chuàng)建圖例
ax.plot(randn(100).cumsum(), 'g--', label='two')
ax.plot(randn(100).cumsum(), 'r.', label='three')
ax.legend(loc='best')  # 把上面設(shè)置的圖例(legend)創(chuàng)建生效
圖例
  • 保存圖表到文件
plt.savefig('figpath.svg')
plt.savefig('figpath.png', dpi=400, bbox_inches='tight')

Pandas的繪圖函數(shù)

  • Series做柱狀圖
import pandas as pd
from pandas import Series, DataFrame
fig, axes = plt.subplots(nrows=2, ncols=1)  # 獲得subplot集合
data = Series(np.random.rand(16), index=list('abcdefghijklmnop'))
data.plot(kind='bar', ax=axes[0], color='k', alpha=0.7)  # 豎向柱狀圖,不設(shè)置kind默認(rèn)是線形圖
data.plot(kind='barh', ax=axes[1], color='k', alpha=0.7)  # 橫向柱狀圖
Series柱狀圖
  • DataFrame做柱狀圖
df = DataFrame(np.random.rand(6, 4),
              index=['one', 'two', 'three', 'four', 'five', 'six'],
              columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus'))
print(df)
df.plot(kind='bar')

df數(shù)據(jù)打?。?/em>
Genus A B C D
one 0.017426 0.964258 0.479931 0.636357

two 0.020693 0.979753 0.846889 0.436802
three 0.650068 0.608675 0.964375 0.866141
four 0.523848 0.610598 0.296204 0.879183
five 0.419329 0.023081 0.442044 0.842727
six 0.926948 0.454734 0.436056 0.970364

DataFrame的柱狀圖
  • 直方圖和密度圖
comp1 = np.random.normal(0, 1, size=200)  # N(0, 1)
comp2 = np.random.normal(10, 2, size=200) # N(10, 4)
values = Series(np.concatenate([comp1, comp2]))  # 合并為一個(gè)Series
values.hist(bins=100, alpha=0.3, color = 'k', normed=True)  # 直方圖
values.plot(kind='kde', style='k--')  # 密度圖(kde表示標(biāo)準(zhǔn)混合正態(tài)分布)
直方圖和密度圖
  • 散布圖
plt.scatter(trans_data['m1'], trans_data['unemp'])  # 散布圖
plt.title('Changes in log %s vs. log %s' % ('m1', 'unemp'))
散布圖
pd.plotting.scatter_matrix(trans_data, diagonal='kde', color='k', alpha=0.3)  # 散布圖矩陣
散布圖矩陣
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容