Python数据分析之数据清洗及特征处理


二、数据清洗及特征处理

🚩 2.1 缺失值观察与处理

2.1.1 缺失值观察

  • 查看列数据
import numpy as np
import pandas as pd
df = pd.read_csv('./train.csv')

# 查看列数据
df[['Age','Cabin','Embarked']].head()
  • 查看特征缺失值个数
# 方法 1: df.isnull()
ageIsNull = df['Age'].isnull().sum(axis = 0)

# 方法 2: df.count() / len(df)
# df.shape[0] 表示 df 行数
AgeIsNull = df.shape[0] - df['Age'].count()
  • 查看缺失值总结
# df.isnull(): 可以识别 null / None / Nan
# isnull, 有缺失值return true, axis=0为寻找列的缺失值
df.isnull().any(axis=0)

# axis=1 寻找行的缺失值
df.isnull().any(axis=1)  

# 计算 df 每一行有多少个缺失值的值,即按行统计缺失值
rows_null = df.isnull().sum(axis=1) 

# 按列统计缺失值
col_null = df.isnull().sum(axis=0)

# 统计整个df的缺失值
all_null = df.isnull().sum().sum()

# 统计某一列的缺失值
idx_null = df['列名'].isnull().sum(axis=0)

# 提取所有行有缺失值的信息
df.loc[df.isnull().any(axis=1),:] 

# np.nan: 不建议使用,只有数组数值运算时才可使用,如果数据类型为 String 则会报错
# np.nan不是空对象,对列表中的nan操作时不能使用"==np.nan"来判断,只能用np.isna()来操作。
# np.nan的数据类型是float

# None:不建议使用,数值列读取数据后,空缺值的数据类型为float64,所以用None一般索引不到

2.1.2 缺失值处理

💡 处理缺失值一般有两种方法,df.dropna() 或 df.fillna()

(1) df.dropna(): 删除含有空值的行或列
df['Age'].dropna()

df.dropna()官方文档

DataFrame.dropna(axis=0, how=‘any’, thresh=None, subset=None, inplace=False)

  • axis: 选取删除行(0)或是列(1), 默认 axis = 0
  • how: how = ‘all’ 表示这一行或列中的元素全部缺失(为nan)才删除这一行或列,how = ‘any’ 表示这一行或列中只要有元素缺失,就删除这一行或列
  • thresh: 一行或一列中至少出现了thresh个才删除。
  • subset:在某些列的子集中选择出现了缺失值的列删除,不在子集中的含有缺失值得列或行不会删除(有axis决定是行还是列)
  • inplace:确定是否创建新的对象进行修改。默认为inplase = False,即创建新的对象进行修改,原对象不变
(2) df.fillna(): 填充缺失值
df['Age'].fillna(0)

df.fillna()官方文档

DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)

  • value: 用来填充缺失值的值
  • method: ffill:用缺失值前面的一个值代替缺失值,如果axis =1,那么就是横向的前面的值替换后面的缺失值,如果axis=0,那么则是上面的值替换下面的缺失值。
  • backfill/bfill,缺失值后面的一个值代替前面的缺失值。注意这个参数不能与value同时出现
  • axis:确定填充维度,从行开始或是从列开始,{0 or ‘index’, 1 or ‘columns’}
  • inplace: 确定是否创建新的对象进行修改
  • limit:确定填充的个数,如果limit=2,则只填充两个缺失值。
  • downcast: 数据类型的转换(如果可能的话,将尝试向下转换为适当的相等类型)(例如float64到int64)。
(3) 检索空缺值再赋值
df[df['Age'].isnull()] = 0 # 把空值替换为0


🚩2.2 重复值观察与处理

2.2.1 查看数据中的重复值

df[df.duplicated()]

2.2.2 处理重复值

df = df.drop_duplicates()

df.drop_duplicates 去重
drop_dulicates 官方文档
DataFrame.drop_duplicates(subset=None, keep=‘first’, inplace=False, ignore_index=False)

  • subset:用来指定特定的列,默认 subset = None 为所有列
  • keep:确定要保留的副本。—first:删除第一次出现的副本。—last:删除除最后一次出现的重复项。—False:删除所有重复项。
  • ignore_index:ignore_index = True,结果轴将被标记为0,1,…,n - 1。默认为False


🚩2.3 特征观察与处理

💡 特征值大概分为两类
数值型特征:
1.离散型数值特征,e.g. Survived, Pclass
2.连续型数值特征,e.g. Age, Fare

文本型特征:
1.类别型文本特征,e.g. Sex, Cabin, Embarked
2.其他,e.g. Name

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


2.3.1 数据分箱(离散化)处理

💡 分箱操作
分箱方法是一种简单常用的预处理方法,通过考察相邻数据来确定最终值。
分箱实际上是按属性值划分的子区间。把待处理的数据(某列的属性值)按照一定的规则放进一些箱子中,考察每一个箱子中的数据,分别对各个箱子中的数据进行处理
分箱时需要确定如何分箱以及如何对每个箱子中的数据进行平滑处理

  • 等深分箱法:将数据集按记录行数分箱,每箱具有相同的记录数,每箱记录数成为箱子的深度
  • 等宽分箱法,使数据集在整个属性值的区间上平均分布,每个箱的区间范围成为箱子宽度

常用方法:

pandas.cut(): 将值转换为离散间隔

pandas.cut()官方文档

pandas.cut(x, bins, right = True, labels = None, retbins = False, precision = 3, include_lowest = False, duplicates = ‘raise’, ordered = True

  • x: 被切分的类数组数据,必须是1维的(不能用DataFrame)
  • bins: 合并的标准 int: 将 x 平分成bins份。x 的范围在每侧扩展0.1%,以包括 x 的最大值和最小值
  • sequence of scalars: 允许不均匀宽度的bin边缘,没有扩展x的范围
  • interval Index: 定义要使用的精确区间 right: 表示是否包含区间最右部分,默认为right = True
  • labels: 指定返回的bin标签,若label = False, 仅返回bin的整数指示符
  • retbin: 表示是否返回bin,当bins为一个Int类型的标量时比较有用,默认rebin = False
  • precesion: 保留区间的小数点的位数,默认为3 include_lowest: 表示区间的左边是开的还是闭的,默认为 False
  • duplicates: 是否允许重复区间。raise: 不允许,drop:允许
  • ordered:表示标签是否有序。适用于返回类型为Categorical and Series (with Categorical dtype)。默认为True, 对生成的类型进行分类
pandas.qcut(): 根据 rank 或 sample quantiles 将变量离散化为大小相等的桶

pandas.qcut()官方文档

pandas,qcut(x, q, labels = None, retbins = False, precision = 3, duplicates = ‘raise’)

  • x: 被切分的类数组数据,必须是1维的
  • q: 分位数。10表示十分位,4表示四分位
  • labels: 指定返回的bin标签,若label = False, 仅返回bin的整数指示符
  • retbin: 表示是否返回bin,当bins为一个Int类型的标量时比较有用,默认rebin = False
  • precesion: 保留区间的小数点的位数,默认为3
  • duplicates: 是否允许重复区间。raise: 不允许,drop:允许

(1) 将连续变量Age平均分箱成5个年龄段,并分别用类别变量12345表示

df['AgeBand'] = pd.cut(df['Age'], 5,labels = [1,2,3,4,5])

(2) 将连续变量Age划分为[0,5) [5,15) [15,30) [30,50) [50,80)五个年龄段,并分别用类别变量12345表示

df['AgeBand'] = pd.cut(df['Age'], bins = [0,5, 15, 30, 50, 80], labels = [1, 2, 3, 4, 5], right = False, include_lowest = True)

(3)将连续变量Age按10% 30% 50 70% 90%五个年龄段,并用分类变量12345表示

df['AgeBand'] = pd.qcut(df['Age'],[0,0.1,0.3,0.5,0.7,0.9],labels = [1,2,3,4,5])

2.3.2 对文本变量进行转换

1. 查看文本变量名及种类

# 返回特征值名称
df.unique()

# 返回特征值个数
df.nunique()

# 返回特征值及其个数
df.value_counts()

2. 文本编码
💡 离散特征的编码分为两种情况;
1. 离散特征的取值之间没有大小的意义,比如color: [red, blue],那么就使用one-hot编码
2. 离散特征的取值有大小的意义,比如size:[X, XL,XXL],那么就使用数值的映射{X: 1, XL: 2, XXL: 3}

  • 将文本变量Sex, Cabin ,Embarked用数值变量12345表示
#方法一: replace
df['Sex_num'] = df['Sex'].replace(['male','female'],[1,2])

#方法二: map
df['Sex_num'] = df['Sex'].map({'male': 1, 'female': 2})

#方法三: 使用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))

# zip: 将可迭代的对象作为参数,将对象中对应的元素打包成一个个元祖,然后返回由这些元组组成的列表 
  • 将类别文本转换为one-hot编码
# One-Hot Encode for one category
Embarked = pd.get_dummies(df["Embarked"])
df = pd.merge(df,Embarked,left_index=True,right_index=True)

# One_Hot Encode for multiple categories
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)

pandas.get_dummies()官方文档

pandas.get_dummies(data, prefix=None, prefix_sep=’_’, dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)

  • data:输入的数据
  • prefix : get_dummies转换后,列名的前缀
  • prefix_sep: 前缀分隔符,默认为’_’
  • dummy_na : 增加一列表示空缺值,如果False就忽略空缺值
  • columns : 指定需要实现类别转换的列名
  • sparse: 伪编码的列由SparseArray (True)或常规NumPy数组(False)支持。
  • drop_first : 获得k中的k-1个类别值,去除第一个。
  • dtype: 新列的数据类型,默认为np.uint8

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

df['Title'] = df.Name.str.extract('([A-Za-z]+)\.', expand=False)

💡 这里用到了正则表达式

  • [A-Za-z]代表任一字母(大写或小写)
  • + 代表+号前的字符出现1次或多次
  • \. 代表 .
  • ([A-Za-z]+). 是匹配 一个或多个字母并且以.结尾的所有字符串组合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值