[数据清洗]- Pandas 清洗“脏”数据(二)
概要
- 了解数据
- 分析数据问题
- 清洗数据
- 整合代码
了解数据
在处理任何数据之前,我们的第一任务是理解数据以及数据是干什么用的。我们尝试去理解数据的列/行、记录、数据格式、语义错误、缺失的条目以及错误的格式,这样我们就可以大概了解数据分析之前要做哪些“清理”工作。
本次我们需要一个 patient_heart_rate.csv (链接:https://pan.baidu.com/s/1geX8oYf 密码:odj0)的数据文件,这个数据很小,可以让我们一目了然。这个数据是 csv 格式。数据是描述不同个体在不同时间的心跳情况。数据的列信息包括人的年龄、体重、性别和不同时间的心率。
import pandas as pd
df = pd.read_csv('../data/patient_heart_rate.csv')
df.head()
分析数据问题
- 没有列头
- 一个列有多个参数
- 列数据的单位不统一
- 缺失值
- 空行
- 重复数据
- 非 ASCII 字符
- 有些列头应该是数据,而不应该是列名参数
清洗数据
下面我们就针对上面的问题一一击破。
1. 没有列头
如果我们拿到的数据像上面的数据一样没有列头,Pandas 在读取 csv 提供了自定义列头的参数。下面我们就通过手动设置列头参数来读取 csv,代码如下:
import pandas as pd
# 增加列头
column_names= ['id', 'name', 'age', 'weight','m0006','m0612','m1218','f0006','f0612','f1218']
df = pd.read_csv('../data/patient_heart_rate.csv', names = column_names)
df.head()
上面的结果展示了我们自定义的列头。我们只是在这次读取 csv 的时候,多了传了一个参数 names = column_names,这个就是告诉 Pandas 使用我们提供的列头。
2. 一个列有多个参数
在数据中不难发现,Name 列包含了两个参数 Firtname 和 Lastname。为了达到数据整洁目的,我们决定将 name 列拆分成 Firstname 和 Lastname
从技术角度,我们可以使用 split 方法,完成拆分工作。
我们使用 str.split(expand=True),将列表拆成新的列,再将原来的 Name 列删除
# 切分名字,删除源数据列
df[['first_name','last_name']] = df['name'].str.split(expand=True)
df.drop('name', axis=1, inplace=True)
上面就是执行执行代码之后的结果。
3. 列数据的单位不统一
如果仔细观察数据集可以发现 Weight 列的单位不统一。有的单位是 kgs,有的单位是 lbs
# 获取 weight 数据列中单位为 lbs 的数据
rows_with_lbs = df['weight'].str.contains('lbs').fillna(False)
df[rows_with_lbs]
为了解决这个问题,将单位统一,我们将单位是 lbs 的数据转换成 kgs。
# 将 lbs 的数据转换为 kgs 数据 for i,lbs_row in df[rows_with_lbs].iterrows():
weight = int(float(lbs_row['weight'][:-3])/2.2)
df.at[i,'weight'] = '{}kgs'.format(weight)
4. 缺失值
在数据集中有些年龄、体重、心率是缺失的。我们又遇到了数据清洗最常见的问题——数据缺失。一般是因为没有收集到这些信息。我们可以咨询行业专家的意见。典型的处理缺失数据的方法:
- 删:删除数据缺失的记录(数据清洗- Pandas 清洗“脏”数据(一)/[数据清洗]-Pandas 清洗“脏”数据(一))
- 赝品:使用合法的初始值替换,数值类型可以使用 0,字符串可以使用空字符串“”
- 均值:使用当前列的均值
- 高频:使用当前列出现频率最高的数据
- 源头优化:如果能够和数据收集团队进行沟通,就共同排查问题,寻找解决方案。
5. 空行
仔细对比会发现我们的数据中一行空行,除了 index 之外,全部的值都是 NaN。
Pandas 的 read_csv() 并没有可选参数来忽略空行,这样,我们就需要在数据被读入之后再使用 dropna() 进行处理,删除空行.
# 删除全空的行
df.dropna(how='all',inplace=True)
6. 重复数据
有的时候数据集中会有一些重复的数据。在我们的数据集中也添加了重复的数据。
首先我们校验一下是否存在重复记录。如果存在重复记录,就使用 Pandas 提供的 drop_duplicates() 来删除重复数据。
# 删除重复数据行
df.drop_duplicates(['first_name','last_name'],inplace=True)
7. 非 ASCII 字符
在数据集中 Fristname 和 Lastname 有一些非 ASCII 的字符。
处理非 ASCII 数据方式有多种
- 删除
- 替换
- 仅仅提示一下
我们使用删除的方式:
# 删除非 ASCII 字符
df['first_name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True)
df['last_name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True)
8. 有些列头应该是数据,而不应该是列名参数
有一些列头是有性别和时间范围组成的,这些数据有可能是在处理收集的过程中进行了行列转换,或者收集器的固定命名规则。这些值应该被分解为性别(m,f),小时单位的时间范围(00-06,06-12,12-18)
# 切分 sex_hour 列为 sex 列和 hour 列
sorted_columns = ['id','age','weight','first_name','last_name']
df = pd.melt(df,
id_vars=sorted_columns,var_name='sex_hour',value_name='puls_rate').sort_values(sorted_columns)
df[['sex','hour']] = df['sex_hour'].apply(lambda x:pd.Series(([x[:1],'{}-{}'.format(x[1:3],x[3:])])))[[0,1]]
df.drop('sex_hour', axis=1, inplace=True)
# 删除没有心率的数据
row_with_dashes = df['puls_rate'].str.contains('-').fillna(False)
df.drop(df[row_with_dashes].index,
inplace=True)
整合代码
import pandas as pd
# 增加列头
column_names= ['id', 'name', 'age', 'weight','m0006','m0612','m1218','f0006','f0612','f1218']
df = pd.read_csv('../data/patient_heart_rate.csv', names = column_names)
# 切分名字,删除源数据列
df[['first_name','last_name']] = df['name'].str.split(expand=True)
df.drop('name', axis=1, inplace=True)
# 获取 weight 数据列中单位为 lbs 的数据
rows_with_lbs = df['weight'].str.contains('lbs').fillna(False)
df[rows_with_lbs]
# 将 lbs 的数据转换为 kgs 数据
for i,lbs_row in df[rows_with_lbs].iterrows():
weight = int(float(lbs_row['weight'][:-3])/2.2)
df.at[i,'weight'] = '{}kgs'.format(weight) # 删除全空的行
df.dropna(how='all',inplace=True)
# 删除重复数据行
df.drop_duplicates(['first_name','last_name'],inplace=True)
# 删除非 ASCII 字符
df['first_name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True)
df['last_name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True)
# 切分 sex_hour 列为 sex 列和 hour 列
sorted_columns = ['id','age','weight','first_name','last_name']
df = pd.melt(df,
id_vars=sorted_columns,var_name='sex_hour',value_name='puls_rate').sort_values(sorted_columns)
df[['sex','hour']] = df['sex_hour'].apply(lambda x:pd.Series(([x[:1],'{}-{}'.format(x[1:3],x[3:])])))[[0,1]]
df.drop('sex_hour', axis=1, inplace=True)
# 删除没有心率的数据
row_with_dashes = df['puls_rate'].str.contains('-').fillna(False)
df.drop(df[row_with_dashes].index,
inplace=True)
# 重置索引,不做也没关系,主要是为了看着美观一点
df = df.reset_index(drop=True)
print(df)
还有一些问题在本例中没有提及内容,下面有两个比较重要,也比较通用的问题:
- 日期的处理
- 字符编码的问题
本次又介绍了一些关于 Pandas 清洗数据的技能。至少用这几次介绍的处理方法,应该可以对数据做很多清洗工作。
更多关于数据清洗的内容可以关注知乎上的专栏“数据清洗”
[数据清洗]- Pandas 清洗“脏”数据(二)的更多相关文章
- [数据清洗]- Pandas 清洗“脏”数据(三)
预览数据 这次我们使用 Artworks.csv ,我们选取 100 行数据来完成本次内容.具体步骤: 导入 Pandas 读取 csv 数据到 DataFrame(要确保数据已经下载到指定路径) D ...
- [数据清洗]-Pandas 清洗“脏”数据(一)
概要 准备工作 检查数据 处理缺失数据 添加默认值 删除不完整的行 删除不完整的列 规范化数据类型 必要的转换 重命名列名 保存结果 更多资源 Pandas 是 Python 中很流行的类库,使用它可 ...
- [数据清洗]-使用 Pandas 清洗“脏”数据
概要 准备工作 检查数据 处理缺失数据 添加默认值 删除不完整的行 删除不完整的列 规范化数据类型 必要的转换 重命名列名 保存结果 更多资源 Pandas 是 Python 中很流行的类库,使用它可 ...
- Linux 根目录所在分区被脏数据占满
背景: 公司在做一个项目,大概功能就是一个通行闸机的人脸识别系统,要经过门禁的人注册了之后,系统就会存储一张原始的图片在服务器的数据文件夹里面,包括了永久的存储和一些访客注册临时存储.一天周五的时 ...
- 【转】Pandas学习笔记(二)选择数据
Pandas学习笔记系列: Pandas学习笔记(一)基本介绍 Pandas学习笔记(二)选择数据 Pandas学习笔记(三)修改&添加值 Pandas学习笔记(四)处理丢失值 Pandas学 ...
- 如何使用R语言解决可恶的脏数据
转自:http://shujuren.org/article/45.html 在数据分析过程中最头疼的应该是如何应付脏数据,脏数据的存在将会对后期的建模.挖掘等工作造成严重的错误,所以必须谨慎的处理那 ...
- Python利用pandas处理Excel数据的应用
Python利用pandas处理Excel数据的应用 最近迷上了高效处理数据的pandas,其实这个是用来做数据分析的,如果你是做大数据分析和测试的,那么这个是非常的有用的!!但是其实我们平时在做 ...
- 【python基础】利用pandas处理Excel数据
参考:https://www.cnblogs.com/liulinghua90/p/9935642.html 一.安装第三方库xlrd和pandas 1:pandas依赖处理Excel的xlrd模块, ...
- Python3 Pandas的DataFrame数据的增、删、改、查
Python3 Pandas的DataFrame数据的增.删.改.查 一.DataFrame数据准备 增.删.改.查的方法有很多很多种,这里只展示出常用的几种. 参数inplace默认为False,只 ...
随机推荐
- SpringCloud学习笔记(3)——Hystrix
参考Spring Cloud官方文档第13.14.15章 13. Circuit Breaker: Hystrix Clients Netflix提供了一个叫Hystrix的类库,它实现了断路器模式. ...
- Apache服务器配置
之前做代码一直按照传统化的方法部署别人的网站,但是一直不成功,尝试了很多次最后才发现时虚拟主机的问题 使用apache默认为127.0.0.1和网站的配置发生冲突. 因此在apache的conf文件夹 ...
- 将后面的m个数移到前面
#include<iostream> #include<algorithm> #include<stdio.h> #include<numeric> u ...
- leetcode算法题3:分组,让每个组的最小者,相加之后和最大。想知道桶排序是怎么样的吗?
/* Given an array of 2n integers, your task is to group these integers into n pairs of integer, say ...
- 简介CentOS与 Ubuntu的不同
1.关于登录用户 centos可以使用root登录 ubuntu不能使用root登录 centos普通用户默认不能通过sudo取得root权限执行命令, ubuntu可以,centos需要sudo时 ...
- 深入理解java虚拟机_第三章(上)----->垃圾收集器与内存分配策略
1. 前言 这一版块内容比较多,分为两篇文章来做笔记.本文讲述上半部分垃圾收集部分;下一篇文章写内存分配部分. 概述 对象已死吗? 引用技术算法 可达性分析算法 再谈引用 两次标记 回收方法区 2. ...
- Postgres中表和元组的组织方式
PG version 9.5.3 PG中四种堆文件: 普通堆 临时堆 序列堆 TOAST表 PageHeaderData长度为24(截图为8.4版本,20字节)个字节包含的内容如下: 空闲空间的起始和 ...
- postgres 9.5 FDW变化
9.5主要是2个方法有变动: create_foreignscan_path extern ForeignPath *create_foreignscan_path(PlannerInfo *root ...
- wkhtmltopdf
最近要做一个html转pdf的功能,在网上找了很多内容,itext什么的,都不太满意,最后找到一个wkhtmltopdf,用起来真的很不错,还找到了一篇好文章,我就直接抄过来了,等有时间我再自己理一遍 ...
- java 之 职责链模式(大话设计模式)
目前很多OA办公自动化软件,加快了办公效率,简化流程.相信很多小伙伴都用过.笔者了解到的大多数办公软件底层实现流程大多数采用的都是Activity或者是JBPM框架. 今天笔者要说的也是类似于流程的一 ...