有数据显示说,数据分析师或者数据科学家通常会花掉80%的时间去清理数据,20%的时间去分析数据和写数据报告。因为通常在真实世界当中拿到的数据往往跟在课堂中拿到的数据样本有着千差万别。真实世界的数据一般会非常的dirty,所以需要花大量的时间去清洗。一般来说,造成数据脏乱差的原因通常有两种,一是人为输入错误,而是技术原因造成的错误。不干净整洁的数据会给我们的分析造成很大的困扰,甚至会产生错误的报告从而影响决策。所以,当我们拿到一大堆数据的时候,第一个工作是要判断数据的来源,并且尽量的以科学的方法把数据清洗干净,然后再进行接下来的分析操作。这篇文章会分步介绍一些常见的数据清理基本操作。数据是从datacamp中获取的,我在次基础上又把相对干净的数据弄脏了一些一遍举例演示,这是一个叫做airlines的csv文件,其中包含了从旧金山国际机场几天出发的航班的数据。我们先来简单的看一下airlines.csv都包含哪些数据。
|
|
|
|
通过输出我们大概可以判断出这个df有id,乘客姓名,航空公司,目的地,目的地区域,登机口,起飞时间,温度,等待时间,还有一些满意度的调查,评分以及常旅和积分情况。在Spyder编译环境下,还可以看到跟Excel类似的表格,来对数据有一个更加直观的感受。
数据类型问题
通过df.info()以及对数据的观察,我们发现了两个数据类型。第一个是wait_min等待时间,这个数据应该是数字int或者float类型,而原来的数据是一个对象类型。第二个是frequent_flyer,我们发现数据中有0,1,2三个数字,这三个数字应该代表的是不同类型,或者不同等级的常旅会员,所以应该是category类型,而不是int类型。我们首先要做的是把这组数据类型转换成正确的数据类型:
|
|
然后我们打印一下我们清理好的wait_time这个新的变量看一下效果,然后再看一下乘客平均的等待时间:
|
|
数据范围问题
有些时候,我们拿到的一些数据可能会出现一些数据范围错误,比如说一些当天起飞的航班日期却错误的记录成了一个未来的日期,或者某些数字超出了设置范围。例如,在airlines的rating当中,我们就发现了rating中有一些评分超出了预设范围:
|
|
通过上图,我们发现了一些打分超过了1-5的评分范围。一般我们处理数据范围问题的时候通常有4种方式:
- 简单的去除这些数据
- 设置特定的最大最小值
- 把这些超出范围的数据设置为空值并进行补全操作
- 根据特定情况为这些数据设置一个特定值
|
|
我们发现仅仅有10个rating大于5的数据,对于一个有2000多条数据的df来说,简单的去除这些数据不会对后面的分析产生较大的影响,所以我们这里就简单的把这些数据drop掉:
|
|
数据重复问题
重复的数据是一个非常常见的问题。通常造成数据重复的原因一般有三种,人为输入错误,合并数据出现的问题以及bug或者设计问题。我们可以通过.duplicated()
函数来检查df中存在重复的数据:
|
|
通过对以上重复的数据观察,我们发现大部分重复的数据为完全重复,就是一模一样的数据出现了两条或两条以上,对于这种情况,我们简单的使用.drop_duplicates()
函数把重复的数据保留下来一条就可以了。但是数据中那些不是完全重复的情况我们需要进一步对其处理,比如以上重复数据中就出现了一对不完全重复的数据:
|
|
这一对数据中其他数据一模一样,但是在wait_time中出现了差别。对于这种差异我们可以根据出现的实际情况进行评估,然后对数据进行impute。以上这种情况,我们可以简单的取两次wait_time的平均值即可:
|
|
在合并这两个df之后,我们需要再对数据进行一次查重操作,因为merge的过程是有可能产生重复数据的,尤其是inner merge:
|
|
我们发现由于merge操作df中又出现了数据重复的情况,原因是因为在我们合并的过程中,由于wait_time在pass_dup中有两个值145和120。所以我们只需要留一条数据即可:
|
|
通过打印和assert验证,我们发现已经没有重复的数据了。
分类数据问题
在分类变量中通常也会出现数据分类错误的问题,例如在采集数据的时候会出现类别输入错误。一般我们处理这类数据问题时,有三种处理方法。
- 去除这些数据
- 对这些数据进行重新映射
- 根据实际情况进行数据推理
在airlines数据中的评价数据cleanliness
中也出现了分类数据的问题。
|
|
每个变量中有5个评分标准,接下来检查数据中是否有评分标准不在这15个评分标准中:
|
|
在cleanliness
,出现了一个Unacceptable的评分,这个评分超出了我们预设的标准categories
,所以需要对它进行一定的处理。
|
|
在浏览数据的过程当中dest_region
出现了字母大小写不统一,相同数据使用不同分类标记的现象,在dest_size
中看到了数据有空格的现象。这些问题python都会把他们当作不同的类别来处理,但是实际上有一些数据的类别是相同的,只是由于各种各样的原因,造成了一些数据错误的录入,所以需要对它们也进行清理:
|
|
在dest_region
中,我们看到python把East US
和EAST US
,Middle East
和middle east
,Europe
和eur
当作了不同的类别来处理,我们知道他们其实应该是相同的类别。类似的问题出现在了dest_size
中,python同样把前面有空格的类别和没有空格的类别当作了不同的类别。我们需要对这些问题数据进行处理,其中关于dest_region
的问题,我们可以把所有的类别名称全部换成大写.str.upper()
或者小写.str.lower()
,然后把eur
替换成europe
即可。在dest_size
中,我们可以把空格去除便可解决问题:
|
|
有时候我们需要更直观的表现一些分类数据的时候,需要为一些数据进行分组,比如说wait_time这个变量:
|
|
可以看出大部分人的等待时间是在0-300分钟之间,如果我们对等待时间进行分组,分别分成等待时间较短(short),等待时间适中(medium)和等待时间较长(long)我们可以这样操作:
|
|
除了可以根据数据划分组别,我们还可以重新映射数据,比如说我们可以把day
变量的星期几重新映射成工作日(weekday)和周末(weekend):
|
|
文本数据清理
full_name变量中的姓名中有个别数据出现了一些敬称如Dr. Mr. Ms. Miss.等,我们为了使得数据变得统一,可以把这些敬称去除:
|
|
关于文本数据清理,可能会在实际情况中遇到更多的问题,多数情况我们需要使用replace()函数进行替换或者删除文本,同时在清理更加复杂的文本数据的时候还会用到正则表达式。
格式统一问题
数据的格式统一性也是经常出现的问题,例如在airlines中,起飞日期dept_time的数据中就出现了日期格式不统一的问题,甚至出现了13/31/2018这种不存在的日期:
|
|
出现了报错:
|
|
因为日期类型超出了范围,所以pandas抛出一个DateParseError错误,我们可以在pd.to_datetime()
函数中增加一个errors
参数来解决这个问题:
|
|
|
|
这时dept_time_dt
变量已经变为了datetime64[ns]
类型,并且infer_datetime_format = True
参数把December 31st, 2018映射成了2018-12-31跟其他数据统一的格式。13/31/2018这个日期程序无法映射和判断其到底为哪天,所以它被赋值为了NaT。
在dept_time_dt
中还出现了一些当天起飞的航班日期被标记成了未来的日期,我们把这些日期进行一些处理:
|
|
到目前为止,我们几乎对所有变量都进行了一定的清理,未被清理的数据也就只剩下个别的变量了。接下来我们来看一下temperature
这个变量的数据有没有问题:
|
|
通过散点图发现了2018年1月和2019年1月有出现了一些极寒的温度,在旧金山这种地方不太会出现10华氏度左右的问题,通过常识判断,应该是10摄氏度,我们对小于20的温度值进行温度转换:
|
|
交叉验证
最后我们对常旅会员的积分进行交叉验证,看是否存在积分不对等的情况。关于积分一共有三个变量,分别是本次飞行获得的积分(points_gain),本次飞行之前的基本(points_last_time),还有总积分(total_points)。
所以,total_points = points_gain + points_last_time
我们来验证一下是否如此:
|
|
发现了存在1个不相等的数据。一般来讲,当我们发现了这种不前后矛盾的数据之后,最简单的办法就是drop,或者我们可以设置为NA空值,然后对其进行impute。我们的例子中的这种情况处理办法比较简单,可以就矛盾的数据拿出来检查,然后看是哪里出了问题,然后进行处理即可。
借此,我们对airlines这个df的数据清洗就到此为止了,接下来我们就可以对此进行分析了。