栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

pandas 进阶

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

pandas 进阶

目录

前言1.数据重塑

1.1 一般数据1.2 多层索引1.3 多层索引的运算 2.数学和统计方法

2.1 简单统计指标2.2 索引标签、位置获取2.3 更多统计指标2.4 高级统计指标 3.数据排序

3.1 根据索引行列名进行排序3.2 属性值排序3.3 返回属性n大或者n小的值 4.分箱操作

4.1 等宽分箱4.2 指定宽度分箱4.3 等频分箱 5.分组聚合

5.1 分组5.2 分组聚合apply、transform5.3 分组聚合agg5.4 透视表pivot_table 6.数据可视化

6.1 线形图6.2 条形图6.3 饼图6.4 散点图6.5 面积图 7.训练场

7.1 找到一班(名字后面跟的数字表示班级),获取班级将其男生1000米跑,成绩绘制线形图7.2 对各项体侧指标进行分箱操作:不及格(0~59)、及格(60~69)、中等(70~79)、良好(80~89)、优秀(90~100)7.3 绘制全校男生1000米跑和男跳远的条形图(分箱操作后统计各个成绩水平数量)7.4 绘制全校女生50米跑和女仰卧的饼图(分箱操作后统计各个成绩水平的数量)7.5 绘制男跳远、女跳远的堆叠条形图(分箱操作后统计各个成绩水平的数量)

前言

本文其实属于:Python的进阶之道【AIoT阶段一】的一部分内容,本篇把这部分内容单独截取出来,方便大家的观看,本文介绍 pandas 高级,读本文之前建议先修:pandas 入门,pandas 高级

1.数据重塑

数据重塑其实就是行变列,列变行

1.1 一般数据
import numpy as np
import pandas as pd

df = pd.Dataframe(data = np.random.randint(0, 100, size = (10, 3)),
                     index = list('ABCDEFHIJK'),
                     columns = ['Python', 'Tensorflow', 'Keras'])
display(df)

# 转置
df.T

1.2 多层索引
df2 = pd.Dataframe(data = np.random.randint(0, 100, size = (20, 3)),
                   index = pd.MultiIndex.from_product([list('ABCDEFHIJK'), 
                                                       ['期中', '期末']]),#多层索引
                   columns = ['Python', 'Tensorflow', 'Keras'])
df2


我们来解释一下这个复杂的代码:ndex = pd.MultiIndex.from_product([list('ABCDEFHIJK'), ['期中', '期末']]),我们的第一个参数:ABCDEFHIJK,共是 10 10 10 个字母,第二个参数是两个字符串,所以我们一共会有 20 20 20 行的数据,这正好对应了前面的代码size = (20, 3),读者自行理解下面这个代码:

df3 = pd.Dataframe(data = np.random.randint(0, 100, size = (10, 6)),
                   index = list('ABCDEFHIJK'),
                   columns = pd.MultiIndex.from_product([['Python', 'Math', 'English'],
                                                         ['期中', '期末']]))
df3


我们用 unstack() 完成多层索引行变列的数据重塑:

# 行索引变列索引,结构改变
# 默认情况下,最里层调整
df2.unstack()


可以看出来,只是把行索引最里层的期中期末 移到了列索引的位置,我们也可以把行索引外层的 ABCDEFHIJK 移动至列索引的位置:

df2.unstack(level = 0)


我们用 stack() 完成多层索引列变行的数据重塑:

# 列索引变行索引,结构改变
# 默认情况下,最里层调整
df3.stack()


同样,我们通过调整参数可以实现使得列索引的最外层变成行索引:

df3.stack(level = 0)

1.3 多层索引的运算

sum() 求和运算:

df2.sum()


当然,这样的数据一般是没有意义的,我们一般想要求出每一位同学的总分,而不是每门科目的总分:

df2.sum(axis = 1)

# 期中,期末消失
# 计算的是每个人,期中期末的总分数
df2.sum(level = 0)


mean() 用来计算平均分:

# 同学消失
# 计算的是所有同学期中期末平均分
df2.mean(level = 1)


接下来简单介绍一下如何取数据:

# df3是多层列索引,可以直接使用[],根据层级关系取数据
# 取出 A 同学的 Python 科目的期中成绩
df3['Python', '期中']['A']

df2['Python']['A', '期中']

2.数学和统计方法

pandas对象拥有一组常用的数学和统计方法。它们属于汇总统计,对Series汇总计算获取mean、max值或者对Dataframe行、列汇总计算返回一个Series。

2.1 简单统计指标

创建数据:

import numpy as np
import pandas as pd

df = pd.Dataframe(data = np.random.randint(0, 100,size = (20, 3)),
                  index = list('ABCDEFHIJKLMNOPQRSTU'),
                  columns = ['Python', 'Tensorflow', 'Keras'])
df

我们现在来把一部分数据设置为空:

def convert(x):
    if x > 80:
        return np.NaN
    else:
        return x
df['Python'] = df['Python'].map(convert)
df['Tensorflow'] = df['Tensorflow'].apply(convert)
df['Keras'] = df['Keras'].transform(convert)

df

现在我们想知道到底有多少个空数据,我们可以自己去数,但这显然是低效的方法,使用 count() 函数可以直接去统计有多少个非空数据:

df.count()  # 统计非空数据的个数

我们重新来构造数据:

import numpy as np
import pandas as pd

df = pd.Dataframe(data = np.random.randint(0, 100,size = (20, 3)),
                  index = list('ABCDEFHIJKLMNOPQRSTU'),
                  columns = ['Python', 'Tensorflow', 'Keras'])
df


使用 median() 可以计算数据的中位数:

df.median()  # 中位数

display(df.quantile(q = 0.5)) # 返回位于数据 50% 位置的数
display(df.quantile(q = 0.8)) # 返回位于数据 80% 位置的数


我们也可以使用如下的方法实现同样的效果:

df.quantile(q = [0.5, 0.8])

2.2 索引标签、位置获取
display(df['Python'].argmin()) # 计算最小值位置
display(df['Keras'].argmax()) # 最大值位置

display(df.idxmax()) # 最大值索引标签
display(df.idxmin()) # 最小值索引标签


索引就是自然数,标签就是我们初始设置的 ABCD…,索引和标签是一一对应的,如 0 对应的就是 A

2.3 更多统计指标

创建数据:

import numpy as np
import pandas as pd

df = pd.Dataframe(data = np.random.randint(0, 5,size = (20, 3)),
                  index = list('ABCDEFHIJKLMNOPQRSTU'),
                  columns = ['Python', 'Tensorflow', 'Keras'])
df


使用 value_counts() 可以统计元素出现的次数:

# 统计元素出现次数
df['Python'].value_counts()


使用 unique() 可以实现去重:

# 去重
df['Python'].unique()


调用 cumsum() 实现累加,调用 cumprod() 实现累乘:

# 累加
display(df.cumsum())
# 累乘
display(df.cumprod())


cummin() 的作用是累计最小值,即碰到更小的数后,该数往后所有数都变成这个更小的数,cummax() 的作用是累计最大值,即碰到更大的数后,该数往后所有的数都变成这个更大的数:

# 累计最小值
display(df.cummin())
# 累计最大值
display(df.cummax())


计算标准差调用 std(),计算方差调用 var()

# 计算标准差
display(df.std())
# 计算方差
display(df.var())


计算差分使用 diff(),差分就是这一行减上一行的结果,计算百分比的变化使用 pct_change():

# 计算差分
# 差分:和上一行相减
display(df.diff())
# 计算百分比变化
display(df.pct_change())

2.4 高级统计指标

我们使用 cov() 和 corr() 用来分别计算协方差和相关性系数:

协方差: C o v ( X , Y ) = ∑ 1 n ( X i − X ‾ ) ( Y i − Y ‾ ) n − 1 Cov(X,Y) = frac{sum_{1}^{n}(X_i-overline{X})(Y_i-overline{Y})}{n-1} Cov(X,Y)=n−1∑1n​(Xi​−X)(Yi​−Y)​

相关性系数: r ( X , Y ) = C o v ( X , Y ) V a r [ X ] V a r [ Y ] r(X,Y) = frac{Cov(X,Y)}{sqrt{Var[X]Var[Y]}} r(X,Y)=Var[X]Var[Y] ​Cov(X,Y)​

# 属性的协方差
display(df.cov())
# Python和Keras的协方差
display(df['Python'].cov(df['Keras'])) 

# 所有属性相关性系数
display(df.corr())
# 单一属性相关性系数
display(df.corrwith(df['Tensorflow']))

3.数据排序

创建数据

import numpy as np
import pandas as pd

df = pd.Dataframe(data = np.random.randint(0, 30, size = (30, 3)),
                  index = list('qwertyuioijhgfcasdcvbnerfghjcf'),
                  columns = ['Python', 'Keras', 'Pytorch'])
df


是一个看起来乱糟糟的数据,我们排序介绍三种方法

3.1 根据索引行列名进行排序
# 按行名排序,升序
display(df.sort_index(axis = 0, ascending = True))
# 按列名排序,降序
display(df.sort_index(axis = 1, ascending = False)) 


当然,按照索引行列名进行排序是不常用的,我们一般都是对数据进行排序

3.2 属性值排序
# 按Python属性值排序
display(df.sort_values(by = ['Python']))
# 先按Python,再按Keras排序
display(df.sort_values(by = ['Python', 'Keras']))

3.3 返回属性n大或者n小的值
# 根据属性Keras排序,返回最大3个数据
display(df.nlargest(3, columns = 'Keras'))
# 根据属性Python排序,返回最小5个数据
display(df.nsmallest(5, columns = 'Python'))

4.分箱操作

分箱操作就是将连续数据转换为分类对应物的过程。比如将连续的身高数据划分为:矮中高。
分箱操作分为等距分箱和等频分箱。
分箱操作也叫面元划分或者离散化。

我们先来创建数据:

import numpy as np
import pandas as pd

df = pd.Dataframe(data = np.random.randint(0, 150, size = (100, 3)),
                  columns = ['Python', 'Tensorflow', 'Keras'])
df

4.1 等宽分箱

等宽分箱在实际操作中意义不大,因为我们一般都会给一个特定的分类标准,比如高于 60 是及格,等分在生活中应用并不多

# bins = 3 表示把 Python 成绩划分成三份
pd.cut(df.Python, bins = 3)

4.2 指定宽度分箱

下述代码就实现了自行定义宽度进行分箱操作,在下述带啊中,不及格是 [ 0 , 60 ) [0,60) [0,60),中等是 [ 60 , 90 ) [60, 90) [60,90),良好是 [ 90 , 120 ) [90, 120) [90,120),优秀是 [ 120 , 150 ) [120, 150) [120,150) 均为左闭右开,这个是由 right = False 设定的

pd.cut(df.Keras,   #分箱数据
       bins = [0, 60, 90, 120, 150],  # 分箱断点
       right = False,      # 左闭右开
       labels=['不及格', '中等', '良好', '优秀'])# 分箱后分类

4.3 等频分箱

等频分箱是按照大家的普遍情况进行等分的操作

pd.qcut(df.Python,q = 4,                 # 4等分
        labels=['差', '中', '良', '优']) # 分箱后分类

5.分组聚合

首先来创建数据:

import numpy as np
import pandas as pd
# 准备数据
df = pd.Dataframe(data = {'sex':np.random.randint(0, 2, size = 300), # 0男,1女
                          'class':np.random.randint(1, 9, size = 300),# 1~8八个班
                          'Python':np.random.randint(0, 151, size = 300),# Python成绩
                          'Keras':np.random.randint(0, 151, size =300),# Keras成绩
                          'Tensorflow':np.random.randint(0, 151, size = 300),
                          'Java':np.random.randint(0, 151,size = 300),
                          'C++':np.random.randint(0, 151, size = 300)})
df['sex'] = df['sex'].map({0:'男', 1:'女'})             # 将0,1映射成男女
df

5.1 分组

根据性别分组并求出平均值,并把平均值保留一位小数:

df.groupby(by = 'sex').mean().round(1)


分组统计男女的数量:

df.groupby(by = 'sex').size()


根据性别和班级两个属性进行分组:

df.groupby(by = ['sex', 'class']).size()


获取每个班,男生女生 P y t h o n , J a v a Python,Java Python,Java 最高分

df.groupby(by = ['sex', 'class'])[['Python', 'Java']].max()


我们通过多层索引的思想对上述代码稍作调整:

df.groupby(by = ['class', 'sex'])[['Python', 'Java']].max()


再用之前学过的数据重塑,又可以稍加变形:

df.groupby(by = ['class', 'sex'])[['Python', 'Java']].max().unstack()

5.2 分组聚合apply、transform

 a p p l y apply apply 返回的是汇总后的情况,对于每一个分组大类都只返回一个结果:

df.groupby(by = ['class','sex'])[['Python','Keras']].apply(np.mean).round(1)


t r a n s f o r m transform transform 是把所有的元素全部返回:

df.groupby(by = ['class','sex'])[['Python','Keras']].transform(np.mean).round(1)

5.3 分组聚合agg

agg 比起 apply 和 transform 来说,功能更加的强大

# 按照班级和性别进行划分,统计 Tensorflow 和 Keras 这两门学科的最大值,最小值,个数
df.groupby(by = ['class','sex'])[['Tensorflow','Keras']].agg(
    [np.max, np.min, pd.Series.count])

# 分组后不同属性应用多种不同统计汇总
# 对 Python 计算最大值和最小值
# 对 Keras 计数和计算中位数
df.groupby(by = ['class','sex'])[['Python','Keras']].agg(
    {'Python':[('最大值',np.max),('最小值',np.min)],
     'Keras':[('计数',pd.Series.count),('中位数',np.median)]})

5.4 透视表pivot_table

所谓透视,其实就是发现事物的一定规律

def count(x):
    return len(x)
df.pivot_table(values=['Python', 'Keras', 'Tensorflow'],# 要透视分组的值
               index=['class', 'sex'], # 分组透视指标,相当于之前的 by
               aggfunc={'Python':[('最大值', np.max)], # 聚合运算
                        'Keras':[('最小值', np.min),('中位数', np.median)],
                        'Tensorflow':[('最小值', np.min),('平均值', np.mean),('计数', count)]})

6.数据可视化

修本章节之前需要安装 m a t p l o t l i b matplotlib matplotlib,建议先修:matplotlib的安装教程以及简单调用

6.1 线形图
df1 = pd.Dataframe(data = np.random.randn(1000, 4),
                  index = pd.date_range(start = '23/1/2022', periods = 1000),
                  columns=list('ABCD'))
df1.cumsum().plot()

6.2 条形图
df2 = pd.Dataframe(data = np.random.rand(10, 4),
                   columns = list('ABCD'))
display(df2.plot.bar(stacked = True)) # stacked 堆叠
display(df2.plot.bar(stacked = False))# stacked 不堆叠

6.3 饼图
# 饼图用来表示百分比,百分比是自动计算的,颜色可以更换
df3 = pd.Dataframe(data = np.random.rand(4, 2),
                   index = list('ABCD'),
                   columns = ['One', 'Two'])
# subplots 表示两个图,多个图
# figsize 表示尺寸
df3.plot.pie(subplots = True,figsize = (8, 8))


更换颜色:

# 更换颜色
df3 = pd.Dataframe(data = np.random.rand(4, 2),
                   index = list('ABCD'),
                   columns = ['One', 'Two'])
df3.plot.pie(subplots = True,figsize = (8, 8),
             colors = np.random.random(size = (4, 3)))

6.4 散点图
# 横纵坐标,表示两个属性之间的关系
df4 = pd.Dataframe(np.random.randint(0, 50, size = (50, 4)), columns = list('ABCD'))
display(df4.plot.scatter(x = 'A', y = 'B')) # A和B关系绘制

df4['F'] = df4['C'].map(lambda x : x + np.random.randint(-5, 5, size = 1)[0])
display(df4.plot.scatter(x = 'C', y = 'F'))

6.5 面积图
df5 = pd.Dataframe(data = np.random.rand(10, 4), 
                   columns = list('ABCD'))
display(df5.plot.area(stacked = True))  # stacked 堆叠
display(df5.plot.area(stacked = False)) # stacked 不堆叠


同样,我们可以调节它的颜色:

df5 = pd.Dataframe(data = np.random.rand(10, 4), 
                   columns = list('ABCD'))
display(df5.plot.area(stacked = True,
                      color = np.random.rand(4, 3)))
# 解释一下 random.rand(4, 3)
# 3就代表三个颜色:红绿蓝(三基色)
# 4就代表 ABCD

7.训练场

首先我们需要下载一个 Excel 文件:

链接:https://pan.baidu.com/s/1gkEEH1yVA1RdaXTrFbw3ww?pwd=rm9t
提取码:rm9t

下载完成之后,把该文件和我们的代码放到同一个文件夹下,这一操作我们在之前的博客中已经反复说到,这里就不再进行演示

7.1 找到一班(名字后面跟的数字表示班级),获取班级将其男生1000米跑,成绩绘制线形图
import numpy as np
import pandas as pd

# 获取1班数据
df = pd.read_excel('./分数汇总.xlsx', sheet_name = 0)
# 获取1班的名字
cnt = df['姓名'].str[3:].astype(np.int16) == 1
df2 = df[cnt]

s = df2['男1000米跑分数']
# 把 Series 数据转为 Dataframe
# 重置行索引,0、1、2、3......
score = s.reset_index()[['男1000米跑分数']]

# 绘图
score.plot()


绘图虽然绘制出来了,但是报错一大堆,这是因为有中文的原因,我们接着继续处理:
接下来的处理方法涉及 m a t p l o t l i b matplotlib matplotlib,属于超纲内容,可以不进行模拟,安装 m a t p l o t l i b matplotlib matplotlib 见博文:matplotlib的安装教程以及简单调用
这是字体需要导包:import matplotlib.pyplot as plt

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

# 获取1班数据
df = pd.read_excel('./分数汇总.xlsx', sheet_name = 0)
# 获取1班的名字
cnt = df['姓名'].str[3:].astype(np.int16) == 1
df2 = df[cnt]

s = df2['男1000米跑分数']
# 把 Series 数据转为 Dataframe
# 重置行索引,0、1、2、3......
score = s.reset_index()[['男1000米跑分数']]

# 把字体设置为楷体(你的电脑上需有这个字体才能进行设置)
plt.rcParams['font.family'] = 'STKaiti'
# 调整字体大小
plt.rcParams['font.size'] = 18

# 绘图
score.plot()

7.2 对各项体侧指标进行分箱操作:不及格(0~59)、及格(60~69)、中等(70~79)、良好(80~89)、优秀(90~100)
columns = df.columns
for col in columns:
    if col.endswith('分数'):
        df[col] = pd.cut(df[col], bins = [0, 60, 70, 80, 90, 101],
                         labels = ['不及格', '及格', '中等', '良好', '优秀'],
                         right = False)
        
df2 = pd.read_excel('./分数汇总.xlsx', sheet_name = 1)
columns = df2.columns
for col in columns:
    if col.endswith('分数'):
        df2[col] = pd.cut(df2[col], bins = [0, 60, 70, 80, 90, 101],
                          labels = ['不及格', '及格', '中等', '良好', '优秀'],
                          right = False)
7.3 绘制全校男生1000米跑和男跳远的条形图(分箱操作后统计各个成绩水平数量)
# 获取男1000米跑分数的数据
s1 = df['男1000米跑分数'].value_counts()
s1.sort_index()
# 获取男跳远分数的数据
s2 = df['男跳远分数'].value_counts()
s2.sort_index()
# 合并成为一个新的 Dataframe
df3 = pd.Dataframe({'男1000米跑分数':s1, '男跳远分数':s2})
# 绘图
df3.plot.bar()

7.4 绘制全校女生50米跑和女仰卧的饼图(分箱操作后统计各个成绩水平的数量)
# 获取女50米跑分数的数据
s3 = df2['女50米跑分数'].value_counts()
s3 = s3.sort_index()
# 获取女仰卧分数的数据
s4 = df2['女仰卧分数'].value_counts()
s4 = s3.sort_index()
# 合并数据
df4 = pd.Dataframe({'女50米跑分数':s3, '女仰卧分数':s4})

df4.plot.pie(subplots = True)


更改一下我们的图像尺寸:

# 获取女50米跑分数的数据
s3 = df2['女50米跑分数'].value_counts()
s3 = s3.sort_index()
# 获取女仰卧分数的数据
s4 = df2['女仰卧分数'].value_counts()
s4 = s3.sort_index()
# 合并数据
df4 = pd.Dataframe({'女50米跑分数':s3, '女仰卧分数':s4})

df4.plot.pie(subplots = True, figsize = (16, 16))


显示各部分的百分比:

# 获取女50米跑分数的数据
s3 = df2['女50米跑分数'].value_counts()
s3 = s3.sort_index()
# 获取女仰卧分数的数据
s4 = df2['女仰卧分数'].value_counts()
s4 = s3.sort_index()
# 合并数据
df4 = pd.Dataframe({'女50米跑分数':s3, '女仰卧分数':s4})
# 显示百分比,百分比保留两位小数
df4.plot.pie(subplots = True, figsize = (16, 16), autopct = '%0.2f%%')

7.5 绘制男跳远、女跳远的堆叠条形图(分箱操作后统计各个成绩水平的数量)
# 获取男跳远分数的数据
s5 = df['男跳远分数'].value_counts()
s5 = s5.sort_index()
# 获取女跳远分数的数据
s6 = df2['女跳远分数'].value_counts()
s6 = s6.sort_index()
# 数据合并
df5 = pd.Dataframe({'男跳远分数':s5, '女跳远分数':s6})
# 绘制堆叠条形图
df5.plot.bar(stacked = True)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/714230.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号