Pandas如虎添翼!数据清洗新神器Pyjanitor

时间:2020-8-26 作者:admin

Pandas在数据分析领域已经是家喻户晓,成为了数据分析师最常使用的Python库之一。本文重点介绍与Pandas库相辅相成的另一个数据分析专用的Python库:Pyjanitor。

Pyjanitor可以在Pandas的基础上进一步简化数据预处理工作。数据预处理通常由一系列步骤组成,通过这些步骤,数据从原始杂乱的格式转化为我们业务所需的格式。在传统Pandas预处理步骤中,我们通过删除空数据行、添加新的列/重命名列/合并列、过滤行等一步步操作来完成。这些步骤是有依赖性的,我们通常称为有向无环图。

受到R语言中dplyr包易用性和表达能力的启发,现在Pyjanitor已经发展成为一种为Pandas用户进行数据处理的便捷实用的有向无环图方法。我们可以通过链式操作,更有逻辑顺序地用Pandas实现数据处理。让我们先来看一个示例吧ヽ(•̀ω•́ )ゝ

现在我们需要完成如下数据处理流程:

  1. 创建一个DataFrame。

  2. 删除一列。

  3. 在两个特定的列中删除具有空值的行。

  4. 重命名另外两列。

  5. 添加一个新列。

建立数据集。

import numpy as np
import pandas as pd
import 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导入dataframe
df = 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):

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

 

 

 

 

感谢观看_(•̀ω•́ 」∠)_


参考资源:pyjanitor: Clean APIs for Cleaning Data | SciPy 2019 | Eric Ma

本文代码:可关注公众号”数据科学与人工智能技术“并发送“Pyjanitor”,或添加微信paixiaoseng获取notebook文件

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。