DW数据清洗及特征处理_fightinglearning的博客-程序员宅基地

技术标签: python数据分析  


数据清洗及特征处理可以让数据看起来规律性更强,为后面操作做铺垫。

我们拿到的数据通常是不干净的,所谓的不干净,就是数据中有缺失值,有一些异常点等,需要经过一定的处理才能继续做后面的分析或建模,所以拿到数据的第一步是进行数据清洗,本章我们将学习缺失值、重复值、字符串和数据转换等操作,将数据清洗成可以分析或建模的亚子。

1 缺失值观察与处理

我们拿到的数据经常会有很多缺失值,比如我们可以看到Cabin列存在NaN,那其他列还有没有缺失值,这些缺失值要怎么处理呢

1.1 任务一:缺失值观察
(1) 请查看每个特征缺失值个数
(2) 请查看Age, Cabin, Embarked列的数据
以上方式都有多种方式,所以大家多多益善

#方法一
df.info()
#方法二
df.isnull().sum()  #缺失值(为空)的个数
df.isna().sum() #缺失值的个数

输出一样

PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

1.2 任务二:对缺失值进行处理
(1)处理缺失值一般有几种思路

(2) 请尝试对Age列的数据的缺失值进行处理

(3) 请尝试使用不同的方法直接对整张表的缺失值进行处理

#处理缺失值的一般思路:
#提醒:可使用的函数有--->dropna函数与fillna函数
#将空值怎么变成了NaN
df[df['Age'] == np.nan] = 0
df.loc[5:7,'Age']
#df[df['Age']==None]=0
df.loc[5:7,'Age']
5     NaN
6    54.0
7     2.0
Name: Age, dtype: float64
#age 是有空值,不是NaN,所以用isnull
df[df['Age'].isnull()] = 0 # 这是将一整行变成了0 是不对的
df.loc[5:7]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
5 0 0 0 0 0 0.0 0 0 0 0.0000 0 0
6 7 0 1 McCarthy, Mr. Timothy J male 54.0 0 0 17463 51.8625 E46 S
7 8 0 3 Palsson, Master. Gosta Leonard male 2.0 3 1 349909 21.0750 NaN S

检索空缺值用np.nan要比用None好,数值列读取数据后,空缺值的数据类型为float64所以用None一般索引不到,比较的时候最好用np.nan

#正解
"""
·dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
axis=0按行删除,1按列
how:'any','all'
thresh要求保留的非NA值个数 eg.thresh=2 仅保留至少具有2个非NA值的行/列
subset=['列名1', '列名2']定义要在哪些列中查找缺失值
inplace=True/False 为True时对原数据进行永久性修改
例子:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html
"""
df.dropna(axis=0,how='any').head(3) #默认按行axis=0,方式any
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
6 7 0 1 McCarthy, Mr. Timothy J male 54.0 0 0 17463 51.8625 E46 S
"""
·fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
value缺失数据填充的值
method:ffill/bfill 将上一个有效观测向前传播到下一个缺失值里,也就是将缺失值前面的数填到缺失的地方(感觉是按列) 
limit=n:替换每一列的前n个NaN元素 
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html
"""
df.fillna(0).head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 0 S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 0 S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 0 S

2 重复值观察与处理

由于这样那样的原因,数据中会不会存在重复值呢,如果存在要怎样处理呢

df.duplicated() #查看是否有重复的行(两行所有列完全一样算重复)
#也可以对特定的列进行重复项判断
df.duplicated(['Age'])
#删除重复行
"""有一个keep参数
当keep=False时,就是去掉所有的重复行 
当keep=‘first’时,就是保留第一次出现的重复行 
当keep=’last’时就是保留最后一次出现的重复行。
"""
df.drop_duplicates().head(3)

3 特征观察与处理

我们对特征进行一下观察,可以把特征大概分为两大类:
数值型特征:Survived ,Pclass, Age ,SibSp, Parch, Fare,其中Survived, Pclass为离散型数值特征,Age,SibSp, Parch, Fare为连续型数值特征
文本型特征:Name, Sex, Cabin,Embarked, Ticket,其中Sex, Cabin, Embarked, Ticket为类别型文本特征

数值型特征一般可以直接用于模型的训练,但有时候为了模型的稳定性及鲁棒性会对连续变量进行离散化。
文本型特征往往需要转换成数值型特征才能用于建模分析。

3.1 任务一:对连续型特征(年龄)进行分箱(离散化)处理

#分箱操作是什么:
#将连续型变量分到不同箱子里成为离散型变量
#平均分箱成5个年龄段
#【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.cut.html
df['AgeBand'] = pd.cut(df['Age'], 5,labels = ['1','2','3','4','5'])
df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked AgeBand
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 2
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 3
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 2
#划分为(0,5](5,15] (15,30] (30,50] (50,80]五个年龄段
df['AgeBand'] = pd.cut(df['Age'],[0,5,15,30,50,80],labels = ['1','2','3','4','5'])
df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked AgeBand
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 3
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 4
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 3
#按10% 30% 50 70% 90%五个年龄段分箱
df['AgeBand'] = pd.qcut(df['Age'],[0,0.1,0.3,0.5,0.7,0.9],labels = ['1','2','3','4','5'])  
#存疑
#【参考】https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.qcut.html
df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked AgeBand
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 2
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 5
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 3

3.2 任务二:对文本型特征转换成数值型特征的方法

#(1) 查看类别文本变量名及种类
print(df['Sex'].value_counts())  #返回每个元素的值有多少 
print(df['Sex'].unique())   #返回所有唯一值
print(df['Sex'].nunique())  #返回唯一值的个数
male      577
female    314
Name: Sex, dtype: int64
['male' 'female']
2
#(2)将文本变量Sex, Cabin ,Embarked用数值变量12345表示 
#方法一: replace
df['Sex_num'] = df['Sex'].replace(['male','female'],[1,2])
df.head(3)

#方法二: map
df['Sex_num'] = df['Sex'].map({
    'male': 1, 'female': 2}) #map一个映射,没有映射的自变量会变成NaN
df.head(3)
#方法三: 使用sklearn.preprocessing的LabelEncoder
#存疑????????????????????
from sklearn.preprocessing import LabelEncoder
for feat in ['Cabin', 'Ticket']:
    lbl = LabelEncoder()  
    
    label_dict = dict(zip(df[feat].unique(), range(df[feat].nunique())))
    df[feat + "_labelEncode"] = df[feat].map(label_dict)
#     df[feat + "_labelEncode"] = lbl.fit_transform(df[feat].astype(str))

df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked AgeBand Sex_num Cabin_labelEncode Ticket_labelEncode
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 2 1 0.0 0
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 5 2 1.0 1
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 3 2 0.0 2
# (3) 将文本变量Sex, Cabin, Embarked用one-hot编码表示

#  OneHotEncoder
for feat in ["Age", "Embarked"]:
#     x = pd.get_dummies(df["Age"] // 6)
#     x = pd.get_dummies(pd.cut(df['Age'],5))
    x = pd.get_dummies(df[feat], prefix=feat)
    df = pd.concat([df, x], axis=1)
    #df[feat] = pd.get_dummies(df[feat], prefix=feat)
    
df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare ... Age_65.0 Age_66.0 Age_70.0 Age_70.5 Age_71.0 Age_74.0 Age_80.0 Embarked_C Embarked_Q Embarked_S
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 ... 0 0 0 0 0 0 0 0 0 1
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 ... 0 0 0 0 0 0 0 1 0 0
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 ... 0 0 0 0 0 0 0 0 0 1

3 rows × 107 columns

3.3 任务三:从纯文本Name特征里提取出Titles的特征(所谓的Titles就是Mr,Miss,Mrs等)

df['Title'] = df.Name.str.extract('([A-Za-z]+)\.', expand=False) 
#.(点号)-匹配除'\ n'的任意字符
"""
expand=True不加的话,df1中将只有一列,其实就是一个series。
当然,可以直接将这列加到df中:df[['新列名']]直接将新的两列加入原先dataframe中"""
df.head(3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare ... Age_66.0 Age_70.0 Age_70.5 Age_71.0 Age_74.0 Age_80.0 Embarked_C Embarked_Q Embarked_S Title
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 ... 0 0 0 0 0 0 0 0 1 Mr
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 ... 0 0 0 0 0 0 1 0 0 Mrs
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 ... 0 0 0 0 0 0 0 0 1 Miss

3 rows × 108 columns

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/fightinglearning/article/details/108158041

智能推荐

【考研高数-线性代数-强化】第四章 线性方程组(重点,别马虎大意)_刘鑫磊up的博客-程序员宅基地

【考研高数-线性代数-基础】第四章 线性方程组【重点】课本讲义:P82~P111一:网络结构网络图二:基本内容与重要结论1.基础知识2.主要定理三:典型例题1.基础解系2.解方程组Ax=b通用方程组求解: 1.已知方程组 同解变形(行变换)讨论参数 2.抽象方程组 秩、解的结构、推理分析一:齐次方程组Ax=0 n-r(A)线性无关的解向量、基础解系二:非齐次方程组Ax=b 有解判...

73.ORM聚合函数详解:Count_长大的小蚂蚁的博客-程序员宅基地

Count:用来求某个数据的个数。在以下所有的示例中所采用的模型为:from django.db import models# 定义作者模型class Author(models.Model): name = models.CharField(max_length=100, unique=True) age = models.IntegerField() ema...

ZUPT的相关初步理解_slam让我头疼的博客-程序员宅基地_zupt算法

参考至https://zhuanlan.zhihu.com/p/115529319零速修正(Zero Velocity Update, ZUPT)即,当载体处于静止状态时,载体此时的速度为零,利用载体中的惯性系统的解算速度作为系统速度误差的观测量,对其他误差量进行修正,改善静止状态下的组合导航结果,不需要增加外部传感器,因而是一种有效且廉价易实现的技术。零速修正一般方法利用卡尔曼滤波进行。当检测到载体处于静止状态时,利用SINS子系统解算的速度作为系统速度误差的观测量,进行卡尔曼滤波估计,利用更新后的

html5 css3d,HTML5/CSS3雀跃的3D字符串_weixin_39841572的博客-程序员宅基地

CSS语言:CSSSCSS确定html,body {width: 100%;height: 100%;background: #76b852;background: -webkit-linear-gradient(to left, #76b852, #8DC26F);background: -webkit-linear-gradient(right, #76b852, #8DC26F);backg...

mybatis plus查询方式_年少一去不复返的博客-程序员宅基地_mybatisplus查询

这两天学习了一下mybatis plus。简单总结了一下条件构造器使用的查询方式。官网: MyBatis-Plus /** * @param isDel 是否删除 */ void userUpdate(int isDel) { //普通查询 QueryWrapper<User> queryWrapper = new QueryWrapper<>();//条件构造器 queryWrapper.eq("isDel",

eslint 的配置与使用_苍海一声呵呵呵的博客-程序员宅基地

eslint 的配置与使用格式rules: { "规则名": [规则值, 规则配置]}规则值"off"或者0 //关闭规则"warn"或者1 //在打开的规则作为警告(不影响退出代码)"error"或者2 //把规则作为一个错误(退出代码触发时为1).eslinrc.js 配置官方参考module.exports = { root: true, // 设置当前目录为根目录,停止在父级目录中寻找eslint配置 env: { node: tru

随便推点

Elastic Stack系列之在基于docker的ELK上新增filebeat(二)_IT管道工的博客-程序员宅基地

上面一篇已经讲解了如何基于docker构建ELK环境。接下来记录一下,在ELK的基础上新增filebeat的方法。1、下载filebeat的软件包在这个例子中我们用的是目前filebeat的最新版本即7.4.2,下载地址为://download.csdn.net/download/yangqinfeng1121/11975165把filebeat放到要抽取日志的服务上,并解压开t...

android 搞通camera preview,android – 在SurfaceView加载Camera Preview时显示我的布局_岳意贺的博客-程序员宅基地

好吧,问题是我在xml布局中使用了SurfaceView.你打电话的那一刻:setContentView(your_layout) – > XML文件被夸大了.这意味着,SurfaceView也会膨胀.这再次意味着调用SurfaceView onSurfaceCreated方法,触发打开相机等.因此,整个过程需要一段时间,因此,您之前的Activity(例如,使用SurfaceView启动A...

Emulator: ERROR: x86 emulation currently requires hardware acceleration!/ VT is disabled in BIOS._Nicoolidu的博客-程序员宅基地

创建Android emulator 出现的问题emulator: ERROR: x86 emulation currently requires hardware acceleration!Please ensure Intel HAXM is properly installed and usable.CPU acceleration status: HAXM is not i

文件名后跟时间后缀_nicholaszt97的博客-程序员宅基地

import datatime# 文件名后跟时间后缀time = datetime.datetime.today()time_list = list(time.utctimetuple())[:-3]save_path = './dict/dict_'+''.join([str(i).zfill(2) for i in time_list]) +'.csv'# 读取最新时间后缀的文件...

OpenGL学习-2-鼠标事件响应练习工程代码_牙膏味奥利奥的博客-程序员宅基地

#include#include#include#includevoid init(void);void drawCoordinates(void);void CALLBACK reshape(GLsizei w,GLsizei h);void CALLBACK OnLButtonDown(AUX_EVENTREC *);void CALLBACK OnLButtonMove(AUX_EVENTR

Spring利用JDBCTemplate批量更新数据_dingyu_12的博客-程序员宅基地

public void addBatchScyh(List<User> userList) throws Exception { final List<User> yhList = userList; final Long drsj = CalendarUtil.getLongDateTime(); if(yhList != null &&...