五、Python数据挖掘(Pandas高级处理)
目录:
- 五、Python数据挖掘(Pandas高级处理)
- pd.isnull(DataFrame数组) DataFrame数组.isnull()
- pd.notnull(DataFrame数组) DataFrame数组.notnull()
- DataFrame数组.dropna(axis="rows", inplace=False)
- DataFrame数组.fillna(value, inplace)
- DataFrame数组.replace(to_replace=" ", value=np.nan)
- sr = pd.qcut(data, bins)
- sr = pd.cut(data, [ ])
- Series数组.value_counts()
- pd.get_dummies(sr, prefix=)
- pd.concat([ ], axis=0)
- pd.merge(left, right, how="inner", on=[ ])
- pd.crosstab(value1, value2)
- DataFrame数组.pivot_table([ ], index=[ ])
- object_ = DataFrame.groupby(by=索引, as_index=False)
一、Nan 缺失值处理
回顾:在 Numpy库 中介绍到,当读取的数据文件中包含 空格 或一些 字符串 时就可能会出现缺失值 NaN
处理思路:
- 删除含有缺失值的样本
- 替换/插补缺失值,如:平均值替换
具有一定的复杂程度,在 Pandas 中就较为容易
判断是否为缺失值 NaN:
pd.isnull(DataFrame数组)
DataFrame数组.isnull()上述两种调用方式都可以
判断 DataFrame数组 中是否为缺失值,是则对应位置为 True ,否则对应位置为 Falsepd.notnull(DataFrame数组)
DataFrame数组.notnull()上述两种调用方式都可以
判断 DataFrame数组 中是否有值,是则对应位置为 True ,否则对应位置为 False
例:快速判断一个 DataFrame数组 中是否存在缺失值:
np.any() 配合 pd.isnull() 的方式,判断是否存在缺失值:
判断列是否含有缺失值:
np.all() 配合 pd.notnull() 的方式,判断是否都有值:
判断列是否都有值:
1.处理方式——删除:
DataFrame数组.dropna(axis=“rows”, inplace=False)
把含有缺失值 NaN 的行删除
当 axis=“rows” 时,会删除含缺失值 NaN 的行,axis 默认为 rows
当 axis=“columns” 时,会删除含缺失值 NaN 的列
当 inplace=True 时,会直接在原 DataFrame数组 上进行修改
当 inplace=False 时,会返回一个删除含 NaN 行的新数组,不会修改 DataFrame数组,inplace 默认为 False
例:
2.处理方式——替换:
DataFrame数组.fillna(value, inplace)
将 DataFrame数组 中的缺失值 NaN 统一修改为 value
value 统一修改后的值
当 inplace=True 时,会直接在原 DataFrame数组 上进行修改
当 inplace=False 时,会返回一个修改后的新数组,不会修改 DataFrame数组,inplace 默认为 False
例:分别替换为各列对应的平均值
二、其他类型缺失值处理
缺失值可能不是 NaN,可能是其他标记值,如:?
此时,我们需要把 ? 替换为 np.nan ——即 NaN 缺失值类型,再对 NaN 缺失值进行处理
DataFrame数组.replace(to_replace=" ", value=np.nan)
把是 to_replace 的值全部替换为 value
to_replace=" " 是需要替换的值,如:to_replace="?"
value= 是替换成的值,如:value=np.nan,替换成 NaN 缺失值
三、数据离散化
1.数据类别处理
一般来说,事物的属性可能并不完全能够使用数字来表示,如:性别男或女,毛发的颜色等等......
以性别为例,如果以数字代表男女,如:1-男、2-女,但是计算机并不懂得这一数字的含义,以计算机的角度来看,计算机知道只知道这是两个数字,并且它们具有大小排名,但是性别属性是不应该具有大小排名之分的,这样带来的影响并不好,如何处理这些数据呢?
处理思路:额外增加其他属性,符合时为1,不符合时为0即可
2.数据离散化
连续属性的离散化就是将连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值
比如说:以身高为例
数据:
height = [165, 174, 160, 180, 159, 163, 192, 184]
离散化:
连续属性离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具
3.Panda 实现数据离散化
(1)分组
自动分组:
sr = pd.qcut(data, bins)
实现自动分组
data 需要分组的数据
bins 要分成的组数
返回值 返回一个 Series 数组
sr = pd.cut(data, [ ])
data 需要分组的数据
[ ] 设定的分组区间,这里输入是所有边界
返回值 返回一个 Series 数组
查看分组数量情况:
Series数组.value_counts()
用于查看分组数量情况
例:
(2)将分组结果转换为 one-hot 编码
pd.get_dummies(sr, prefix=)
将分组结果转换为 one-hot 编码
sr 经过分组操作的 Series 数组
prefix 指定前缀,一般取属性名即可
例:就以身高分组为例
数据:
height = [165, 174, 160, 180, 159, 163, 192, 184]
离散化结果:
分组:
将分组结果转换为 one-hot 编码:
四、合并处理
1.按方向拼接
pd.concat([ ], axis=0)
按照行或列进行拼接
[ ] 要进行拼接的数组,列表形式
- axis 指定按行或按列进行拼接:
axis=0 表示进行竖直拼接
axis=1或-1 表示进行水平拼接
注:如果存在数据空缺的情况,空缺的位置用缺失值 NaN 填充
例:根据身高表,对身高进行数据离散化,再利用拼接将离散化后的数据拼接回原身高表中
数据:
准备数据:
import numpy as np
import pandas as pd
index = ["张三", "李四", "王二", "小蕾", "小明", "老王", "王五", "小六"]
columns = ["序号", "身高"]
information = np.array([[1, 165], [2, 174], [3, 160], [4, 180], [5, 159], [6, 163], [7, 192], [8, 184]])
information = pd.DataFrame(information, index=index, columns=columns)
取出数据:
height = pd.Series(information["身高"])
分组:
height = pd.cut(height, [150, 165, 180, 195])
转换为 one-hot 编码:
height = pd.get_dummies(height, prefix="身高")
拼接到原数据表上:
information = pd.concat([information, height], axis=1)
2.按索引拼接
可以参考 SQL 中根据索引来进行连接的方式,一般可以根据主码来进行连接
pd.merge(left, right, how=“inner”, on=[ ])
left 左表
right 右表
how=“inner” 连接方式,默认连接方式为内连接
on=[ ] 索引,即按什么索引进行连接,一般可以是主码或主码组
how 参数 | 含义 |
---|---|
“left” | 左外连接 |
“right” | 右外连接 |
“outer” | 外连接 |
“inner” | 内连接 |
在有意义的一张表中,索引就是这张表的属性,而每一行就是一个个不同的事物
当两张表进行连接时,会根据 on 所指定的索引中值相等的行 (因为 on 指定的索引/属性中,值相等的行可以视为同一事物。这些行在左表中具有一些属性;在右表中具有其他属性,这些所有属性组合起来,构成了新的表中的这些行的所有属性) 构成新的表。而那些 on 所指定的索引在两张表之间没有相同值的行,在构成新的表时由于缺少了某一张表的属性,而导致在构成新的表时缺少完整的属性,而只能用 NaN 来表示
在新的表中,对这些含 NaN 的行的不同的保留情况,分为了四种不同的连接方式:
- 内连接:不保留那些 on 所指定的索引在两张表之间没有相同值的行,即不保留含 NaN 的行
- 外连接:保留那些 on 所指定的索引在两张表之间没有相同值的行,即保留含 NaN 的行
- 左外连接:保留出现在左表中那些 on 所指定的索引在两张表之间没有相同值的行,即保留左表那些含 NaN 的行
- 右外连接:保留出现在右表中那些 on 所指定的索引在两张表之间没有相同值的行,即保留右表那些含 NaN 的行
注:大多数情况下使用的是内连接
例:
数据:
left = pd.DataFrame({"key1": ["K0", "K0", "K1", "K2"],
"key2": ["K0", "K1", "K0", "K1"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"]})
right = pd.DataFrame({"key1": ["K0", "K1", "K1", "K2"],
"key2": ["K0", "K0", "K0", "K0"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"]})
内连接:
外连接:
左外连接:
右外连接:
五、交叉表与透视表
交叉表和透视表可以理解成将两个变量放在一起,探索两个变量之间的关系
1.交叉表
pd.crosstab(value1, value2)
将 value1 和 value2 两个数据列表比较
value1 数据列表1
value2 数据列表2
例:
准备数据:自 2020-01-01 开始,生成 600 天的股票涨跌数据
import numpy as np
import pandas as pd
stock_rate = np.random.normal(size=(600, 1))
date = pd.date_range(start = "2021-01-01", periods=600, freq="D")
stock_rate = pd.DataFrame(stock_rate, index=date, columns=["涨跌幅"])
要求:统计星期和涨跌幅之间的关系
根据要求,增加一列星期索引/属性:
date = pd.to_datetime(stock_rate.index)
stock_rate["星期"] = date.weekday
根据要求,增加一列涨跌情况属性(1表示涨,0表示跌):
stock_rate["涨跌情况"] = np.where(stock_rate["涨跌幅"] > 0, 1, 0)
生成交叉表:
data = pd.crosstab(stock_rate["星期"], stock_rate["涨跌情况"])
- 这里统计了所有股票中不同星期中的涨跌情况
将交叉表的数值显示转化为频率显示:
data.div(data.sum(axis=1), axis=0)
首先分别计算每个星期股票的总数:
data.sum(axis=1)
然后再让每个星期中的涨跌数量情况除以总数,即可转化为涨跌的频率:
data.div(data.sum(axis=1), axis=0)
注意:由于 data.sum(axis=1) 是一维数组,而 data 是二维数组;我们需要 data 除以竖直的 data.sum(axis=1),因此我们在 div(other[, axis=1]) 中,需要把 other 行列转置一下,即指定 axis=0 即可
一维数组: 二维数组:
最后我们画成柱状图的形式来进行表示:
data.div(data.sum(axis=1), axis=0).plot(kind="bar", stacked=True)
注:这里的 stacked=True 就是把柱状图设置为堆叠显示
如果出现红色报错,可能存在中文显示错误,加上以下代码即可:
import matplotlib.pyplot as plt
# 指定默认字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.family']='sans-serif'
# 解决负号'-'显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
2.透视表
DataFrame数组.pivot_table([ ], index=[ ])
使用透视表,实现刚才的过程更加简单
DataFrame数组 需要进行操作的总表
[ ] 需要进行分组的内容——因变量
index=[ ] 按照 index=[ ] 索引进行分组——自变量
例:
这里直接显示的就是 1 的占比
六、分组与聚合
分组与聚合的含义,如图:
如:表格中的 name 的分数 score 是累加的,且表格中的累加过程并不删除,而是保留在表格中,那么这种情况下,就需要对最终分数 score 进行筛选:
如图,先根据主码 name 进行分组,分组后取最大值后即为聚合
object_ = DataFrame.groupby(by=索引, as_index=False)
根据 by=索引 对数组进行分组
by=索引 是分组的依据,会根据指定索引把值相同的行分为一组
例:
数据:
col = pd.DataFrame({"color": ["white", "red", "green", "red", "green"],
"object": ["pen", "pencil", "pencil", "ashtray", "pen"],
"price1": [5.56, 4.20, 1.30, 0.56, 2.75],
"price2": [4.75, 4.12, 1.60, 0.75, 3.15]})
分组并聚合:
col.groupby(by="color")["price1"].max()