数据分析与挖掘入门——学习笔记(九)Pandas高级操作
1 缺失值处理
对于获取到的数据,总会有一些是缺少的,如果这些缺少的数据对于我们的接下来的工作无关紧要,就可以直接舍弃;而有作用的就要应该补齐。我们使用一些电影数据来说明接下来的操作,先看看电影数据的结构
import pandas as pd # 读取电影数据 movie = pd.read_csv("data/IMDB/IMDB-Movie-Data.csv")
index | Rank | Title | Genre | Description | Director | Actors | Year | Runtime (Minutes) | Rating Votes | Revenue (Millions) | Metascore |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | Guardians of the Galaxy | Action,Adventure,Sci-Fi | A group of intergalactic criminals are forced … | James Gunn | Chris Pratt, Vin Diesel, Bradley Cooper, Zoe S… | 2014 | 121 | 8.1 | 757074 | 333.13 76. |
1.1 判断缺失值
首先判断是否空缺值
pd.notnull(movie) # 这个函数会把NaN的数值返回False,非NaN的数值返回True
pd.isnull(movie).head(10) # 这个函数会把NaN的数值返回True,非NaN的数值返回False
1.2 丢弃缺失值
对于不重要的数据可以直接舍弃
movie.size # 12000 movie = movie.dropna() # 丢弃空缺的数据行 movie.size # 10056
丢弃之后数量从12000变成了10056
1.3 替换缺失值
通常情况下缺失的只是一组数据的一小部分,这时候丢弃就是非常浪费的了,同时如果这组数据比较重要,那么丢弃就不可取,而是使用替换。
替换可以用中位数、众数、均值等替换,或者回归方程,最近值、固定值替换,高级一点可以使用拉 格朗日插值法和牛顿插值法
import numpy as np # 读取电影数据 movie = pd.read_csv("data/IMDB/IMDB-Movie-Data.csv") np.any(pd.isnull(movie)) # True
# ①判断哪一列有缺失值 for col in movie.columns: # pd.isnull(movie[col])将当前列的缺失值转换为True,any()判断数组中是否至少有一个为True,是就返回True if (np.any(pd.isnull(movie[col]))): # 使用fillna()来填充缺失值,第一个参数的替换后的值,inplace参数表示是否修改原数据 movie[col].fillna(movie[col].mean(), inplace=True)
np.any(pd.isnull(movie)) # 可以看到在变换之后any返回为False,说明已经没有缺失值了 # False
1.4 当缺失值不为NaN的时候
把它替换成NaN,如下面这组缺失值为?的数据
wis = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data")
····· 22 1057013 8 4 5 1 2 ? 7 3 1 4 ·····
这种情况下用any有缺失值但是不是NaN所以判断不出来
np.any(pd.isnull(wis)) # False
那么,就先替换掉这个?,变成NaN
# 如果缺失值不是np.NaN 首先替换成nan wis = wis.replace(to_replace='?', value=np.NAN) np.any(pd.isnull(wis)) # 再次查看是否有缺失值 True # 可以看到现在是有缺失值的
接下来在进行其他缺失值操作
2 数据的离散化
- 离散化的概念
把连续的数据 分成几段, 处于某一段中的所有数据 忽略他们之间的区别 - 离散化的作用
- ① 可以降低数据属性的个数
- ② 可以是数据稳定性更强
- ③ 可以降低异常值对结果的影响
- ④有一些算法 更适合处理离散的值 比如逻辑回归
案例:股票的涨跌幅离散化
我们对股票每日的”p_change”进行离散化
先看看数据
data = pd.read_csv("data/stock_day/stock_day.csv") p_change= data['p_change'] p_change.head()
2018-02-27 2.68 2018-02-26 3.02 2018-02-23 2.42 2018-02-22 1.64 2018-02-14 2.05 Name: p_change, dtype: float64
2.1 使用qcut()进行离散化
qcut会根据分组个数均匀分组
# 第一个参数为分组的依赖索引,第二个参数为分的组别 qcat = pd.qcut(data['p_change'], 10) qcat.value_counts() # 可见qcut会根据参数分成均匀的组别 (5.27, 10.03] 65 (0.26, 0.94] 65 (-0.462, 0.26] 65 (-10.031, -4.836] 65 (2.938, 5.27] 64 (1.738, 2.938] 64 (-1.352, -0.462] 64 (-2.444, -1.352] 64 (-4.836, -2.444] 64 (0.94, 1.738] 63 Name: p_change, dtype: int64
2.2 使用cut()进行分组
cut()方法是根据自定义的分组区间来分组
bins =[-12,-8,-5,-3,0,3,5,8,12] cat = pd.cut(data['p_change'], bins) cat.value_counts() (0, 3] 215 (-3, 0] 188 (3, 5] 57 (-5, -3] 51 (5, 8] 43 (-8, -5] 34 (-12, -8] 28 (8, 12] 27 Name: p_change, dtype: int64
2.3 使用哑变量矩阵离散化
哑变量实际上就是生成数据与区间的ont-hot的dataframe格式
# 生成哑变量矩阵 参数1 要生成哑变量矩阵的数据 参数2 (可选)每一列的前缀 如果没有前缀就是 列名分组的区间 dummies = pd.get_dummies(cat,prefix='rise')
3 数据合并
3.1 concat
直接把表格堆叠在一起的合并方式
# concat数据合并 参数1 要合并的所有数据的list 参数2 按照行还是列进行合并 pd.concat([data,dummies],axis=1).head()
open high close low volume price_change p_change ma5 ma10 ma20 ... v_ma20 turnover rise_(-12, -8] rise_(-8, -5] rise_(-5, -3] rise_(-3, 0] rise_(0, 3] rise_(3, 5] rise_(5, 8] rise_(8, 12] 2018-02-27 23.53 25.88 24.16 23.53 95578.03 0.63 2.68 22.942 22.142 22.875 ... 55576.11 2.39 0 0 0 0 1 0 0 0 2018-02-26 22.80 23.78 23.53 22.80 60985.11 0.69 3.02 22.406 21.955 22.942 ... 56007.50 1.53 0 0 0 0 0 1 0 0 2018-02-23 22.88 23.37 22.82 22.71 52914.01 0.54 2.42 21.938 21.929 23.022 ... 56372.85 1.32 0 0 0 0 1 0 0 0 ·····
3.2 merge
用于dataframe数据连接,类似于mysql的表格连接,同样分为左连接,右连接,内连接,外连接
pd.merge(left, right, how=’inner’, on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True,suffixes=(‘_x’, ‘_y’), copy=True, indicator=False,validate=None)
- left:连接的左表
- right:连接的右表
- how:连接方式,分为right,left,inner,outer,默认是inner
- on:连接后的两个表之间的公键
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']}) left A B key1 key2 0 A0 B0 K0 K0 1 A1 B1 K0 K1 2 A2 B2 K1 K0 3 A3 B3 K2 K1 right C D key1 key2 0 C0 D0 K0 K0 1 C1 D1 K1 K0 2 C2 D2 K1 K0 3 C3 D3 K2 K0
现在对两个表进行连接
左连接
result = pd.merge(left, right, how='left', on=['key1', 'key2']) result # 左表全部保留,右表缺失的值会变成NaN A B key1 key2 C D 0 A0 B0 K0 K0 C0 D0 1 A1 B1 K0 K1 NaN NaN 2 A2 B2 K1 K0 C1 D1 3 A2 B2 K1 K0 C2 D2 4 A3 B3 K2 K1 NaN NaN
右连接
result = pd.merge(left, right, how='right', on=['key1', 'key2']) result # 右表全部保留,左表缺失的值会变成NaN A B key1 key2 C D 0 A0 B0 K0 K0 C0 D0 1 A2 B2 K1 K0 C1 D1 2 A2 B2 K1 K0 C2 D2 3 NaN NaN K2 K0 C3 D3
内连接
result = pd.merge(left, right, how='inner', on=['key1', 'key2']) result # 两个表都有的部分保留,缺失的舍弃 A B key1 key2 C D 0 A0 B0 K0 K0 C0 D0 1 A2 B2 K1 K0 C1 D1 2 A2 B2 K1 K0 C2 D2
外连接
result = pd.merge(left, right, how='outer', on=['key1', 'key2']) result # 两个表所有数据保留,缺失的用NaN替换 A B key1 key2 C D 0 A0 B0 K0 K0 C0 D0 1 A1 B1 K0 K1 NaN NaN 2 A2 B2 K1 K0 C1 D1 3 A2 B2 K1 K0 C2 D2 4 A3 B3 K2 K1 NaN NaN 5 NaN NaN K2 K0 C3 D3
4 交叉表和透明表
4.1 交叉表
用于探寻两列之间的关系,例如,探究股票的涨跌与星期几有关
stock = pd.read_csv('./data/stock_day/stock_day.csv') # 加载股票数据 date = pd.to_datetime(stock.index).weekday # 把索引(日期)变成日期,再转换为weekday stock['week'] = date # 2、把p_change按照大小分类,以0为界限 stock['posi_neg'] = np.where(stock['p_change'] > 0, 1, 0) # 通过交叉表找寻两列数据的关系 count = pd.crosstab(stock['week'], stock['posi_neg']) count posi_neg 0 1 week 0 63 62 1 55 76 2 61 71 3 63 65 4 59 68
但是我们看到count只是每个星期日子的好坏天数,并没有得到比例,该怎么去做?
对于每个星期一等的总天数求和,运用除法运算求出比例
# 算数运算,先求和 count.sum(axis=1).astype(np.float32) # 进行相除操作,得出比例 pro = count.div(count.sum(axis=1).astype(np.float32), axis=0) pro posi_neg 0 1 week 0 0.504000 0.496000 1 0.419847 0.580153 2 0.462121 0.537879 3 0.492188 0.507812 4 0.464567 0.535433
import matplotlib.pyplot as plt pro.plot(kind='bar', stacked=True) plt.show()
4.2 使用pivot_table(透视表)实现
透视表和作用和交叉表一样,实现起来更加简单
# 通过透视表,将整个过程变成更简单一些 # 参数一是分析的列,index参数是相关分析的列 stock.pivot_table(['posi_neg'], index=['week']) posi_neg week 0 0.496000 1 0.580153 2 0.537879 3 0.507812 4 0.535433
5 分组和聚合
分组与聚合通常是分析数据的一种方式,通常与一些统计函数一起使用,查看数据的分组情况
5.1 什么是分组和聚合
5.2 实际操作
DataFrame.groupby(key, as_index=False)
key:分组的列数据,可以多个
as_index:分组的列在显示结果的时候是否作为索引 默认是使用分组的列作为索引
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 color object price1 price2 0 white pen 5.56 4.75 1 red pencil 4.20 4.12 2 green pencil 1.30 1.60 3 red ashtray 0.56 0.75 4 green pen 2.75 3.15
进行分组,对颜色分组聚合后计算price1的平均值
col.groupby(['color'])['price1'].mean() color green 2.025 red 2.380 white 5.560 Name: price1, dtype: float64
# 分组,数据的结构不变 col.groupby(['color'], as_index=False)['price1'].mean() color price1 0 green 2.025 1 red 2.380 2 white 5.560阅读更多
- 数据挖掘 pandas基础入门之操作
- Python 数据分析:pandas 操作基础篇
- 利用Python进行数据分析(15) pandas基础: 字符串操作
- python数据分析入门(一)----安装pandas
- 利用Python数据分析:pandas入门(六)
- 利用Python数据分析:pandas入门(一)
- Python数据分析——Pandas数据结构和操作
- 用python做数据分析4|pandas库介绍之DataFrame基本操作
- Python数据挖掘入门与实践(四)——亲和性分析
- python数据分析:pandas数据结构与操作
- Pandas数据分析工具快速进阶四(字符串操作技巧)
- 数据分析、数据挖掘、机器学习、神经网络、深度学习和人工智能概念区别(入门级别)
- python数据挖掘入门与实战——学习笔记(第1、2章)
- 利用Python进行数据分析(15) pandas基础: 字符串操作
- 利用Python进行数据分析_python3实现_pandas入门_相关系数与协方差
- Python和R数据挖掘分析技术高级公开课在上海举行
- python数据挖掘课程 十一.Pandas、Matplotlib结合SQL语句可视化分析
- 利用Python数据分析:pandas入门(二)
- #######用python做数据分析4|pandas库介绍之DataFrame基本操作#######
- 数据分析之Pandas(一):Series、DataFrame基本操作及索引对象