【pandas数据可视化超全笔记整理】Numpy Pandas | 常用API介绍 | 缺失值处理 matplotlib数据可视化介绍

时间:2024-10-01 20:34:35

文章目录

  • Numpy 部分
    • NumPy的数组类被称作ndarray,通常被称作数组。
      • 属性
      • 创建方法
      • 内置函数
      • 运算
        • 基本运算
        • 矩阵运算
  • Pandas部分
    • 总述
    • Serise 对象
      • 创建
      • 属性
      • 方法
      • 运算
    • DataFrame
        • 属性
        • 索引操作
        • 添加删除插入列
      • 保存读取文件
        • 保存
        • 读取
      • 数据加载
      • 分组聚合
        • 语法格式:
      • 基本绘图
  • 数据组合和缺失值处理
    • 数据组合
      • Dataframe 数据组合 concat连接
          • df对象和df对象拼接
          • df对象和series对象拼接
      • DataFrame 数据组合 添加 行和列
          • 添加行
          • 添加列
          • 一对一合并
      • join 方式
    • 缺失值
        • 加载缺失值
        • 缺失值可视化
        • 缺失值处理和非时序数据缺失值填充
          • 删除缺失值
          • 非时序数据填充
          • 时序数据填充
        • series 中的apply方法
        • DataFrame 中的apply方法
  • 向量化函数
  • 分组聚合
    • 分组转换
    • 分组过滤
    • DataFrameGroupby对象
  • 日期类型处理
    • Pandas日期时间类型简介
    • 日期时间类型相关操作
  • 生成规则如下:
  • Matplotlib 数据可视化
    • Matplotlib的API介绍

Numpy 部分

NumPy的数组类被称作ndarray,通常被称作数组。

属性

ndim 维度(几轴)
shape 形状
dtype 数据类型
size 大小(元素个数)
type 数组类型

创建方法

zeros() 创建一个全是0的数组
ones() 创建一个全是1的数组
empty() 创建一个内容随机并依赖于内存状态的数组

arange() 创建一个一维的ndarray数组
matrix() 生成一个二维矩阵

logspace(参1,参2,参3) 等比数列 参1 : 起始点 参2: 结束点 参3: 步长
linspace(参1,参2,参3) 等差数列 参1 : 起始点 参2: 结束点 参3: 步长

内置函数

  • 基本函数
ceil() 天花板数 向上取整
floor() 地板数 向下取整
rint() 四舍五入 
isnan() 判断是否为空(NAN)
multiply() 元素相乘
divide() 元素相除
abs() 绝对值
where(condition , x, y) 三元运算符 x if condition else y
  • 统计函数
mean() 平均值
sum() 和
max() 最大值
min() 最小值
std() 标准差
var() 方差
argmax() argmin() 最大值 最小值 的下标索引值
cumsum() 累加和
cumprod() 累乘积
  • 比较函数
any() 一个元素满足 返回True
all() 所有元素满足 返回 True
  • 去重函数
unique() 找到唯一值并返回排序结果
  • 排序函数
sort()
np.sort() 返回排序后的副本
ndarray对象.sort() 直接对 ndarray对象排序

运算

基本运算

两个ndarray, 一个是arr_a 另一个是arr_b

它们俩之间进行 arr_a + arr_b 或 arr_a - arr_b 或 arr_a * arr_b 这样计算的前提是 shape相同

计算的时候, 位置对应的元素 进行 加减乘除的计算, 计算之后得到的结果的shape 跟arr_a /arr_b 一样

数组a [20 30 40 50]
数组b [0 1 2 3]
a-b [20 29 38 49]
矩阵运算

​ 前提是 a的行数 = b的列数 b的行数 = a的列数

a的第几行 * b 的第几列 元素相加 填入对应的结果集中

Pandas部分

总述

pandas存储时没有行只有列 每列为一个Series对象 多个Series对象组成一个DataFrame

请添加图片描述

  • DataFrame 可以看作由Series 对象 组成的字典 key是列名 值是Series
  • Serise 与 列表非常相似 存储一列信息

Serise 对象

创建

创建方式 pandas.Series(值,参数)
指定索引 参数 index = [值1,值2]
值可以是字典/ndarray/列表/元组等

属性

loc 使用索引值取子集
iloc 使用索引位置取自己
dtype series内容的类型
T 转置矩阵
shape 维度
size 元素数量
values 值
index 索引值

方法

append 连接两个或多个series
corr 计算与另一个series 的相关系数
cov 计算与另一个series 的协方差
describe 计算常见统计量
drop_duplicates 返回去重后的series
equals 判断两个series 是否相同
get_values 获取series 的值 作用与values 属性相同
hist 直方图
isin 判断是否包涵某些值
min max 最小值 最大值
mean 算数平均值
median 中位数
mode 众数
quantile 返回指定位置的分位数
replace 用指定值代替series中的值
sample 返回随机采样值
sort_values 对值进行排序
to_frame series转化为dataframe
unique 去重返回数组
value_counts 统计不同值数量
keys 获取索引值
head tail 查看前五个 后五个值

运算

​ series 计算时 变量会和series中的每个元素逐一计算

​ 两个series 之间计算时 索引值相同的互相计算 不同的位置返回nan

DataFrame

可以通过字典 / 列表+ 元组等方式创建

属性
shape 维度
size 元素个数
values 数据值
ndim 维度数
dtypes 元素类型
index 索引值
columns 列名对象
head tail 前 后 五行数据
info 基本信息
describe 描述信息
len 行数
min max 最小最大
count 非空值个数
mean 平均值
索引操作
set_index() 设置索引列
reset_index() 重置索引列
rename() 修改行索引 列索引名 参数 index 行索引 columns 列索引
添加删除插入列
 df[列名] = 值   可以给df对象新增一列, 默认: 在df对象的最后添加一列.\
 drop(名称 , axis = 行/列)  删除一行或列 根据 axis 参数 删 rows 0 行 columns 1 列
 也可以drop([行索引1,行索引2]) 按行索引删除
 insert() 表示插入列.   参数解释: loc:插入位置(从索引0开始计数), column=列名, value=值

保存读取文件

保存
to_pickle('路径名')  保存为 pickle文件 
to_csv('路径名')  保存为csv文件
to_excel('路径名') 保存为 excel文件

pandas 读写excel需要额外安装

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xlwt
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openpyxl
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xlrd

读取
read_pickle('路径名')  读取 pickle文件 
read_csv('路径名')  读取csv文件
read_excel('路径名') 读取 excel文件

数据加载

df对象[['列名1', '列名2', '列名3'...]] 按列加载数据
df对象.loc[[行索引],[列名]] 按行加载数据
df对象.loc[:,[列名]] 获取所有行的某些列
df对象.loc[:,3:5]  获取列编号为 3 ~ 5 区间的数据, 包左不包右, 即: 只获取索引为3, 4列的数据.
loc只接收 行列名,  iloc只接收行列序号, 搞反了, 会报错.

分组聚合

​ 先将数据分组 对每组的数据再去进行统计计算如,求平均,求每组数据条目数(频数)等 再将每一组计算的结果合并起来,可以使用DataFrame的groupby方法完成分组/聚合计算

语法格式:
df.groupby('分组字段')['要聚合的字段'].聚合函数()
df.groupby(['分组字段','分组字段2'])[['要聚合的字段','要聚合的字段2']].聚合函数()

基本绘图

df对象.plot()
line 折线图 bar 柱状图 pie 饼图

数据组合和缺失值处理

数据组合

Dataframe 数据组合 concat连接

概述: 连接是指把某行或某列追加到数据中, 数据被分成了多份可以使用连接把数据拼接起来

把计算的结果追加到现有数据集,也可以使用连接

df对象和df对象拼接

行拼接参考: 列名, 列拼接参考: 行号
格式 pandas.concat([df对象1,df对象2,df对象3], axis = 拼接方式)

拼接方式 rows 0 行拼接 columns 1 列拼接

df对象和series对象拼接

由于Series是列数据(没有行索引), concat()默认是添加行, 所以 它们拼接会新增一列. 缺值用NaN填充

请添加图片描述

DataFrame 数据组合 添加 行和列

添加行
通过 concat 和 append 都可实现添加一行
df5 = pd.DataFrame([['n1', 'n2', 'n3', 'n4']], columns=['A', 'B', 'C', 'D'])
pd.concat([df1, df5])
df1.append(df5)
添加列
方式1: 通过 df[列名] = [列值1, 列值2...] 的方式, 可以给 df添加列.
方式2: 通过 df[列名] = Series对象 的方式, 添加1列.      # 值的个数和列的个数, 匹不匹配均可.

DataFrame 数据组合 merge 方式

概述 : 在使用concat连接数据时,涉及到了参数**join(join = ‘inner’,join = ‘outer’)

数据库中可以依据共有数据把两个或者多个数据表组合起来,即join操作

DataFrame 也可以实现类似数据库的join操作

Pandas可以通过pd.join命令组合数据,也可以通过pd.merge命令组合数据

merge更灵活,如果想依据行索引来合并DataFrame可以考虑使用join函数

一对一合并
df对象.merge(df对象子集的 id1,id2, id3)   on表示关联字段, how表示连接方式
how 关联方式 有 
left 左外连接 
right 右外连接
inner 内连接
outer 外连接
  1. on 连接的字段, 如果左右两张表 连接的字段名字相同直接使用 on=‘关联字段名’

  2. 如果名字不同, left_on 写左表字段, right_on 写右表字段.

  3. 连接之后, 两张表中如果有相同名字的字段, 默认会加上后缀 默认值 _x, y

    suffixes:(" x", “_ y”)

join 方式

  • 使用join合并,可以是依据两个DataFrame的行索引,
  • 或者一个DataFrame的行索引另一个DataFrame的列索引进行数据合并
如果合并的两个数据有相同的列名,需要通过lsuffix,和rsuffix,指定合并后的列名的后缀
例:
stocks_2016.join(stocks_2017, lsuffix='_2016', rsuffix='_2017', how='outer') # 默认是: 左外连接.

缺失值

简介

  • 好多数据集都含缺失数据。缺失数据有多重表现形式
    • 数据库中,缺失数据表示为NULL
    • 在某些编程语言中用NA表示
    • 缺失值也可能是空字符串(’’)或数值
    • 在Pandas中使用NaN表示缺失值
  • Pandas中的NaN值来自NumPy库,NumPy中缺失值有几种表示形式:
    • NaN,NAN,nan,他们都一样
    • 缺失值和其它类型的数据不同,它毫无意义,NaN不等于0,也不等于空串
  • 数据中出现缺失值是很常见的
    • 计算的过程中, 两个表join 可能会有缺失
    • 原始的数据中也有可能直接带着缺失值
    • 数据处理和模型训练的时候, 有很多场景要求必须先把缺失值处理掉,
    • 想处理缺失值先要在数据中找到缺失值
# 1. 缺失值不是 True, False, 空字符串, 0等, 它"毫无意义"
print(np.NaN == False)
print(np.NaN == True)
print(np.NaN == 0)
print(np.NaN == '')

# 2. np.nan np.NAN np.NaN 都是缺失值, 这个类型比较特殊, 不同通过 == 方式判断, 只能通过API
print(np.NaN == np.nan)
print(np.NaN == np.NAN)
print(np.nan == np.NAN)

# 3. Pandas 提供了 isnull() / isna()方法, 用于测试某个值是否为缺失值
import pandas as pd

print(pd.isnull(np.NaN))    # True
print(pd.isnull(np.nan))    # True
print(pd.isnull(np.NAN))    # True

print(pd.isna(np.NaN))  # True
print(pd.isna(np.nan))  # True
print(pd.isna(np.NAN))  # True

# isnull() / isna()方法 还可以判断数据.
print(pd.isnull(20))    # False
print(pd.isnull('abc'))    # False

# 4. Pandas的notnull() / notna() 方法可以用于判断某个值是否为缺失值
print(pd.notnull(np.NaN))   # False
print(pd.notnull('abc'))   # True
加载缺失值
在加载数据时
可以通过 keep_default_na 参数 设置 加载数据时候是否加载缺失值
可以通过 na_values=[值1, 值2...]	加载数据时, 设定哪些值为缺失值.
缺失值可视化
# 导包
import missingno as msno
柱状图 展示缺失值的个数
msno.bar(数据对象名)
缺失值处理和非时序数据缺失值填充
删除缺失值
dropna() 函数 参数介绍
subset=None  默认是: 删除有缺失值的行, 可以通过这个参数来指定, 哪些列有缺失值才会被删除
例如: subset = ['Age']  只有当年龄有缺失才会被删除
inplace=False  通用参数, 是否修改原始数据默认False
axis=0 通用参数 按行按列删除 默认行
how='any'  只要有缺失就会删除 还可以传入'all' 全部都是缺失值才会被删除
非时序数据填充
用 0 来填充 空值.
数据对象名.fillna(0) 
用平均数, 来替换 某列的空值.
数据对象名[列名].fillna(数据对象名[列名].mean())
时序数据填充
加载数据时
可以通过 设置 prase_dates 把某些列转成时间列
index_col 设置指定列为索引列
填充方式 1 固定值填充
数据对象名.dillna(填充数据)
2. ffill 填充 用时间序列空值的上一个非空值填充
数据对象名.fillna(method = 'ffill')
3. bfill 填充 用时间序列空值的下一个非空值填充
数据对象名.fillna(method = 'bfill')
4. 线性插值方法填充缺失值
数据对象名.interpolate(limit_direction = 'both')

缺失值处理的套路

  • 能不删就不删 , 如果某列数据, 有大量的缺失值(50% 以上是缺失值, 具体情况具体分析)
  • 如果是类别型的, 可以考虑使用 ‘缺失’ 来进行填充
  • 如果是数值型 可以用一些统计量 (均值/中位数/众数) 或者业务的默认值来填充
series 中的apply方法

apply函数可以接收一个自定义函数, 可以将DataFrame的行/列数据传递给自定义函数处理

import pandas as pd

# 1. 准备数据
df = pd.DataFrame({'a': [10, 20, 30], 'b': [20, 30, 40]})
df


# 2. 创建1个自定义函数.
def my_func(x):
    # 求平方
    return x ** 2


def my_func2(x, e):
    # 求x的e次方 
    return x ** e


# 3. apply方法有一个func参数, 把传入的函数应用于Series的每个元素
# 注意, 把 my_func 传递给apply的时候,不要加上小括号.
df['a'].apply(my_func)          # 传入函数对象.
df['a'].apply(my_func2, e = 2)  # 传入函数对象, e次幂(这里是平方)
df['a'].apply(my_func2, e = 3)  # 传入函数对象, e次幂(这里是立方)
DataFrame 中的apply方法

格式

df.apply(func,axis = )
axis = 0 按列传递数据 传入一列数据(Series)
axis = 1 按行传递数据 传入一列数据(Series)

代码演示

# 1. 把上面创建的 my_func, 直接应用到整个DataFrame中
df.apply(my_func)   # my_func函数会作用到 df对象的每一个值.

# 2. 报错, df对象是直接传入一列数据的, 并不是 一个值一个值传入的
def avg_3(x, y, z):
    return (x + y + z) / 3
df.apply(avg_3)


# 3. 演示 df对象, 到底传入啥.
def my_func3(x):
    print(x)
    print(f'x的数据类型是: {type(x)}')

# 每次传入 1 列    
# df.apply(my_func3, axis=0)  # 0(默认): 列,  1: 行
# 每次传入 1 行    
df.apply(my_func3, axis=1)  # 0(默认): 列,  1: 行

向量化函数

  • 分析代码

    def avg_test2(x,y):
        if x==20:
            return np.NaN
        else:
            return (x+y)/2
    avg_test2(df['a'],df['b'])
    
  • 报错原因

    • 上面的方法调用之所以报错, 就是因为if 需要传入的是 一个True/False .
    • 但是我们传入的是一个 True/False 组成的Series 此时if 不能做出判断, 抛出了错误
    • 想让上面的代码正常的执行, 我们需要把 Series里的每一个值遍历的传递给if 做多次判断,
    • 此时必须要自己写for循环, 可以通过 np.vectorize(avg_test2) 这种方式,
    • 把这个方法变成一个向量化的方法(会遍历每一个值(分量)多次调用这个方法)

格式

@  np.vectorize
或者 
 np.vectorize(函数名)

Lambda 表达式

  • 背景

    • 当函数比较简单的时候, 没有必要创建一个def 一个函数, 可以使用lambda表达式创建匿名函数
  • 格式

    lambda 形参列表 : 函数体
    
  • 代码演示

    df.apply(lambda x: x + 1)
    df.apply(lambda x: x.isnull().sum())
    df.apply(lambda x: x.mean())
    

分组聚合

概述

  • 在SQL中我们经常使用 GROUP BY 将某个字段,按不同的取值进行分组,
  • 在pandas中也有groupby函数, 分组之后,每组都会有至少1条数据, 将这些数据进一步处理,
  • 返回单个值的过程就是聚合,比如分组之后计算算术平均值, 或者分组之后计算频数,都属于聚合
例如
df.groupby('year').lifeExp.mean()
df[df['year'] == 1952]['lifeExp'].mean()
df[df.year == 1952].lifeExp.mean()  # 效果同上

分组转换

概述

  • transform 需要把DataFrame中的值传递给一个函数, 而后由该函数"转换"数据。
  • 即: aggregate(聚合) 返回单个聚合值,但transform 不会减少数据量
# 需求1: 计算z-score(也叫: z分数, 标准分数), 即: (x - 平均值) / 标准差
def my_zscore(x):
    # (每一组的值 - 当前组的平均值) / 当前组的标准差
    return (x-x.mean())/x.std()

# 按年分组 计算z-score
df.groupby('year').lifeExp.transform(my_zscore)

# 查看数据集条目数, 跟之前transform处理之后的条目数一样
df.shape    # 1704行, 6列

分组过滤

概述

  • 使用groupby方法还可以过滤数据
  • 调用filter 方法,传入一个返回布尔值的函数,返回False的数据会被过滤掉
# 需求: 根据就餐人数进行分组, 过滤掉条目数少于30条的组
# 1. 使用小费数据
tips = pd.read_csv('data/tips.csv')

# 2. 查看用餐人数
tips['size'].value_counts()

# 3. 人数为1、5和6人的数据比较少,考虑将这部分数据过滤掉
tips_filtered = tips.groupby('size').filter(lambda x: x['size'].count() > 30)

# 4. 查看结果
tips_filtered['size'].value_counts()

# 5. 合并版写法
tips.groupby('size').filter(lambda x: x['size'].count() > 30)['size'].value_counts()

DataFrameGroupby对象

概述

  • 调用了groupby方法之后, 就会返回一个DataFrameGroupby对象
  • python 中 是datetime pandas 中 是 Datetime64 和 Timestamp 时间戳类型

日期类型处理

Pandas日期时间类型简介

概述

  • 和其它语言类似, Python内置了datetime对象,可以在datetime库中找到
  • pandas的日期时间类型默认是 datetime64[ns]

日期时间类型相关操作

时间类型对象.year 获取年
时间类型对象.month 获取月
时间类型对象.day 获取日
时间类型对象.dayofyear 获取年中第几天

读取数据时 可以通过 parse_dates = [列的编号 列名] 来设置时间类型
可以通过 pd.date_range(开始时间,结束时间,freq = '生成规则')来生成指定区间的日期序列

生成规则如下:

请添加图片描述

Matplotlib 数据可视化

Matplotlib的API介绍

Matplotlib提供了两种方法来作图:**状态接口和面向对象

导包方式
# Matplotlib.pyplot 包含一系列绘图函数的相关函数
import matplotlib.pyplot as plt
创建画布方法
plt.figure() 参数 figsize 画布大小 

方式1 : 状态接口

# 1. 准备x轴 和 y轴的数据.
x = [-3, 5, 7]  # x轴坐标
y = [10, 2, 5]  # y轴坐标
# 2. 创建画布, figure: 创建画布, figsize=指定画布大小
plt.figure(figsize=(15, 6)) 
# 3. 绘图, 传入x轴, y轴
plt.plot(x, y)
plt.grid(True)  # 添加网格线
# 4. 设置x轴坐标 和 y轴坐标的范围
plt.xlim(0, 10)
plt.ylim(-3, 8)
# 5. 设置x轴 和 y轴的标签
plt.xlabel('X Axis', size=20)
plt.ylabel('Y Axis', size=10)
# 6. 设置标题.
plt.title('Line Plot', size=30)
# 7. 显示图片
plt.show()

方式2 面向对象

# 面向对象 绘图.
import matplotlib.pyplot as plt

# 1. 准备x轴 和 y轴的数据.
x = [-3, 5, 7]  # x轴坐标
y = [10, 2, 5]  # y轴坐标
# 2. 创建画布, 坐标轴对象
fig, ax = plt.subplots(figsize=(15, 6)) 
# 3. 绘图, 传入x轴, y轴
ax.plot(x, y)
ax.grid(True)  # 添加网格线
# 4. 设置x轴坐标 和 y轴坐标的范围
ax.set_xlim(0, 10)
ax.set_ylim(-3, 8)
# 5. 设置x轴 和 y轴的标签
ax.set_xlabel('X Axis', size=20)
ax.set_ylabel('Y Axis', size=10)
# 6. 设置标题.
ax.set_title('Line Plot', size=30)
# 7. 显示图片
plt.show()