Pandas统计分析(数据排序、计算、统计)

116 阅读15分钟

数据排序

DataFrame数据排序主要使用sort_values()方法,该方法类似于SQL中的ORDER_BY.sort_values()方法可以根据指定行/列进行排序,语法如下:

DataFrame.sort_values(by, 
                      axis=0, 
                      ascending=True, 
                      inplace=False, 
                      kind='quicksort', 
                      na_position='last', 
                      ignore_index=False, 
                      key=None)

参数说明:

  • by: 排序的列名或列名的列表.
  • axis: 0是按行排序,1是按列排序,默认是0.
  • ascending: 默认是True,即升序排序;False为降序排序.
  • inplace: 是否修改原数据。默认值是False不替换;如果为True,则在原始数据帧中进行原位排序.
  • ignore_index: 是否重置索引,默认为False。如果为True,则将新的整数索引分配给结果DataFrame。
  • key: 排序用的函数.

按一列数据排序

import pandas as pd
excelFile = 'mrbook.xlsx'
df = pd.DataFrame(pd.read_excel(excelFile))
pd.set_option('display.unicode.east_asian_width', True)
#按“销量”列 , 降序排序(F降T升)
df=df.sort_values(by='销量',ascending=False)
print(df)

按多列数据排序

import pandas as pd
excelFile = 'mrbook.xlsx'
df = pd.DataFrame(pd.read_excel(excelFile))
pd.set_option('display.unicode.east_asian_width', True)
#按“类别”和“销量”列降序排序
df=df.sort_values(by=['销量','类别'])
print(df)

对统计结果排序

import pandas as pd
excelFile = 'mrbook.xlsx'
df = pd.DataFrame(pd.read_excel(excelFile))

df1=df.groupby(["类别"])["销量"].sum().reset_index()  #对类别进行分类,然后求销量综合,并重新对行索引排序
df2=df1.sort_values(by='销量',ascending=False)   #通过销量,降序排序
print(df2)

对行数据排序

import pandas as pd
excelFile = 'books.xls'
dfrow = pd.DataFrame(pd.read_excel(excelFile))

#按照索引值为0的行,即第一行的值升序排序
df=dfrow.sort_values(by=0,ascending=True,axis=1)
print(df)

输出结果:

image.png

数据排名

排名是根据Series对象或dataframe的某几列的值进行排名的,主要使用rank()方法。语法如下:

DataFrame.rank(axis=0, method=‘average’, numeric_only=NoDefault.no_default, na_option=‘keep’, ascending=True, pct=False)

参数说明:

axis: axis=0为按行排名,axis=1为按列排名

method: 如何对具有相同价值(即领带)的记录组进行排序

numeric_only: 对于DataFrame对象,如果设置为True,则只对数字列排序

na_option: 如何对NaN值进行排序: ascending: 元素按升序/降序排列

pct: 是否以百分比形式显示返回的排名

顺序排名

import pandas as pd
excelFile = 'mrbook.xlsx'
df = pd.DataFrame(pd.read_excel(excelFile))
pd.set_option('display.unicode.east_asian_width', True)
#按“销量”列降序排序
df=df.sort_values(by='销量',ascending=False)
print(df)
# 顺序排名
# df['顺序排名'] = df['销量'].rank(method="first", ascending=False)   #rank(method=‘first’) 就是根据数字本身正常排序,这里和省略的结果一样
df1=df[['图书名称','销量','顺序排名']]
print(df1)

平均排序、最小值排名、最大值排名

import pandas as pd
df = pd.DataFrame(pd.read_excel('mrbook.xlsx'))

#按“销量”列降序排序
pd.set_option('display.unicode.east_asian_width',True)
df=df.sort_values(by='销量',ascending=False)
print(df)

#平均排名
pd.set_option('display.unicode.east_asian_width',True)
df['平均排名']=df['销量'].rank(ascending=False)
df1=df[['图书名称','销量','平均排名']]
print(df1)

#最小值排名
df['最小值排名']=df['销量'].rank(method="min",ascending=False)
df_min=df[['图书名称','销量','最小值排名']]
print(df_min)

#最大值排名
df['最大值排名']=df['销量'].rank(method="max",ascending=False)
df_max=df[['图书名称','销量','最大值排名']]
print(df_max)

数据计算

注意:以下计算方式中的的axis参数都是1行0列,包括中位数计算。

求和 sum()函数

DataFrame.sum(axis = None,skipna = None,level = None,numeric_only = None,min_count = 0,**kwargs)

参数说明:

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • skipna:布尔型,表示计算结果是否排除NaN/Null值,默认值为None
  • level:表示索引层级,默认为None
  • numeric_only:仅数字,布尔型,默认值为None
  • min_count:表示执行操作所需的数目,整型,默认为0
  • **kwargs:要传递给函数的附加关键字参数。
  • 返回值:返回Series对象或DataFrame对象。行或列求和数据
import pandas as pd

pd.set_option('display.unicode.east_asian_width', True)
data = [[110, 105, 99], [105, 88, 115], [109, 120, 130]]
index = [1, 2, 3]
columns = ['语文', '数学', '英语']
df = pd.DataFrame(data=data, index=index, columns=columns)
print(df)
df['总成绩'] = df.sum(axis=1)
print(df)

输出结果:

image.png

求均值 mean()函数

mean(axis=None, skipna=None, level=None, numeric_only=None, **kwargs)

参数说明:

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • skipna:布尔型,表示计算结果是否排除NaN/Null值,默认值为None
  • level:表示索引层级,默认为None
  • numeric_only:仅数字,布尔型,默认值为None
  • min_count:表示执行操作所需的数目,整型,默认为0
  • **kwargs:要传递给函数的附加关键字参数。
  • 返回值:返回Series对象或DataFrame对象。行或列平均值数据
import pandas as pd

pd.set_option('display.unicode.east_asian_width', True)
data = [[110, 105, 99], [105, 88, 115], [109, 120, 130]]
index = [1, 2, 3]
columns = ['语文', '数学', '英语']
df = pd.DataFrame(data=data, index=index, columns=columns)
print(df)
df['平均成绩'] = df.mean(axis=1)
print(df)

输出结果:

image.png

最小值 min()

min(axis=None, skipna=None, level=None, numeric_only=None, **kwargs)

参数说明:

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • skipna:布尔型,表示计算结果是否排除NaN/Null值,默认值为None
  • level:表示索引层级,默认为None
  • numeric_only:仅数字,布尔型,默认值为None
  • min_count:表示执行操作所需的数目,整型,默认为0
  • **kwargs:要传递给函数的附加关键字参数。
  • 返回值:返回Series对象或DataFrame对象。行或列最小值数据
import pandas as pd
pd.set_option('display.unicode.east_asian_width',True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,111]]
index = [1,2,3,4]
columns =['语文','数学','英语']
df = pd.DataFrame(data = data,index = index,columns=columns)
print(df)

new = df.min()
print(new)

最大值 max()

max(axis=None, skipna=None, level=None, numeric_only=None, **kwargs)

参数说明:

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • skipna:布尔型,表示计算结果是否排除NaN/Null值,默认值为None
  • level:表示索引层级,默认为None
  • numeric_only:仅数字,布尔型,默认值为None
  • min_count:表示执行操作所需的数目,整型,默认为0
  • **kwargs:要传递给函数的附加关键字参数。
  • 返回值:返回Series对象或DataFrame对象。行或列最大值数据
import pandas as pd
pd.set_option('display.unicode.east_asian_width',True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,113]]
index = [1,2,3,4]
columns =['语文','数学','英语']
df = pd.DataFrame(data = data,index = index,columns=columns)
print(df)

new = df.max()
print(new)

中位数 median()

median(axis=None, skipna=None, level=None, numeric_only=None, **kwargs)

参数说明:

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • skipna:布尔型,表示计算结果是否排除NaN/Null值,默认值为None
  • level:表示索引层级,默认为None
  • numeric_only:仅数字,布尔型,默认值为None
  • min_count:表示执行操作所需的数目,整型,默认为0
  • **kwargs:要传递给函数的附加关键字参数。
  • 返回值:返回Series对象或DataFrame对象。行或列中位数数据
import pandas as pd
pd.set_option('display.unicode.east_asian_width',True)
data = [[110,105,99],[105,88,115],[109,120,130]]
index = [1,2,3]
columns =['语文','数学','英语']
df = pd.DataFrame(data = data,index = index,columns=columns)
print(df)

new = df.median()
print(new)

众数 mode()

众数就是一组数据中出现最多的数,代表了数据的一般水平。

mode(axis=0, numeric_only=False, dropna=True)

参数说明:

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • numeric_only:仅数字,布尔型,默认值为None
  • drop_na:是否删除缺失值,布尔型,默认为True
  • 返回Series对象或DataFrame对象。
import pandas as pd
pd.set_option('display.unicode.east_asian_width',True)
data = [[110,120,110],[130,130,130],[130,120,130]]
columns = ['语文','数学','英语']
df = pd.DataFrame(data = data ,columns=columns)
print(df)

print(df.mode())#三科成绩的众数

print(df.mode(axis = 0))#每一列的众数

print(df['数学'].mode())#'数学'成绩的众数

方差 var()

方差越大,越不稳定

var(axis=None, skipna=None, level=None, ddof=1, numeric_only=None, **kwargs)

参数说明:

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • skipna:布尔型,表示计算结果是否排除NaN/Null值,默认值为None
  • level:表示索引层级,默认为None
  • ddof:整型,默认值为1.自由度,计算中使用的除数是N-ddof,其中N表示元素的数量。
  • numeric_only:仅数字,布尔型,默认值为None
  • **kwargs:要传递给函数的附加关键字参数。
  • 返回值:返回Series对象或DataFrame对象。
import pandas as pd

data = [[110, 113, 102, 105, 108], [118, 98, 119, 85, 118]]
index = ['小黑', '小白']
columns = ['物理1', '物理2', '物理3', '物理4', '物理5']
df = pd.DataFrame(data=data, index=index, columns=columns)
print(df.var(axis=1))  #小黑和小白成绩的方差

标准差 std()

标准差越小,数据点就更靠近平均值,表明数据分布较为集中,数据较为稳定,风险较小。

std(axis=None, skipna=None, level=None, ddof=1, numeric_only=None, **kwargs)

参数说明: 跟var的参数一样

  • axis:axis = 1表示行,axis = 0表示列,默认为None(无)
  • skipna:布尔型,表示计算结果是否排除NaN/Null值,默认值为None
  • level:表示索引层级,默认为None
  • ddof:整型,默认值为1.自由度,计算中使用的除数是N-ddof,其中N表示元素的数量。
  • numeric_only:仅数字,布尔型,默认值为None
  • **kwargs:要传递给函数的附加关键字参数。
  • 返回值:返回Series对象或DataFrame对象。
import pandas as pd

data = [[110, 113, 102, 105, 108], [118, 98, 119, 85, 118]]
index = ['小黑', '小白']
columns = ['物理1', '物理2', '物理3', '物理4', '物理5']
df = pd.DataFrame(data=data, index=index, columns=columns)
print(df.std(axis=1))  #小黑和小白成绩的标准差

数据格式化

在进行数据处理时,尤其是在数据计算中应用求均值(mean()函数)后,发现结果中的小数位数增加了许多。此时就需要对数据进行格式化,以增加数据的可读性。例如,保留小数点位数,百分号,千位分隔符等等。

注意numpy和pandas的区别

  1. numpy的核心数据结构是ndarray,支持任意维数的数组
  2. numpy用于数值计算,pandas主要用于数据处理与分析

设置小数位数

设置小数位数主要使用DataFrame对象的round()函数,该函数可以实现四舍五入,而它的decimals参数则用于设置保留小数的位数,设置后数据类型不会发生变化,依然是浮点型。 语法如下:

DataFrame.round(decimals=0,*args,**kwargs)

参数说明:

  • decimals:每一列四舍五入的小数位数,整数,字典或者Series对象。如果是整数,则将每一列四舍五入到相同的位置。否则,将字典和Series摄入到可变数目的位置;如果小数是类似于字典的,那么列名应该在键中;如果小数是级数,列名应该在索引中。没有包含在小数中的任何列都将保持原样。非输入列的小数元素都将被忽略。
  • args,kwargs:附加关键字的参数
  • 返回值:返回DataFrame对象
import pandas as pd
import numpy as np
# print(np.random.random([5, 5])) #生成一个5X5的数组
df = pd.DataFrame(np.random.random([5, 5]),columns=['A1', 'A2', 'A3','A4','A5'])
print(df)

print(df.round(2))                                   #保留小数点后两位,四舍五入
print(df.round({'A1': 1, 'A2': 2}))                  #A1列保留小数点后一位、A2列保留小数点后两位

s1 = pd.Series([1, 0, 2], index=['A1', 'A2', 'A3']) 
print(s1)
print(df.round(s1))                                  #设置Series对象小数位数,相当于这里传入的是{'A1': 1,'A2': 0,'A3': 2}

设置百分比

在数据分析过程中,有时需要百分比数据。那么,利用自定义函数讲数据进行格式化处理,处理后的数据就可以从浮点型和转换成带指定小数位数的百分比数据。其中主要用到的就是apply()函数和format()函数。

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.random([5, 5]),columns=['A1', 'A2', 'A3','A4','A5'])

df['百分比']=df['A1'].apply(lambda x: format(x,'.0%'))       #整列保留0位小数
print(df)
df['百分比']=df['A1'].apply(lambda x: format(x,'.2%'))       #整列保留两位小数
print(df)
df['百分比']=df['A1'].map(lambda x:'{:.2%}'.format(x))       #将每个元素转换为百分比形式并保留 0 位小数。整列保留0位小数,也可以使用map函数
print(df)

输出结果:

image.png

设置千位分隔符

有时候由于业务的需要,需要将数据格式化为带千位分隔符的数据,但是处理后的数据不再是浮点型,而是对象型,即为字符串

import pandas as pd

data = [['零基础学Python','1月',49768889],['零基础学Python','2月',11777775],['零基础学Python','3月',13799990]]
columns = ['图书','月份','码洋']
df = pd.DataFrame(data=data, columns=columns)
print(df)
print(df['码洋'])
df['码洋']=df['码洋'].apply(lambda x:format(int(x),',')) # 逗号会根据数字的长度自动插入到适当的位置,以形成千位分隔,这是format函数的默认行为。
print(df)

数据分组统计

对数据进行分组统计,主要使用DataFrame对象中的groupby()函数,其功能如下:

1、根据给定的条件将数据拆分成组。

2、每个组都可以独立应用函数。

3、将结果合并到一个数据结构中。 语法如下:

DataFrame.groupby(by=None,axis=0,level=None,as_index=True,sort=True,froup_keys=True,squeeze=Flase,observed=Flase)

参数说明:

  • by:用于分组的列名或函数。可以是一个列名、一个函数、一个列表或一个字典。
  • axis:分组轴。如果 axis=0(默认值),则沿着行方向分组;如果 axis=1,则沿着列方向分组。
  • level:在多层索引的情况下,用于指定分组的级别。
  • as_index:是否将分组键作为索引返回。如果 as_index=True(默认值),则返回一个带有分组键作为索引的对象;否则返回一个不带索引的对象。
  • sort:是否对分组键进行排序。如果 sort=True(默认值),则对分组键进行排序;否则不排序。
  • group_keys:是否在结果中包含分组键。如果 group_keys=True(默认值),则在结果中包含分组键;否则不包含。
  • squeeze:是否压缩返回结果。如果 squeeze=True,则尝试压缩返回结果;否则不压缩。
  • observed:是否仅使用观察到的类别进行分组。仅适用于类别类型数据。

按照一列分组统计

import pandas as pd

df = pd.read_csv('JD.csv',encoding='gbk')
pd.set_option('display.unicode.east_asian_width', True)
df1 = df[['一级分类','7天点击量','订单预定']]
print(df1)

print(df1.groupby('一级分类').sum())

输出结果:

image.png

按照多列分组统计

import pandas as pd
# 解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width',True)
df = pd.read_csv('JD.csv',encoding='gbk')

df2 = df[['一级分类','二级分类','7天点击量','订单预定']]
print(df2)
print(df2.groupby(['一级分类','二级分类']).sum())

输出结果:

image.png

分组并按照指定列数据计算

df3 = df[['二级分类', '7天点击量']]
df3 = df3.groupby('二级分类')['7天点击量'].sum()
print(df3)

对分组数据进行迭代

使用for循环对分组统计数据进行迭代

import pandas as pd  #导入pandas模块

df=pd.read_csv('JD.csv',encoding='gbk')
#抽取数据
df1=df[['一级分类','7天点击量','订单预定']]
print(df1)

for name, group in df1.groupby('一级分类'):
        print(name)
        print(group)

image.png

对分组的某列或多列使用聚合函数(agg()函数)

python也可以实现像SQL中的分组聚合运算操作,主要通过gropby()函数与agg()函数实现。 对分组统计结果使用聚合函数。

import pandas as pd  #导入pandas模块

df=pd.read_csv('JD.csv',encoding='gbk')
#抽取数据
df1=df[['一级分类','定价','7天点击量','订单预定']]

print(df1)
print(df1.groupby('一级分类').agg(['mean','sum']))

针对不同的列使用不同的聚合函数。

import pandas as pd  #导入pandas模块

df=pd.read_csv('JD.csv',encoding='gbk')
#抽取数据
df1=df[['一级分类','定价','7天点击量','订单预定']]

print(df1.groupby('一级分类').agg({'定价':['mean'],'7天点击量':['mean','sum'], '订单预定':['sum']}))

自定义函数实现分组统计。

import pandas as pd  #导入pandas模块

df=pd.read_excel('1月.xlsx')  # 导入Excel文件
#x是“宝贝标题”对应的列
#value_counts()函数用于Series对象中的每个值进行计数并且排序
max1 = lambda x: x.value_counts(dropna=False).index[0]  #dropna=False不删除缺失值
max1.__name__ = "购买次数最多"
df1=df.agg({'宝贝标题': [max1],
        '数量': ['sum', 'mean'],
        '买家实际支付金额': ['sum', 'mean']})
print(df1)

数据移位

数据移位就是在分析数据时,需要移动到上一条,在pandas中,可以使用shift方法获得上一条数据。

该方法返回向下移动后的结果,从而得到上一条数据。

语法如下:

shift(periods=1,freq=None, axis=0)

参数说明:

periods:表示移动的幅度,可正可负,默认为1。1表示移动一次。这里移动的都是数据,索引不移动,移动之后没有对应值的,赋值为NaN。

freq:可选参数,默认为None,只适用于时间序列,如果这个参数存在,那么会按照参数值移动时间索引,而数据值没有发生变化。

axis:axis = 1表示行,axis = 0表示列。默认为0

import pandas as pd
data =[110,105,99,120,115]
index = [1,2,3,4,5]
df = pd.DataFrame(data = data,index = index,columns=['英语'])
print(df)
print(df['英语'].shift())
df['升降'] = df['英语']- df['英语'].shift()
print(df)

输出结果:

image.png

shitf()还有很多方面的应用。在分析股票数据,获取的股票数据中有股票的实时价格,也有每日的收盘价,此时需要将实时价格和上一个工作日的收盘价进行对比,那么通过shift()方法就可以轻松解决。