资源经验分享Python数据清洗终极指南

Python数据清洗终极指南

2020-03-26 | |  47 |   0

原标题: Python数据清洗终极指南

来源:AI研习社   链接:https://www.yanxishe.com/TextTranslation/2415


在拟合机器学习或统计模型之前,我们总是要清理数据。没有一个模型能用凌乱的数据产生有意义的结果。

数据清理或清除是指从记录集、表或数据库中检测和纠正(或删除)损坏或不准确的记录的过程,指识别数据中不完整、不正确、不准确或不相关的部分,然后替换、修改或删除脏的或粗糙的数据。


多长的定义啊!这当然不好玩也不费时。

1585193793216915.png

为了更简单,我们在Python中创建了这个新的完整的分步指南。您将学习如何查找和清理的技巧:

  • 丢失的数据

  • 不规则数据(异常值)

  • 不必要的数据-重复数据、重复数据等

  • 不一致的数据-大小写、地址等

在本指南中,我们使用来自Kaggle的俄罗斯住房数据集。该项目的目标是预测俄罗斯的房价波动。我们不会清理整个数据集,但会显示其中的示例。

在我们开始清理之前,让我们先简要地看一下数据。

03.png  

从这些结果中,我们了解到数据集有30471行292列。我们还确定特征是数值变量还是分类变量。这些都是有用的信息。
现在我们可以查看“脏”数据类型的清单,并逐个修复它们。
我们开始吧。

丢失的数据


处理丢失的数据/值是数据清理中最棘手但最常见的部分之一。虽然许多模型可以处理数据的其他问题,但大多数模型不接受丢失的数据。

怎么知道?

我们将介绍三种技术,以进一步了解数据集中丢失的数据。



  • 技术1:缺少数据热力图

当特征数量较少时,我们可以通过热力图可视化丢失的数据。

cols = df.columns[:30] # first 30 columns    colours = ['#000099', '#ffff00'] # specify the colours - yellow is missing. blue is not missing.    sns.heatmap(df[cols].isnull(), cmap=sns.color_palette(colours))

下面的图表演示了前30个特性的缺失数据模式。水平轴显示要素名称;垂直轴显示观测值/行数;黄色表示缺少的数据,蓝色表示缺少的数据。

例如,我们看到life-sq特性在许多行中缺少值。而floor特性在第7000行附近几乎没有缺少值。

04.png

  缺失值数据热力图

  • 技术2:缺失数据百分比表

当数据集中有许多功能时,我们可以为每个功能列出丢失的数据百分比。

# if it's a larger dataset and the visualization takes too long can do this.    # % of missing.    for col in df.columns:    
    pct_missing = np.mean(df[col].isnull())    
    print('{} - {}%'.format(col, round(pct_missing*100)))

这将在下面生成一个列表,显示每个功能的丢失值的百分比。

具体地说,我们看到life-sq功能丢失了21%,floor只丢失了1%。此列表是一个有用的摘要,可以补充热图可视化。

05.png  

缺少数据%列表 - 前30个特征

技术3:缺失数据直方图

当我们有很多特征时,丢失数据直方图也是一种技术。

为了了解更多关于观测值丢失模式的信息,我们可以用直方图将其可视化。

06.png

  此直方图有助于识别30471个观测值中的缺失值情况。


例如,有6000多个观测值没有丢失,近4000个观测值有一个丢失。

07.png

  缺少数据直方图怎么办?

对于处理丢失的数据,没有达成一致的解决方案。我们必须研究特定的特征和数据集,以确定处理它们的最佳方式。
下面介绍了处理丢失数据的四种最常见方法。但是,如果情况比平常更复杂,我们需要有创意地使用更复杂的方法,比如缺失数据建模。

  • 解决方案1:放弃观察

在统计学中,这种方法被称为列表删除技术。在这个解决方案中,只要包含一个丢失的值,我们就删除整个观测值。
只有当我们确信丢失的数据没有提供信息时,我们才能执行此操作。否则,我们应该考虑其他解决办法。
可以使用其他标准来删除观察结果。
例如,从丢失的数据直方图中,我们注意到总共丢失35个以上特征的观测数据非常少。我们可以创建一个新的数据集df_less_missing_rows,删除具有35个以上丢失特征的观测值。

# drop rows with a lot of missing values.    
ind_missing = df[df['num_missing'] > 35].index    
df_less_missing_rows = df.drop(ind_missing, axis=0)

解决方案2:删除特征


与解决方案1类似,我们只在确信此功能不提供有用信息时才执行此操作。

例如,从丢失数据百分比列表中,我们注意到医院床位的丢失值百分比高达47%。我们可以删除整个功能。

# hospital_beds_raion has a lot of missing.    
# If we want to drop.    
cols_to_drop = ['hospital_beds_raion']    
df_less_hos_beds_raion = df.drop(cols_to_drop, axis=1)
  • 解决方案#3:键入缺失值

当特征为数值变量时,可以进行缺失数据的插补。我们将缺失的值替换为相同特征数据中未缺失的平均值或中值。
当特征是一个分类变量时,我们可以通过模式(最频繁的值)来估算缺失的数据。
以life-sq为例,我们可以用它的中值替换这个特征的缺失值。

# replace missing values with the median.    
med = df['life_sq'].median()    
print(med)    
df['life_sq'] = df['life_sq'].fillna(med)

此外,我们可以同时对所有数字特征应用相同的插补策略。

08.png

09.png

幸运的是,我们的数据集没有缺少分类特性的值。然而,我们可以同时对所有的范畴特征应用模式归责策略。

10.png  

  • 解决方案4:替代丢失值

对于分类功能,我们可以添加一个值为“u MISSING”的新类别。对于数字特性,我们可以用-999这样的特定值替换它。
这样,我们仍然保留丢失的值作为有价值的信息。

# categorical    
df['sub_area'] = df['sub_area'].fillna('_MISSING_')    
# numeric    
df['life_sq'] = df['life_sq'].fillna(-999)

不规则数据(异常值)

异常值是与其他观测值截然不同的数据。它们可能是真正的异常值或错误。
如何发现?
根据特征是数值的还是分类的,我们可以使用不同的技术来研究其分布以检测异常值。

  • 技术1:直方图/方框图

当特征是数值时,我们可以使用直方图和方框图来检测异常值。
下面是特征寿命的柱状图。

# histogram of life_sq.    df['life_sq'].hist(bins=100)

由于可能存在离群值,数据看起来高度倾斜。

11.png

  直方图

为了更深入地研究这个特性,让我们画一个方框图。

# box plot.    df.boxplot(column=['life_sq'])

在这个图中,我们可以看到一个值超过7000的异常值。

12.png

  方块图

  • 技术2:描述性统计

此外,对于数值特征,异常值可能过于明显,以致方框图无法将其可视化。相反,我们可以看看他们的描述性统计数据。

例如,对于特征寿命,我们可以看到最大值是7478,而75%的四分位数只有43。7478值是一个异常值。

df['life_sq'].describe()

13.png  

  • 技术3:条形图

当特征是分类的。我们可以使用条形图了解其类别和分布。

例如,特征生态具有合理的分布。但是如果有一个类别只有一个值叫做“other”,那么这将是一个异常值。

# bar chart -  distribution of a categorical variable    df['ecology'].value_counts().plot.bar()

14.png

  条形图

  • 其他技术:许多其他技术也可以发现异常值,例如散点图、z-score和聚类。这篇文章并没有涵盖所有这些。

怎么办?
虽然异常值不难发现,但我们必须确定正确的解决方案来处理它们。它高度依赖于数据集和项目目标。
处理异常值的方法有点类似于丢失的数据。我们要么放弃,要么调整,要么保留它们。关于可能的解决方案,我们可以参考缺失数据部分。

不必要数据

在对丢失的数据和异常值做了所有的艰苦工作之后,让我们看看不必要的数据,这更简单。

所有输入到模型中的数据都应该为项目的目的服务。不必要的数据是当数据没有增值时。由于不同的原因,我们涵盖了三种主要类型的不必要数据。

不必要类型1:无信息/重复

有时一个功能没有信息,因为它有太多的行是相同的值。
怎么知道?
我们可以创建具有相同值的高百分比特性的列表。

例如,我们在下面指定以显示95%以上的行是相同值的功能。

15.png

  我们可以逐一研究这些变量,看看它们是否具有信息性。我们这里不显示细节。

16.png  

怎么办?
我们需要了解重复特征背后的原因。当他们真的缺乏信息时,我们可以把他们扔掉。

不必要类型2:不相关


同样,数据需要为项目提供有价值的信息。如果这些特性与我们在项目中试图解决的问题无关,它们就不相关。

怎么知道?
我们需要浏览一下这些特性来识别不相关的特性。



例如,一个记录多伦多气温的功能并不能为预测俄罗斯房价提供任何有用的信息。


怎么办?


当这些特性不符合项目的目标时,我们可以删除它们。

不必要的类型3:重复

重复数据是指存在相同观测值的副本。

重复数据主要有两种类型。

  • 重复类型1:基于所有功能

怎么知道?

当观察到的所有特征值都相同时,就会发生这种重复。很容易找到。

我们首先删除数据集中的唯一标识符id。然后通过删除重复项创建一个名为df_deduped的数据集。我们比较两个数据集(df和df_deduped)的形状,找出重复行的数量。

# we know that column 'id' is unique, but what if we drop it?    
df_dedupped = df.drop('id', axis=1).drop_duplicates()  

# there were duplicate rows    
print(df.shape)    
print(df_dedupped.shape)

10行是完全重复的观察结果。

17.png

怎么办?

我们应该删除这些复制品,我们已经删除了。

  • 重复类型2:基于关键特性

怎么知道?

有时,最好基于一组唯一标识符删除重复数据。

例如,同一建筑面积、同一价格、同一建筑年份的两个交易同时发生的可能性接近于零。

我们可以设置一组关键特征作为事务的唯一标识符。我们包括时间轴、完整面积、使用面积、楼层、建造年份、客房数量、价格。我们检查是否有基于它们的副本。

key = ['timestamp', 'full_sq', 'life_sq', 'floor', 'build_year', 'num_room', 'price_doc']    
df.fillna(-999).groupby(key)['id'].count().sort_values(ascending=False).head(20)

基于这组关键特征,共有16个副本。

 18.png

怎么办?
我们可以根据关键特征删除这些副本。

# drop duplicates based on an subset of variables.    
key = ['timestamp', 'full_sq', 'life_sq', 'floor', 'build_year', 'num_room', 'price_doc']    
df_dedupped2 = df.drop_duplicates(subset=key)    
print(df.shape)    
print(df_dedupped2.shape)

我们在名为df_dedupped2的新数据集中删除了16个重复项。

19.png

不一致的数据


让数据集遵循特定的标准来适应模型也是至关重要的。我们需要用不同的方法来探索数据,找出不一致的数据。很多时候,这取决于观察和经验。没有固定的代码来运行和修复它们。

下面我们将介绍四种不一致的数据类型。

不一致类型1:大写


在分类值中不一致地使用大写和小写是一个常见的错误。由于Python中的分析是区分大小写的,因此可能会导致问题。

怎么知道?

让我们看看sub_area  特征


df['sub_area'].value_counts(dropna=False)

它存储不同区域的名称,看起来非常标准化。

20.png  

但有时在同一个特性中存在不一致的大写用法。“Poselenie Sosenskoe”和“Poselenie Sosenskoe”可以指同一区域。

怎么办?


为了避免这种情况,我们可以把所有的字母设置为小写(或大写)。

# make everything lower case.    
df['sub_area_lower'] = df['sub_area'].str.lower()    
df['sub_area_lower'].value_counts(dropna=False)


21.png

 

不一致类型2:格式


我们需要执行的另一个标准化是数据格式。一个例子是将特性从字符串格式转换为DateTime格式。

怎么知道?

功能时间轴以字符串格式表示日期。


df

1585194646948812.png

 怎么办?

我们可以使用下面的代码转换它并提取日期或时间值。在此之后,更容易按年或月分析交易量组。 

df['timestamp_dt'] = pd.to_datetime(df['timestamp'], format='%Y-%m-%d')    
df['year'] = df['timestamp_dt'].dt.year    
df['month'] = df['timestamp_dt'].dt.month    
df['weekday'] = df['timestamp_dt'].dt.weekday    print(df['year'].value_counts(dropna=False))    print()    print(df['month'].value_counts(dropna=False))

23.png  

相关文章 :如何像老板一样在Python中操作日期和时间

不一致类型3:分类值


不一致的分类值是我们讨论的最后一种不一致的类型。分类特征的值数目有限。有时,由于输入错误等原因,可能会有其他值。

怎么知道?

我们需要观察这个特性来找出这种不一致性。让我们用一个例子来说明这一点。

我们在下面创建了一个新的数据集,因为我们在房地产数据集中没有这样的问题。例如,城市的价值被错误地定义为“Toronto”和“tronto”。但他们都提到了正确的数值“多伦多”。

一种简单的识别方法是模糊逻辑(或编辑距离)。它测量需要更改一个值的拼写以与另一个值匹配的字母数(距离)。

我们知道这些类别应该只有“多伦多”、“温哥华”、“蒙特利尔”和“卡尔加里”四个值。我们计算所有值和单词“多伦多”(和“温哥华”)之间的距离。我们可以看到,那些可能是打字错误的单词与正确的单词之间的距离较小。因为它们只差几个字母。


from nltk.metrics import edit_distance    
df_city_ex = pd.DataFrame(data={'city': ['torontoo', 'toronto', 'tronto', 'vancouver', 'vancover', 'vancouvr', 'montreal', 'calgary']})    
df_city_ex['city_distance_toronto'] = df_city_ex['city'].map(lambda x: edit_distance(x, 'toronto'))    
df_city_ex['city_distance_vancouver'] = df_city_ex['city'].map(lambda x: edit_distance(x, 'vancouver'))    
df_city_ex

24.png  

怎么办?

我们可以设置标准将这些输入错误转换为正确的值。例如,下面的代码将距离“toronto”2个字母以内的所有值设置为“toronto”。

msk = df_city_ex['city_distance_toronto'] <= 2    
df_city_ex.loc[msk, 'city'] = 'toronto'    
msk = df_city_ex['city_distance_vancouver'] <= 2    
df_city_ex.loc[msk, 'city'] = 'vancouver'    
df_city_ex

25.png

不一致类型 4:地址


地址特征可以成为我们许多人的头条新闻。因为人们经常将数据输入数据库,而不遵循标准格式。

如何找到?

我们可以通过查看数据找到弥补地址。即使有时候我们不能解决任何问题,我们仍然可以运行代码,使其标准化。

我们的数据集中没有关于隐私原因的地址。因此,我们创建了一个新的数据集  df_add_ex 和特征地址。


# no address column in the housing dataset. So create one to show the code.    df_add_ex = pd.DataFrame(['123 MAIN St Apartment 15', '123 Main Street Apt 12   ', '543 FirSt Av', '  876 FIRst Ave.'], columns=['address'])    
df_add_ex

如我们所见,地址特征相当混乱。

26.png  

怎么办?

我们运行下面的代码来将字母小写、删除空白、删除句点和标准化文字。

df_add_ex['address_std'] = df_add_ex['address'].str.lower()    
df_add_ex['address_std'] = df_add_ex['address_std'].str.strip() # remove leading and trailing whitespace.    df_add_ex['address_std'] = df_add_ex['address_std'].str.replace('\.', '') # remove period.    df_add_ex['address_std'] = df_add_ex['address_std'].str.replace('\bstreet\b', 'st') # replace street with st.    df_add_ex['address_std'] = df_add_ex['address_std'].str.replace('\bapartment\b', 'apt') # replace apartment with apt.    df_add_ex['address_std'] = df_add_ex['address_std'].str.replace('\bav\b', 'ave') # replace apartment with apt.    df_add_ex

现在看起来好多了。

27.png  

我们做到了!我们走了这么长的路。
清除所有阻碍您适应模型的“脏”数据。
做清洁工的老板!
谢谢你的阅读。
我希望你觉得这个数据清理指南有帮助。请留言让我们知道你的想法。

----------------------------------------------------------

发起:唐里 校对:唐里 审核:鸢尾

参与翻译(1人):邺调

英文原文:Data Cleaning in Python: the Ultimate Guide (2020)

THE END

免责声明:本文来自互联网新闻客户端自媒体,不代表本网的观点和立场。

合作及投稿邮箱:E-mail:editor@tusaishared.com

上一篇:神经网络优化器总结

下一篇:Python 语法复习之 Loops 和 Functions

用户评价
全部评价

热门资源

  • Python 爬虫(二)...

    所谓爬虫就是模拟客户端发送网络请求,获取网络响...

  • TensorFlow从1到2...

    原文第四篇中,我们介绍了官方的入门案例MNIST,功...

  • TensorFlow从1到2...

    “回归”这个词,既是Regression算法的名称,也代表...

  • 机器学习中的熵、...

    熵 (entropy) 这一词最初来源于热力学。1948年,克...

  • TensorFlow2.0(10...

    前面的博客中我们说过,在加载数据和预处理数据时...