1. 程式人生 > 實用技巧 >Pandas如虎添翼!資料清洗新神器Pyjanitor!

Pandas如虎添翼!資料清洗新神器Pyjanitor!

Pandas在資料分析領域已經是家喻戶曉,成為了資料分析師最常使用的Python庫之一。本文重點介紹與Pandas庫相輔相成的另一個數據分析專用的Python庫:Pyjanitor。

Pyjanitor可以在Pandas的基礎上進一步簡化資料預處理工作。資料預處理通常由一系列步驟組成,通過這些步驟,資料從原始雜亂的格式轉化為我們業務所需的格式。在傳統Pandas預處理步驟中,我們通過刪除空資料行、新增新的列/重新命名列/合併列、過濾行等一步步操作來完成。這些步驟是有依賴性的,我們通常稱為有向無環圖。

受到R語言中dplyr包易用性和表達能力的啟發,現在Pyjanitor已經發展成為一種為Pandas使用者進行資料處理的便捷實用的有向無環圖方法。我們可以通過鏈式操作,更有邏輯順序地用Pandas實現資料處理。讓我們先來看一個示例吧ヽ(•̀ω•́ )ゝ

現在我們需要完成如下資料處理流程:

  1. 建立一個DataFrame。
  2. 刪除一列。
  3. 在兩個特定的列中刪除具有空值的行。
  4. 重新命名另外兩列。
  5. 新增一個新列。

建立資料集。

import numpy as npimport pandas as pdimport janitor​company_sales = {    'SalesMonth': ['Jan', 'Feb', 'Mar', 'April'],    'Company1': [150.0, 200.0, 300.0, 400.0],    'Company2': [180.0, 250.0, np.nan, 500.0],    'Company3': [400.0, 500.0, 600.0, 675.0]}

對於Pandas“傳統流派”,這幾步操作可能是這樣的:

# 從dict匯入dataframedf = pd.DataFrame.from_dict(company_sales)# 從dataframe中刪除一列“Company1”del df['Company1']# 刪除有空值的資料行df = df.dropna(subset=['Company2', 'Company3'])# 更改列名df = df.rename(    {     'Company2': 'Amazon',     'Company3': 'Facebook',    },    axis=1,)# 新增新的一列df['Google'] = [450.0, 550.0, 800.0]df

稍微有鏈式思想的分析師的程式碼可能如下:

df = (    pd.DataFrame(company_sales)​    .drop(columns="Company1")    .dropna(subset=['Company2', 'Company3'])    .rename(columns={"Company2": "Amazon", "Company3": "Facebook"})    .assign(Google=[450.0, 550.0, 800.0])    )df

使用Pyjanitor的情況下,我們可以“謂語化”地以每一步的動作來進行鏈式操作:

df = (    pd.DataFrame.from_dict(company_sales)    .remove_columns(['Company1'])    .dropna(subset=['Company2', 'Company3'])    .rename_column('Company2', 'Amazon')    .rename_column('Company3', 'Facebook')    .add_column('Google', [450.0, 550.0, 800.0]))df

其中remove_columns、dropna、rename_column、add_column都是“謂語化”的方法,效果和傳統方法是一樣的。

Pyjanitor提供了一種方便的資料處理鏈來處理Pandas格式資料,而與傳統Pandas方法相比,Pyjanitor更加清晰簡便。在匯入原始資料的一開始,我們也可以用Pyjanitor進行全域性的初步預處理。現在我們有以下資料集:

company_sales2 = {    'First Name': ['Jason', 'Alicia', 'Ada', 'Desus'],    'Last Name': ['Bourne', 'Keys', 'Lovelace', 'Nice'],    'Full Time?': ['yes', 'yes', 'no', 'yes'],    'Allocated %': [0.75, 0.25, 1.0, 1.0],    'Certification': [np.nan, 'instr.music', 'PENDING', 'science 6-12'],    'Certification.1': ['Teacher', 'Vocal music', np.nan, 'Physics'],    'Certification.2': [np.nan, np.nan, np.nan, np.nan],    'Hire Date': [39690.0, 37118.0, 27515.0, 41431.0]}

可以看到,該資料集中的列名很混亂,不僅含有空格、存在“?”“%”等符號,還有空值列;Hire Date列為不標準的Timestamp格式;相同特徵Certification有三列(需要進行合併處理);最後需要新增新的屬性列並做log轉換。在用原始Pandas清洗該資料集時會用如下方法:

import datetime df2 = pd.DataFrame.from_dict(company_sales2)​df2 = df2.rename(             mapper={                'First Name': 'first_name',                'Last Name': 'last_name',                'Full Time?': 'is_full_time',                'Allocated %': 'percentage_allocated',                'Certification': 'certification',                 'Hire Date': 'hire_date'            },            axis=1)df2['hire_date'] = (    pd.TimedeltaIndex(df2['hire_date'], unit='d')    + datetime.datetime(1899, 12, 30))df2['certification'] = df2['certification'].combine_first(df2['certification.1'])​df2 = (    df2.drop(        ['certification.1', 'certification.2'],        axis=1        ))​gratitude_points = [10, 500, 1000, 300]df2 = df2.assign(gratitude_points=gratitude_points)df2['gratitude_log'] = df2['gratitude_points'].apply(np.log) df2

經過Pandas的方法,經過長長的程式碼,終於清洗完了,深呼一口氣~

下面來看看Pyjanitor是如何處理的:

gratitude_points = [10, 500, 1000, 300]​df2 = (    df2    .remove_empty()    .clean_names(strip_underscores=True)    .coalesce(column_names=['certification', 'certification_1'], new_column_name='certification', delete_columns=True)    .convert_excel_date('hire_date')    .rename_column('allocated_%', 'percentage_allocated')    .add_column('gratitude_points', gratitude_points)    .transform_column('gratitude_points', np.log, 'gratitude_log')) df2

經過幾行Pyjanitor操作,資料已經變成了和上面Pandas處理後相同的效果。可以看到,Pyjanitor可以鏈式地“謂語化”地結合Pandas高效處理資料,怎麼樣?高大上吧(•̀ω•́)✧

另外Pyjanitor也可以方便地對特徵進行拆分與合併,用到的方法是concatenate_columns()和deconcatnate_column():

# 因為該方法是對字串操作,所以特意新加入一列字串格式的日期特徵df2['hire_date_str'] = df2['hire_date'].astype(str)df2 = (    df2    .deconcatenate_column(        column_name='hire_date_str',        new_column_names=['year', 'month', 'day'],        sep='-',        preserve_position=False    )) df2

現在新生成了三列特徵year、month、day,相比於Pandas的str.split方法,此種方法可以直接將新生成的特徵列加入到Dateframe中。

還有更多的Pyjanitor內容以及可生成“自定義”Pandas方法的pandas-flavor庫,這些就留給大家自己去探索了!看完有沒有覺得Pyjanitor很實用呢?快去自己的專案裡試試手吧ヽ(•̀ω•́ )ゝ

Pyjanitor安裝方法(注意是pyjanitor而不是janitor):

# pippip install pyjanitor# pip清華源pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyjanitor# condaconda install pyjanitor -c conda-forge

原始碼獲取記得加下我的交流群哦:1136192749