29

利用 Pandas 的 transform 和 apply 来处理组级别的丢失数据

 5 years ago
source link: http://mp.weixin.qq.com/s?__biz=MjM5ODU3OTIyOA%3D%3D&%3Bmid=2650680255&%3Bidx=2&%3Bsn=0c87f0586c5adcb75f0652344faacb26
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

2UvQzmJ.gif

点击上方“蓝字”关注“AI开发者”

2QjM3uJ.jpg!web

vme2Ij3.jpg!web

根据 Businessbroadway 的一项分析,数据专业人员将会花高达 60% 的时间用于收集、清理和可视化数据。

bYBF3q6.png!web

资料来源:Businessbroadway

清理和可视化数据的一个关键方面是如何处理丢失的数据。Pandas 以 fillna 方法的形式提供了一些基本功能。虽然 fillna 在最简单的情况下工作得很好,但只要数据中的组或数据顺序变得相关,它就会出现问题。本文将讨论解决这些更复杂情况的技术。

这些情况通常是发生在由不同的区域(时间序列)、组甚至子组组成的数据集上。不同区域情况的例子有月、季(通常是时间范围)或一段时间的大雨。性别也是数据中群体的一个例子,子组的例子有年龄和种族。

这篇文章附带了代码。所以你可以随意启动一个 Notebook,直接开始。

文章结构:

  1. Pandas fillna 概述

  2. 当排序不相关时,处理丢失的数据

  3. 当排序相关时,处理丢失的数据

   Pandas fillna 概述

e2MRjy6.jpg!web

图片来自 Pixabay

Pandas 有三种通过调用 fillna()处理丢失数据的模式:

  • method='ffill':ffill 或 forward fill 向前查找非空值,直到遇到另一个非空值

  • method='bfill':bfill 或 backward fill 将第一个观察到的非空值向后传播,直到遇到另一个非空值

  • 显式值:也可以设置一个精确的值来替换所有的缺失值。例如,这个替换值可以是 -999,以表示缺少该值。

例子:

zYjqeaJ.png!web

rMjAFzV.png!web

   当排序不相关时,处理丢失的数据

QFjAjyb.jpg!web

来自 Pixabay 公共领域的图片

通常,在处理丢失的数据时,排序并不重要,因此,用于替换丢失值的值可以基于可用数据的整体来决定。在这种情况下,你通常会用你猜测的最佳值(即,可用数据的平均值或中等值)替换丢失的值。

让我们快速回顾一下为什么应该小心使用此方法。假设你调查了 1000 个男孩和 1000 个女孩的体重。不幸的是,在收集数据的过程中,有些数据丢失了。

# imports

import numpy as np


# sample 1000 boys and 1000 girls

boys = np.random.normal(70,5,1000)

girls = np.random.normal(50,3,1000)


# unfortunately, the intern running the survey on the girls got distracted and lost 100 samples

for i in range(100):

girls[np.random.randint(0,1000)] = np.nan

# build DataFrame

boys = pd.DataFrame(boys, columns=['weight'])

boys['gender'] = 'boy'


girls = pd.DataFrame(girls, columns=['weight'])

girls['gender'] = 'girl'


df = pd.concat([girls,boys],axis=0)

df['weight'] = df['weight'].astype(float)

子组

如果不是很在意缺失值填充什么,我们可以用整个样本的平均值填充缺失的值。不过,结果看起来有些奇怪。女孩的 KDE 有两个驼峰。有人可能会得出结论,在我们的样本中有一个子组的女孩体重较重。因为我们预先构建了分布,所以我们知道情况并非如此。但如果这是真实的数据,我们可能会从中得出错误的结论。

7VfM3iz.png!web

男孩和女孩的体重 KDE,我们用样本均值替换缺失的数据(下附代码)

# PLOT CODE:

sns.set_style('white')

fig, ax = plt.subplots(figsize=(16, 7))


mean = df['weight'].mean()


sns.distplot(

df[df['gender'] == 'girl']['weight'].fillna(mean),

kde=True,

hist=False,

ax=ax,

label='girls'

)


sns.distplot(

df[df['gender'] == 'boy']['weight'],

kde=True,

hist=False,

ax=ax,

label='boys'

)


plt.title('Kernel density estimation of weight for boys and girls')


sns.despine()

用组的平均值填充缺失值

在这种情况下,Pandas 的转换函数就派上了用场,它使用变换提供了一种简洁的方法来解决这个问题:

df['filled_weight'] = df.groupby('gender')['weight'].transform(

lambda grp: grp.fillna(np.mean(grp))

)

运行上述命令并绘制填充的权重值的 KDE 将得到:

A7R3Qjn.png!web

男孩和女孩权重的 KDE,我们用组平均值替换缺失值(下面附代码)

# PLOT CODE:

sns.set_style('white')

fig, ax = plt.subplots(figsize=(16, 7))


sns.distplot(

df[df['gender'] == 'girl']['filled_weight'],

kde=True,

hist=False,

ax=ax,

label='girls'

)

sns.distplot(

df[df['gender'] == 'boy']['filled_weight'],

kde=True,

hist=False,

ax=ax,

label='boys'

)


plt.title('Kernel density estimation of weight for boys and girls')


sns.despine()

多个子组

让我们使用前面的例子,但是这次,我们进一步将数据细分为年龄组。我们先创建一些模拟数据:

# paramter for the weight distribution (mean, std)

param_map = {

'boy':{

'<10':(40,4),

'<20':(60,4),

'20+':(70,5),

},

'girl':{

'<10':(30,2),

'<20':(40,3),

'20+':(50,3),

}

}

# generate 10k records

df = pd.DataFrame({

'gender':np.random.choice(['girl','boy'],10000),

'age_cohort':np.random.choice(['<10','<20','20+'],10000)

})

# set random weight based on parameters

df['weight'] = df.apply(

lambda x: np.random.normal(

loc=param_map[x['gender']][x['age_cohort']][0],

scale=param_map[x['gender']][x['age_cohort']][1]

),axis=1

)

# set 500 values missing

for i in range(500):

df.loc[np.random.randint(0,len(df)),'weight'] = np.nan

绘制数据图,会出现一些奇怪的双峰分布(后面有代码)。

AVZnia6.png!web

用样本平均值代替缺失值

# PLOT CODE

df['filled_weight'] = df['weight'].fillna(

df['weight'].mean()

)


g = sns.FacetGrid(

df,

col='age_cohort',

row='gender',

col_order=['<10','<20','20+']

)


g.map(sns.kdeplot,'filled_weight')

现在,如果我们只用性别的平均值来代替缺失的值,就远远不够,因为男孩和女孩不仅体重不同,而且不同年龄组的体重也大不相同。

幸运的是,可以像前面一样使用转换。我们将对两列进行分组,代码如下:

df['filled_weight'] = df.groupby(['gender','age_cohort'])

['weight'].transform(

lambda grp: grp.fillna(np.mean(grp))

)

运行上述代码片段将生成更清晰的曲线:

bYRZNbB.png!web

按年龄、性别分组的体重 KDE 用各组的平均值代替缺失值

   当顺序相关时,处理丢失的数据

VB7Nv2u.png!web

Jake Hills 在 Unsplash 上的照片

在处理时间序列数据时,经常会出现两种情况:

  1. 调整日期范围:假设你有一份关于各国的 GDP、教育水平和人口年增长率的数据。对一些国家来说,你缺失了最初几年、最后几年或者中间几年的数据。当然,你可以忽略它们。不过,为了可视化,你可能想要填充这些数据。

  2. 插值:看时间序列数据插值,你会发现排序变得非常相关。如果用基于截至 2019 年的数据计算出的平均值来替换 2012 年丢失的股票数据,势必会产生一些古怪的结果。

我们将以《2019 年世界幸福报告》(World Happiness Report 2019)中的数据为基础来看一个例子,在这个例子中,我们将处理这两种情况。《世界幸福报告》试图回答影响全世界幸福的因素。该报告调查了 2005 年至 2018 年的数据。

载入数据

# Load the data

df = pd.read_csv('https://raw.githubusercontent.com/FBosler/you- datascientist/master/happiness_with_continent.csv')

样本检验

与 df.head(5)相反,df.sample(5) 选择五个随机行,从而使你有一个偏差更小的数据可视化图。

2EJJRnr.png!web

下载数据帧中的数据示例

让我们看看我们每年有多少国家的数据。

b6name2.png!web

每年有数据的国家数量

# PLOT CODE:

df.groupby(['Year']).size().plot(

kind='bar',

title='Number of countries with data',

figsize=(10,5)

)

我们可以看到,特别是在早些年,我们没有多少国家的数据,而且整个样本周期都有一些波动。为了减轻丢失数据的影响,我们将执行以下操作:

  1. 按国家分组并重新索引到整个日期范围

  2. 在对每个国家分组的范围之外的年份内插和外推

1.按国家分组并重新索引日期范围

# Define helper function

def add_missing_years(grp):

_ = grp.set_index('Year')

_ = _.reindex(list(range(2005,2019)))

del _['Country name']

return _

# Group by country name and extend

df = df.groupby('Country name').apply(add_missing_years)

df = df.reset_index()

我们现在大约有 600 行数据。然而,这些观察结果现在是无效的。

bYNbamF.png!web

扩展数据帧,所有国家在 2005 年到 2018 年间都有数据

2.在对每个国家分组的范围之外的年份内插和外推

# Define helper function

def fill_missing(grp):

res = grp.set_index('Year')\

.interpolate(method='linear',limit=5)\

.fillna(method='ffill')\

.fillna(method='bfill')

del res['Country name']

return res

# Group by country name and fill missing

df = df.groupby(['Country name']).apply(

lambda grp: fill_missing(grp)

)


df = df.reset_index()

fill_missing 函数在末尾和开头进行插值和外推,结果是:

nYR7b2Q.png!web

很完美!现在我们有样本中所有国家 2005 年至 2018 年的数据。当我写这篇关于可视化的文章时,上面的方法对我来说很有意义。如果你想了解更多关于这篇报告的信息,可以查看:https://towardsdatascience.com/plotting-with-python-c2561b8c0f1f

via:https://towardsdatascience.com/using-pandas-transform-and-apply-to-deal-with-missing-data-on-a-group-level-cb6ccf060531

/ 更多阅读 /

3mmE3qZ.jpg!web

nQZJjub.gif点击 阅读原文 ,查看:什么是好的编程语言?


Recommend

  • 18

    关于Excel数据处理,很多同学可能使用过Pyhton的pandas模块,用它可以轻松地读取和转换Excel数据。但是实际中Excel表格结构可能比较杂乱,数据会分散不同的工作表中,而且在表格中分布很乱,这种情况下啊直接使用pandas就会非常吃力。本文虫虫给...

  • 8

    一、为什么消息会丢失? 跟消息重复问题类似,消息丢失也可能出现在生产者、MQ、消费者三者中。这三者导致消息丢失的原因是什么呢? 生产者:生产者推送消息到 MQ 中,由于网络抖动等原因消息没有推送到 MQ 中,...

  • 7

    常见问题分析RabbitMQ如何处理消息丢失 工具 ...

  • 8
    • www.flydean.com 3 years ago
    • Cache

    Pandas高级教程之:处理缺失数据

    在数据处理中,Pandas会将无法解析的数据或者缺失的数据使用NaN来表示。虽然所有的数据都有了相应的表示,但是NaN很明显是无法进行数学运算的。 本文将会讲解Pandas对于NaN数据的处理方法。 NaN的例子 上面讲到了缺失的数据会被表现为Na...

  • 7
    • www.flydean.com 3 years ago
    • Cache

    Pandas高级教程之:处理text数据

    在1.0之前,只有一种形式来存储text数据,那就是object。在1.0之后,添加了一个新的数据类型叫做StringDtype 。今天将会给大家讲解Pandas中text中的那些事。 创建text的DF 先看下常见的使用text来构建DF的例子: In [1]: pd.Ser...

  • 14

    这篇文章主要围绕下列问题进行探讨:如何处理消息的丢失问题数据的丢失问题,可能出现在生产者、MQ、消费者中,咱们从 RabbitMQ 和 Kafka 分别来分析一下吧。RabbitMQ

  • 11

    在 JavaScript 中浮点数运算时经常出现 0.1+0.2=0.30000000000000004 这样的问题,除此之外还有一个不容忽视的大数危机(大数处理精度丢失)问题。之前也分享过这个问题,我在做个梳理分享给大家,

  • 8

    V2EX  ›  Python 处理比较大的数据集的时候,单机 spark 会比 pandas 更快吗   MTMT · 10 分钟前 vi...

  • 4

    Pandas处理大数据的性能优化技巧 作者:Okan Yenigün 2022-12-30 15:29:35 Pandas是Python中最著名的数据分析工具。在处理数据集时,每个人都会使用到它。但是随着数据大小的增加,执行某些操作的某些方法会比其他...

  • 4
    • blog.51cto.com 2 years ago
    • Cache

    Pandas处理数据的性能技巧

    Pandas是Python中最著名的数据分析工具。在处理数据集时,每个人都会使用到它。但是随着数据大小的增加,执行某些操作的某些方法会比其他方法花费更长的时间。所以了解和使用更快的方法非常重要,特别是在大型数据集中,本文将介绍一些使用Pandas处理大数据时的技巧...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK