您的位置:首页 > 其它

数据分析与挖掘入门——学习笔记(九)Pandas高级操作

2018-09-17 15:59 387 查看

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
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: