IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 机器学习入门 05 —— Pandas使用 -> 正文阅读

[Python知识库]机器学习入门 05 —— Pandas使用


系列文章

机器学习入门 01 —— 机器学习概述
机器学习入门 02 —— 环境搭建(Jupyter Notebook 及扩展库的安装与使用)
机器学习入门 03 —— Matplotlib使用
机器学习入门 04 —— Numpy使用
机器学习入门 05 —— Pandas使用


5 Pandas

学习目标:

  • 了解Numpy与Pandas的不同

  • 说明Pandas的Series与Dataframe两种结构的区别

  • 了解Pandas的MultiIndex结构

  • 应用Pandas实现基本数据操作

  • 应用Pandas实现数据的合并

  • 应用crosstab和pivot_table实现交叉表与透视表

  • 应用groupby和聚合函数实现数据的分组与聚合

  • 了解Pandas的plot画图功能

  • 应用Pandas实现数据的读取和存储

5.1 Pandas介绍

?

pandas
  • 是专门用于数据挖掘的开源Python库
  • 以Numpy为基础,利用了Numpy模块在计算方面高性能的优势
  • 基于Matplotlib,能够简便快速地画图
  • 有着独特的数据结构

有了numpy和matplotlib,为什么还要使用Pandas?

  • 读取文件方便

  • 封装了Matplotlib和Numpy的画图与计算

  • Pandas可以增强图表可读性:左边是原生的数据显示,右边是用Pandas的显示。

image-20210729194933075
  • 便捷的数据处理能力:Pandas可以显示的数据长度更长

    数据处理能力

?

5.2 Pandas数据结构

Pandas中有三种数据结构:

  • Series:对应一维数组
  • DataFrame:对应二维数组
  • MultiIndex(Panel):对应三维数组

?

1 Series

Series是类似于一维数组的数据结构,它能存储任何类型的数据。Series由索引和数据构成。

?

创建Series

import pandas as pd
pd.Series(data=None, index=None, dtype=None)
data:传入的数据,可以是ndarry、列表、字典、元祖等。
index:索引,要求是唯一值,且数量和data一一对应。如果没有传入索引,则默认从0开始。如果data是字典,索引就是key。
dtype:数据类型。
效果

?

Series属性

属性

?

2 DataFrame

DataFrame类似于二维数组,它就像一个表格,所以既有行索引又有列索引。

?

创建DataFrame

import pandas as pd
pd.DataFrame(data=None, index=None, columns=None)

index:行标签。如果没有传入,则默认创建0-N作为索引。
columns:列标签。如果没有传入,则默认创建0-N作为索引。
DataFrame

?

DataFrame属性

索引

?

重置索引

reset_index(drop=False)设置新的下标索引(0-N)。drop如果为True表示要删除原来的索引值。

重置索引

?

设置某列值为新索引

set_index(keys, drop=True)设置keys为新索引,drop默认为True,删除原索引。

se

上面把年份和月份都设置为索引,这其实就是一个MultiIndex(多重索引)

?

3 MultiIndex

MultiIndex是三维的数据结构,多重索引,其实就是在Series、DataFrame对象上拥有两个或两个以上的索引的结构。

我们打印下刚刚的年月份的索引:

创建MultiIndex

创建

?

5.3 基本数据操作

为了更好的理解这些基本操作,这里的例子会先读取一个真实的文件数据。(关于文件操作后面会介绍,这里看看就行)

# 读取文件(csv文件其实就是Excel)
data = pd.read_csv('./stock_day.csv')

# 删除一些列,让数据更简单,再进行后面操作
data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"], axis=1)

data.head(3)
文件

?

1 索引操作

直接操作

要特别注意,Pandas直接操作索引是先列后行,和列表、Numpy的先行后列不同!!

# 直接使用列行操作(注意,是先列后行且不能切片。这和列表、Numpy的先行后列不同)
data['open']['2018-02-27'] # 获取到 23.53

# 下面的用法是错误的
data['2018-02-27']['open'] # 不能先行后列

data[:1][:2] # 不能使用切片

loc和iloc

# 使用loc就是先行后列,还可以使用切片(注意,不能用[][],只能[: , :])
data.loc['2018-02-27':'2018-02-23','open':'close']
loc
# 使用iloc也是先行后列,但用的是索引下标而不是索引值
data.iloc[:4, :3]
iloc
# loc和iloc混合使用(原理上还是一样的)
# 第一个参数实质上还是传递索引值
data.loc[data.index[0:4], ['open', 'close', 'high', 'low']] 
# 第二个参数实质上还是传递索引下标
data.iloc[0:4, data.columns.get_indexer(['open', 'close', 'high', 'low'])]

?

2 赋值操作

# 把'close'列全部赋值为1
data.close = 1 # 或者 data['close'] = 1

# 把'close'列 '2018-02-27'行 赋值为2
data.loc['2018-02-27', 'close'] = 2

# 把第4列大于23的赋值为0
data[data.iloc[:,3]>22]=0

data.head(3)
赋值

?

3 排序

Series和DataFrame都可以进行排序,根据索引排序,也可以根据值排序。

DataFrame排序

  • sort_values(by=keys,ascending=True):根据值排序。by是排序参考的键(可以多个),ascending为True是升序(默认)。
  • sort_index(ascending=True):根据索引排序。升序。
# 根据值排序,返回一个新对象,不会改变原来对象; 根据'open'列,升序;
data.sort_values('open', ascending=True).head(3)

# 根据'open'列和'high'列,降序;(如果open相同才比较high)
data.sort_values(['open','high'], ascending=False).head(3)

# 根据索引 从小到大
data.sort_index().head(3)

Series排序

由于Series只有一列,所以不需要传入参数,要么根据值排序要么根据索引排序。

  • sort_values(ascending=True):根据值排序。ascending=True升序(默认)。
  • sort_index(ascending=True):根据索引排序。
# 将DataFrame中某一列取出来就是Series
# 利用Series的值排序 升序
data['open'].sort_values(ascending=True).head(3)

# 利用Series的索引 降序
data['open'].sort_index(ascending=False).head(3)

?

5.4 运算

1 算数运算

# 加法 'open'列每个元素+10
data['open'].add(10) # 等价于 data['open']+10

# 减法 'open'
data['open'].sub(10)

# 乘法
data['open'].mul(10)

# 除法
data['open'].div(10)

?

2 逻辑运算

# 筛选 'open' > 23的数据
a = data['open'] > 23 # 每一行 会返回True或False
data[a] # 获取 'open' > 23的数据

# 多个逻辑运算符
data[(data['open'] > 23) & (data['open'] < 24) ]

# 使用逻辑运算符函数 query(表达式)
data.query('open > 23 & open < 24')

# 判断 ‘open'列 有某个元素
b = data['open'].isin([23.53, 23.85]) # 会对每行的'open'进行判断,返回True或False
data[b] # 获取'open'是23.53 或者 23.85的数据

?

3 统计运算

下面的函数可以对Series和DataFrame操作。对于DataFrame的统计函数,都有参数axisaxis=0表示对列进行统计(默认),axis=1表示对行进行统计。

统计函数描述
sum()求和
mean()平均值
median()中位数(是从小到大的中间一位数字)
min()最小值
max()最大值
mode()众数(出现次数最多的)
abs()绝对值
prod()标准差
std()标准差
var()方差
idxmax()最大值的索引
idxmin()最小值的索引
cumsum()对某一列累计求和
cummax()对某一列累计求最大值
cummin()对某一列累计求最小值
cumprod()对某一列累计求积

?

4 自定义运算

可以自己定义函数进行运算

'''
apply(function, axis=0)
function:自定义的函数;axis:0 对列,1对行。
'''

def function(x):
    return x.max() - x.min()

# 举例 下面定义一个队列 求最大值与最小值的差值
# 等价于 data[['open', 'close']].apply(function)
data[['open', 'close']].apply(lambda x: x.max() - x.min())

?

5.5 画图

Pandas中封装了Matplotlib的画图,所以用法大致相同。在Pandas中使用画图函数plot,同时,需要先导入Matplotlib。

无论是DataFrame还是Series都是使用plot()画图。

DataFrame.plot(kind='line')

  • kind=‘line’,表示要画折线图(默认)
  • kind=‘bar’,柱状图,加上参数stacked=True就是堆积柱状图
  • kind=‘barh’,水平方向柱状图
  • kind=‘hist’,直方图
  • kind=‘pie’,饼图
  • kind=‘scatter’,散点图

下面举个简单例子:

import matplotlib.pyplot as pltimport pandas as pd# 读取文件data = pd.read_csv('./Pandas测试数据.csv')# 删除一些列,让数据更简单,再进行后面操作data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"], axis=1)# 排序data = data.sort_index()data = data['p_change'].cumsum()data.plot()plt.show() # 之所以要导入matplotlib,是因为show()后才能显示
结果

?

5.6 文件读取与存储

我们的数据大部分都存储在文件中,而Pandas支持多种文件操作,例如CSV、HDF5、JSON、SQL、XLS等。

最常用的是HDF5和CSV。优先选择HDF5:

  • HDF5在存储的时候支持压缩,使用的方式是blosc,这个是速度最快的也是pandas默认支持的
  • 使用压缩可以提磁盘利用率,节省空间
  • HDF5还是跨平台的,可以轻松迁移到hadoop 上面

下面这张表是常用API

常用API

?

1 CSV

'''
读取CSV
pandas.read_csv(filepath_or_buffer, sep=',', usecols)
filepath_or_buffer:文件路径
sep:分隔符,默认用,
usecols:指定读取的列名(用列表类型)
''' 
data = pd.read_csv('./Pandas测试数据.csv', usecols=['open', 'close'])


'''
写入csv
DataFrame.to_csv(path_or_buf=None, sep=',', columns=None, header=True, index=True, mode='w', encoding=None)
path_of_buf:文件路径
sep:分隔符
columns:要写入的列索引
header:是否写入【列索引】
index:是否写入【行索引】
mode: 'w'重写,'a'追加
encoding:编码格式
'''
# 通常我们写入文件时,会把行索引也写入进去,行索引会变成一列数据,所以我们可以用index=False不写入行索引
data[:10].to_csv('test.csv', columns=['open'],index=False)

?

2 HDF5

'''
写入HDF5
DataFrame.to_hdf(path_or_buf, key)
path_or_buffer:文件路径
key:读取的键(HDF5的读取和存储都要指定一个key)
'''
data.to_hdf('hdf5_data.hdf', 'HDF5_DATA')


'''
读取HDF5(读取需要导入tables模块)
pandas.read_hdf(path_or_buf, key=None)
path_or_buffer:文件路径
key:读取的键(HDF5的读取和存储都要指定一个key)
'''
data = pd.read_hdf('hdf5_data.hdf','HDF5_DATA')

?

3 JSON

JSON存储形式有几种:

  • ‘split’:将索引、列名、数据三种分开。形如{index -> [index], columns -> [columns], data -> [values]}
  • ’records’:形如columns:values,通常用这种。
  • ‘index’:形如index:{columns:values}...
  • ’columns’:形如columns:{index:values}
  • ‘values’:直接输出值
'''
JSON的存储
DataFrame.to_json(path_or_buf=None, orient=None, lines=False)
path_or_buf:文件路径
orient:存储JSON的形式 【'split'、'records','index','colummns','values'】
lines:一个对象存储一行(建议设置为True)
'''
data.to_json('jsondata.json', orient='records')

'''
pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False)
typ : default ‘frame’, 指定转换成的对象类型series或者dataframe
'''
pd.read_json('jsondata.json',orient='records')

?

5.7 缺失值处理

我们获取到的数据不一定都是完整的,可能某个数据有缺失,所以我们需要先对错误数据进行处理。

  • 缺失的表现形式可能是NaN或者?之类的,需要我们先查看数据进行判断。
  • 如果缺失值的标记方式是NaN
    • 用来判断NaN的函数:pd.isnull(DataFrame)pd.notnull(DataFrame)
    • 存在缺失值:
      • 如果缺失值数量少,则删除。数量多,则替换。
      • 删除缺失值(不会改变原表,只返回新表):dropna(axis='rows)'
      • 替换缺失值:fillna(value, inplace=True),其中value替换的值,inplace=True会修改原表。
  • 如果缺失值不是NaN而是?之类的
    • 先将?替换为NaN(),再按上述方式处理。

下面进行举例说明:

  1. 判断缺失值是否存在
判断缺失值是否存在
  1. 删除缺失值NaN
删除缺失值
  1. 替换缺失值NaN
替换缺失值
  1. 对于非NaN的缺失值,例如?这是下面的链接
处理非NaN

?

5.8 数据离散化

1 数据离散化介绍

为什么要数据离散化

连续数据离散化是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具。

?

什么是数据离散化

就是在连续数据的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值。下面举个栗子:

  • 原始人的身高数据:165,174,160,180,159,163,192,184
  • 假设按照身高分几个区间段:150~165, 165~180, 180~195
  • 我们将数据分到了三个区间段,每个数据可以对应到矮、中、高三个类别的区间,最终要处理成一个"哑变量"矩阵(后面有解释)

?

One-Hot编码

在很多学习任务中,特征并不总是连续值,而有可能是分类值。

离散特征的编码分为两种情况:

1、离散特征的取值之间没有大小的意义,比如color:[red,blue],那么就使用one-hot编码

2、离散特征的取值有大小的意义,比如size:[X,XL,XXL],那么就使用数值的映射{X:1,XL:2,XXL:3}

One-Hot编码又称为独热编码(或哑变量 dummy variable),我们把数据离散化后的每个类别区间转为布尔列,这些列中只有一个可以为True(1)。例如下面这种表格,把【Human、Penguin、Octopus、Alien】分为了四个布尔列。

one-hot编码

?

2 API介绍

  • pd.qcut(data, q):返回Series。对数据进行分组(区间是自动分配的),q是分组个数。通常会再搭配value_counts()用来统计每组里数据个数。
  • pd.cut(data, bins):返回Series。也是对数据分组,但区间由自己指定。bins是分组区间。
  • pd.get_dummines(data, prefix=None):data是Series或者DataFrame,prefix是分组的名称。

下面举例:

# 读取CSV数据(某日股票数据)
data = pd.read_csv('stock_day.csv')
p_change = data['p_change']
qcut = pd.qcut(p_change, 10) # 将p_change分10组
qcut.value_counts() # 查看每组的数据个数
结果1

?

bins = [-100, -7, -5, -3, 0, 3, 5, 7, 100]
cut = pd.cut(p_change, bins) # 将p_change按bins分组
cut.value_counts() # 查看每组的数据个数
结果2

?

# 查看热编码
pd.get_dummies(cut).head()
结果3

?

5.9 表格合并

有时候我们会想讲多张表格合并在一起,就需要用到pd.concat()或者pd.merge()

  • pd.concat([data1, data2], axis=1),第一个参数是表格数据的列表,第二个参数为1则按行索引合并,为0则按列索引合并。
# 将刚刚的One-Hot编码与原数据合并
data = pd.read_csv('stock_day.csv')
bins = [-100, -7, -5, -3, 0, 3, 5, 7, 100]
cut = pd.cut(p_change, bins)
dummies = pd.get_dummies(cut, prefix='rise')

pd.concat([data, dummies], axis=1) # 按行索引
效果
  • pd.merge(left, right, how='inner', on=None)
    • 可以指定安装两组数据的共同键值对合并或按照左右各自合并。
    • left:左表(DataFrame)
    • right:右表(DataFrame)
    • on:指定共同的键(如果不指定就是左右表各自合并)
    • how:按什么方式连接(和数据库的表连接类似,inner、left、right、outer)
left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3'],
                     'key1': ['K0', 'K0', 'K1', 'K2'], 
                     'key2': ['K0', 'K1', 'K0', 'K1']}) 
right = pd.DataFrame({'C': ['C0', 'C1', 'C2', 'C3'],
                      'D': ['D0', 'D1', 'D2', 'D3'],
                      'key1': ['K0', 'K1', 'K1', 'K2'], 
                      'key2': ['K0', 'K0', 'K0', 'K0']}) 

内连接:

# 默认用内连接 inner,使用两个表共同键作为连接点
pd.merge(left, right) # 可以不指定on=['key1', 'key2']
内连接

左连接:

# 左连接 
pd.merge(left, right, how='left', on=['key1', 'key2'])
左连接

右连接:

# 右连接 
pd.merge(left, right, how='right', on=['key1', 'key2'])
右连接

外连接:

# 外连接
pd.merge(left, right, how='outer', on=['key1', 'key2'])
外连接

?

5.10 交叉表与透视表

交叉表:用于统计两列数据之间的关系。

透视表:是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数【pd.crosstab(列1,列2)

下面用案例进行说明:探究股票涨跌与星期之间的关系(交叉表)。【data.pivot_table([列1..], 索引)

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 读取股票数据 (索引是 '2018-02-27')
data = pd.read_csv('stock_day.csv')

# 将行索引转换为datatime类型,再将日期转换为对应的星期几。
week = pd.to_datetime(data.index).weekday

# 增加一个新列 星期
data['week'] = week

# 判断涨跌 p_change列,大于0则置为1(涨),小于0则置为0(跌)。并将结果作为新列p_n
data['p_n'] = np.where(data['p_change'] > 0, 1, 0)

# 交叉表:此时得到的是 0 和 1 的统计数量。(即涨跌)———— 看图1
count = pd.crosstab(data['week'], data['p_n'])

# 现在将上面的表转为百分比[例如 63/(63+62)] ———— 看图2
img = count.div(count.sum(axis=1).astype(np.float32), axis=0)

# 绘图 ———— 看图3
img.plot(kind='bar', stacked=True)
plt.show()

图1:

图1

图2:

图2

图3:

图3

从上面可看出,交叉表是统计出两列的数量关系,而透视表是直接得出百分比关系。

data.pivot_table(['p_n'], 'week')
透视表

?

5.11 分组与聚合

分组与聚合通常是分析数据的一种方式,通常与一些统计函数一起使用,查看数据的分组情况。其实刚才的交叉表与透视表也有分组的功能,所以算是分组的一种形式,只不过他们主要是计算次数或者计算比例。下面这张图就非常形象。

分组与聚合

聚合的内置函数:sum(), mean(), max(), min(), count(), size(), describe()

下面用代码演示:

演示

星巴克案例:

# 读取数据 (数据来自Kaggle)
starbucks = pd.read_csv("directory.csv")

# 按国家分组,并求出每个国家星巴克零售店的数量
count = starbucks.groupby(['Country']).count()

# 绘图显示
count['Brand'].pl ot(kind='bar', figsize=(20, 8))
plt.show()

# 对国家和省份进行分组
starbucks.groupby(['Country', 'State/Province']).count().head()
案例

?

5.12 练习案例-电影分析

现在对2006年至2016年1000部流行电影进行分析:

  • 获取电影评分的平均分和导演人数
  • 获取电影评分和时长的分布情况
  • 获取电影分类情况

先导包并读取电影数据。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

movie = pd.read_csv('IMDB-Movie-Data.csv')
movie.head(3)

image-20210808222748145

?

1 获取电影评分的平均分和导演人数

# 平均分
movie['Rating'].mean()

# 导演人数
movie['Director'].unique().shape[0] # 方法一  unique()是去除重复元素
np.unique(movie['Director']).shape[0] # 方法二
问题1

?

2 获取电影评分和时长的分布情况

如果使用Pandas直接绘制直方图,会出现坐标无法对齐的问题,所以还是要使用Matplotlib。

# 如果使用Pandas绘制直方图,会出现坐标无法对齐的问题
movie['Rating'].plot(kind='hist', figsize=(14, 6))
问题2

?

# 1. 创建画布
plt.figure(figsize=(20,8),dpi=80) 

# 2. 绘制图像
plt.hist(movie["Rating"].values,bins=20) # 分为20组(即间隔)

# 2.1 创建刻度表(否则还是会有无法对齐的问题)
max_rating = movie['Rating'].max()
min_rating = movie['Rating'].min()
x_tick = np.linspace(min_rating, max_rating, num=21) # 均分为21个数字,中间就有20个间隔
plt.xticks(x_tick)

# 2.2 添加网格
plt.grid()

# 3. 显示图像
plt.show()
问题2

?

3 获取电影分类情况

思路:

  • 创建一个全为0的表(即DataFrame),表的索引就是电影类别(要去重)
  • 然后遍历所有电影,由于每部电影可能有多个类别,所以在遍历一部电影时,根据其类别使其列值加1
  • 对每一列求和,这样就得到每个类别的电影总数
# 1. 先判断总共有哪些电影类别,要去重。每部电影的多个类别用 , 分割
temp_list = [i.split(',') for i in movie['Genre']] # 将每部电影的类别分割,并放入列表。

genre_list = np.unique([i for j in temp_list for i in j]) # 获取到总的电影类别列表。

# 2. 以电影类别作为列索引,创建全为0的DataFrame
temp_df = pd.DataFrame(np.zeros([movie.shape[0], genre_list.shape[0]]), columns=genre_list)

# 3. 遍历每部电影,并根据每部电影的类别 使其对于列加1
for i in range(movie.shape[0]):
    # 其中 temp_list[0] = ['Action', 'Adventure', 'Sci-Fi']
    # 所以这行代码是让每部电影对应类别的列值 +1
    temp_df.loc[i, temp_list[i]] = 1

# 4. 每列求和并从小到大排序
result = temp_df.sum().sort_values()

# 5. 绘图
result.plot(kind='bar', figsize=(15, 6), fontsize=20, colormap='cool')
问题3
  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:12:00  更:2021-08-09 10:12:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 1:47:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计