前些天报名参加了 Kaggle 的 Data Cleaning 5天挑战,5天的任务如下:
- Day 1: Handling missing values
- Day 2: Data scaling and normalization
- Day 3: Cleaning and parsing dates
- Day 4: Fixing encoding errors (no more messed up text fields!)
- Day 5: Fixing inconsistent data entry & spelling errors
今天是第一天,任务是处理数据集中的缺失值。活动的主持人 Rachael Tatman 给出的操作步骤如下:
- Take a first look at the data
- See how many missing data points we have
- Figure out why the data is missing
- Drop missing values
- Filling in missing values
我们一步一步来进行操作~
1、观察数据
首先我们在 notebook 中加载需要清理的数据集,数据集的位置可以在本地也可以在服务器上。今天官方例子中的数据集是关于美国橄榄球比赛的,然后我们动手去做的是关于旧金山建筑许可证的数据集。
引入 pandas 和 numpy 包,从给出的路径读数据集,
# modules we'll use
import pandas as pd
import numpy as np# read in all our data
sf_permits = pd.read_csv("../input/building-permit-applications-data/Building_Permits.csv")# set seed for reproducibility
np.random.seed(0)
然后用 sample(10) 方法随机抽取数据集中的 10 条数据,结果中有很多数据格被标记了 "NaN" ,这些就是我们需要处理的缺失值。
sf_permits.sample(10)
2、观察缺失值的数量
现在我们知道了数据集中存在缺失值,再来看看每一个 column 下缺失值的具体数量(由于 column 过多我们只选了前 15 列)。
# get the number of missing data points per column
missing_values_count = sf_permits.isnull().sum()# look at the # of missing points in the first ten columns
missing_values_count[0:15]
然后可以进一步看看数据集中缺失值的数目占总数的百分比,结果约为 26.26%,四分之一的数据都缺失了!
# how many total missing values do we have?
total_cells = np.product(sf_permits.shape)
total_missing = missing_values_count.sum()# percent of data that is missing
(total_missing/total_cells) * 100
3、分析出现缺失值的原因
这一部分的重点之一是我们对数据的直觉,Rachael 所用的说法是 "data intuition",也就是说我们需要搞清楚我们面对的数据集为什么如此,以及对我们后续的数据分析会有什么样的影响。由于缺乏经验,入门者这部分可能比较困扰。我们需要考虑的问题之一是:
某个数据的缺失是因为它没有被记录还是根本不存在?
如果一个数据值缺失是因为它根本不存在,那么我们就没有必要去猜它可能的值,我们需要做的就是让它继续为 NaN;如果一个数据值缺失是因为没有被记录,我们就应该基于与它同行同列的其他值,来猜想它的可能值。
拿当前的数据集做例子,我们来看一下 Street Number Suffix 和 Zipcode 的缺失值:
missing_values_count = sf_permits.isnull().sum()
missing_values_count[['Street Number Suffix', 'Zipcode']]
我们看到 Street Number Suffix 下有大量缺失值,由于它对地址来说并不是一个普遍存在的数据,所以我猜想它的缺失值根本不存在;有少量的 Zipcode 数据缺失,由于每个地址的邮编一定存在,所以它应该是没有被记录。
4、剔除缺失值
如果你实在急于做分析,可以采取的方案之一就是剔除掉任何包含缺失值的行或列。但这种方法是并不推荐,要想得到更好的分析结果,还是要先合理地处理缺失值。
如果确定想要剔除掉含有缺失值的数据行,可以直接使用 pandas 的 dropna() 方法:
# remove all the rows that contain a missing value
sf_permits.dropna()
但是我们得到的结果是 0 rows × 43 columns,因为每一行都存在缺失值!
再剔除含有缺失值的数据列:
# remove all columns with at least one missing value
columns_with_na_dropped = sf_permits.dropna(axis=1)
columns_with_na_dropped.head()
看一下剔除空值前后的 column 数目对比:
# just how much data did we lose?
print("Columns in original dataset: %d n" % sf_permits.shape[1])
print("Columns with na's dropped: %d" % columns_with_na_dropped.shape[1])
5、自动补全缺失值
除了直接 drop 掉含有缺失值的行或列,另一个方案是去补全缺失的值。这部分我们先截取一部分 column 的数据进行处理,便于观察。
# get a small subset of the sf_permits dataset
subset_sf_permits = sf_permits.loc[:,"Street Number Suffix":"Issued Date"].head()
subset_sf_permits
如果数据的类型都是数字,我们可以考虑把所有的缺失值都填为 0:
# replace all NA's with 0
subset_sf_permits.fillna(0)
但该数据集中,有 string 型的数据,还有另一种选择就是将空值置为与它相邻的下一行对应的数据,没有下一行数据就置为 0:
# comes directly after it and then
subset_sf_permits.fillna(method = "bfill", axis=0).fillna("0")
处理不同类型的数据集,需要采取不同的方法,还可以用相应 column 的平均值来补全该列的缺失值等。
这就是 5 Day Challenge 第一天的内容,总地来说是非常基础的清洗数据方法,完毕~
欢迎大家关注微信公众号【数据池塘】: