返回介绍

7.1 Handling Missing Data 处理缺失数据

发布于 2023-07-20 22:49:54 字数 12526 浏览 0 评论 0 收藏 0

CHAPTER 7 Data Cleaning and Preparation

其实数据分析中 80%的时间都是在数据清理部分,loading, clearning, transforming, rearranging。而 pandas 非常适合用来执行这些任务。

7.1 Handling Missing Data

在 pandas 中,missing data 呈现的方式有些缺点的,但对大部分用户能起到足够的效果。对于数值型数据,pandas 用浮点值 Nan(Not a Number)来表示缺失值。我们称之为识别符(sentinel value),这种值能被轻易检测到:

import pandas as pd
import numpy as np
string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
string_data
0     aardvark
1    artichoke
2          NaN
3      avocado
dtype: object
string_data.isnull()
0    False
1    False
2     True
3    False
dtype: bool

在 pandas 中,我们使用了 R 语言中的一些传统,把缺失值表示为 NA(not available)。在统计应用里,NA 数据别是要么是数据不存在,要么是存在但不能被检测到。做数据清理的时候,对缺失值做分析是很重要的,我们要确定是否是数据收集的问题,或者缺失值是否会带来潜在的偏见。

内建的 Python None 值也被当做 NA:

string_data[0] = None
string_data.isnull()
0     True
1    False
2     True
3    False
dtype: bool

1 Filtering Out Missing Data(过滤缺失值)

有一些方法来过滤缺失值。可以使用 pandas.isnull 和 boolean indexing, 配合使用 dropna。对于 series,只会返回 non-null 数据和 index values:

from numpy import nan as NA
data = pd.Series([1, NA, 3.5, NA, 7])
data.dropna()
0    1.0
2    3.5
4    7.0
dtype: float64

上面的等同于:

data[data.notnull()]
0    1.0
2    3.5
4    7.0
dtype: float64

对于 DataFrame,会复杂一些。你可能想要删除包含有 NA 的 row 和 column。dropna 默认会删除包含有缺失值的 row:

data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],
                     [NA, NA, NA], [NA, 6.5, 3.]])
data
 012
01.06.53.0
11.0NaNNaN
2NaNNaNNaN
3NaN6.53.0
cleaned = data.dropna()
cleaned
 012
01.06.53.0

设定 how=all 只会删除那些全是 NA 的行:

data.dropna(how='all')
 012
01.06.53.0
11.0NaNNaN
3NaN6.53.0

删除列也一样,设置 axis=1:

data[4] = NA
data
 0124
01.06.53.0NaN
11.0NaNNaNNaN
2NaNNaNNaNNaN
3NaN6.53.0NaN
data.dropna(axis=1, how='all')
 012
01.06.53.0
11.0NaNNaN
2NaNNaNNaN
3NaN6.53.0

一种删除 DataFrame row 的相关应用是是 time series data。假设你想要保留有特定数字的观测结果,可以使用 thresh 参数:

df = pd.DataFrame(np.random.randn(7, 3))
df
 012
0-0.9865750.487466-0.251823
12.008704-0.1771331.827761
22.240856-0.5878650.273062
30.777182-0.629568-0.220044
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807
df.iloc[:4, 1] = NA
df
 012
0-0.986575NaN-0.251823
12.008704NaN1.827761
22.240856NaN0.273062
30.777182NaN-0.220044
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807
df.iloc[:2, 2] = NA
df
 012
0-0.986575NaNNaN
12.008704NaNNaN
22.240856NaN0.273062
30.777182NaN-0.220044
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807
df.dropna()
 012
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807
df.dropna(thresh=2) 
 012
22.240856NaN0.273062
30.777182NaN-0.220044
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807

2 Filling In Missing Data(填补缺失值)

不是删除缺失值,而是用一些数字填补。对于大部分目的,fillna 是可以用的。调用 fillna 的时候设置好一个常用用来替换缺失值:

df.fillna(0)
 012
0-0.9865750.0000000.000000
12.0087040.0000000.000000
22.2408560.0000000.273062
30.7771820.000000-0.220044
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807

给 fillna 传入一个 dict,可以给不同列替换不同的值:

df.fillna({1: 0.5, 2: 0})
 012
0-0.9865750.5000000.000000
12.0087040.5000000.000000
22.2408560.5000000.273062
30.7771820.500000-0.220044
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807

fillna 返回一个新对象,但你可以使用 in-place 来直接更改原有的数据:

_ = df.fillna(0, inplace=True)
df
 012
0-0.9865750.0000000.000000
12.0087040.0000000.000000
22.2408560.0000000.273062
30.7771820.000000-0.220044
40.3275220.781662-0.651949
51.454611-0.170581-1.740959
6-0.7118970.0749831.343807

在使用 fillna 的时候,这种插入法同样能用于 reindexing:

df = pd.DataFrame(np.random.randn(6, 3))
df
 012
0-1.1515081.185176-1.766933
10.544729-0.8078140.696087
2-1.4619500.4488520.189045
30.5597660.3413351.469807
4-0.3627891.117338-0.383870
5-0.452329-0.282040-0.541759
df.iloc[2:, 1] = NA
df
 012
0-1.1515081.185176-1.766933
10.544729-0.8078140.696087
2-1.461950NaN0.189045
30.559766NaN1.469807
4-0.362789NaN-0.383870
5-0.452329NaN-0.541759
df.iloc[4:, 2] = NA
df
 012
0-1.1515081.185176-1.766933
10.544729-0.8078140.696087
2-1.461950NaN0.189045
30.559766NaN1.469807
4-0.362789NaNNaN
5-0.452329NaNNaN
df.fillna(method='ffill')
 012
0-1.1515081.185176-1.766933
10.544729-0.8078140.696087
2-1.461950-0.8078140.189045
30.559766-0.8078141.469807
4-0.362789-0.8078141.469807
5-0.452329-0.8078141.469807
df.fillna(method='ffill', limit=2)
 012
0-1.1515081.185176-1.766933
10.544729-0.8078140.696087
2-1.461950-0.8078140.189045
30.559766-0.8078141.469807
4-0.362789NaN1.469807
5-0.452329NaN1.469807

使用 fillna 可以我们做一些颇有创造力的事情。比如,可以传入一个 series 的平均值或中位数:

data = pd.Series([1., NA, 3.5, NA, 7])
data.fillna(data.mean())
0    1.000000
1    3.833333
2    3.500000
3    3.833333
4    7.000000
dtype: float64

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文