Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)

  • 本篇博文来自《Python数据分析从入门到精通》_明日科技编著
  • 相信经过第3章的学习,您已经了解Pandas了,那么本章开始进行Pandas进阶,对Pandas相关技术进一步加深讲解,主要包括数据计算、数据格式化,以及应用非常广泛的数据分组统计、数据位移、数据转换、数据合并、数据导出和日期数据的处理,时间序列等。
  • 对于本章的学习,可能存在一定难度,建议读者弹性学习,内容有一定的选择性,对于短时间无法理解的内容可以先放一放,重要的是多练习、多时间,重复学习是快速提升编程技能的阶梯。

4.1 数据计算

  • Pandas提供了大量的数据计算函数,可以实现求和、求均值、求最大值、求最小值、求中位数、求众数、求方差、标准差等,从而使得数据统计变得简单高效。

4.1.1 求和(sum()函数)

  • 在Python中通过调用DataFrame对象的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。

NaN表示非数值。在进行数据处理、数据计算时,Pandas会为缺少的值自动分配NaN值。

  • level:表示索引层级,默认值为None
  • numeric_only:仅数字,布尔型,默认值为None
  • min_count:表示执行操作所需的数目,整型,默认值为0
  • **kwargs:要传递给函数的附加关键字参数
  • 返回值:返回Series对象或DataFrame对象。行或列求和数据。
  • 首先,创建一组DataFrame类型的数据。包括语文、数学和英语三科的成绩:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130]]
index = [1,2,3]
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=index, columns=columns)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第1张图片

  • 下面使用sum()函数计算三科的总成绩,代码如下:
df['总成绩']=df.sum(axis=1)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第2张图片

4.1.2 求均值(mean()函数)

  • 在Python中通过调用DataFrame对象的mean()函数实现行/列数据平均值运算,语法如下:
DataFrame.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
    – **kwargs:要传递给函数的附加关键字参数
    – 返回值:返回Series对象或DataFrame对象。
  • 计算语文、数学和英语三科的平均值:
import pandas as pd
data = [[110,105,99],[105,88,115],[109,120,130],[112,115]]
index = [1,2,3,4]
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=index, columns=columns)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第3张图片

new=df.mean()
#增加一行数据(语文、数学和英语的平均值,忽略索引)
df=df.append(new,ignore_index=True)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第4张图片

  • 从运行结果看,语文平均分109,数学平均分107,英语平均分114.667

4.1.3 求最大值(max()函数)

  • 在Python中通过调用DataFrame对象的max()函数实现行/列数据最大值运算,语法如下:
DataFrame.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
    – **kwargs:要传递给函数的附加关键字参数
    – 返回值:返回Series对象或DataFrame对象
  • 计算语文、数学和英语三科的最大值:
new=df.max()
#增加一行数据(语文、数学和英语的最大值,忽略索引)
df=df.append(new,ignore_index=True)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第5张图片

4.1.4 求最小值(min()函数)

  • 在Python中通过调用DataFrame对象的min()函数实现行/列数据最小值运算,语法如下:
DataFrame.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
    – **kwargs:要传递给函数的附加关键字参数
    – 返回值:返回Series对象或DataFrame对象。
  • 计算语文、数学和英语三科的最小值:
new=df.min()
#增加一行数据(语文、数学和英语的最小值,忽略索引)
df=df.append(new,ignore_index=True)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第6张图片

4.1.5 求中位数(median()函数)

  • 在Python中通过调用DataFrame对象的median()函数实现中位数的计算,语法如下:
DataFrame.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
    – **kwargs:要传递给函数的附加关键字参数
    – 返回值:返回Series对象或DataFrame对象。
  • 计算语文、数学和英语三科的中位数:
import pandas as pd
data = [[110,120,110],[130,130,130],[130,120,130]]
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data,columns=columns)
new=df.median()
#增加一行数据(语文、数学和英语的中位数,忽略索引)
df=df.append(new,ignore_index=True)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第7张图片

4.1.6 求众数(model()函数)

  • 众数就是一组数据中出现最多的数称为众数,它代表了数据的一般水平。
  • 在Python中通过调用DataFrame对象的mode()函数求众数,语法如下:
DataFrame.mode(axis=0,numeric_only=False,dropna=True)
  • 参数说明:
    – axis:axis=1表示行,axis=0表示列,默认值为None(无)。
    – numeric_only:仅数字,布尔型,默认值为None
    – dropna:是否删除缺失值,布尔型,默认值为True。
    – 返回值:返回Series对象或DataFrame对象。
  • 计算语文、数学和英语三科的众数:
import pandas as pd
data = [[110,120,110],[130,130,130],[130,120,130]]
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data,columns=columns)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第8张图片

new=df.mode() #计算三科成绩的众数
#df.mode(axis=1)     #每一行的众数
#df['数学'].mode()   #“数学”的众数
#增加一行数据(语文、数学和英语的中位数,忽略索引)
df=df.append(new,ignore_index=True)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第9张图片

4.1.7 求方差(var()函数)

  • 方差用于衡量一组数据的离散程度,即各组数据与它们的平均数的差的平方,那么我们用这个结果衡量这组数据的波动大小,并把它叫做这组数据的方差,方差越小越稳定。通过方差可以了解以下这个问题的波动性。
  • 在Python中通过调用DataFrame对象的var()函数求方差,语法如下:
DataFrame.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
import numpy as np
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)
df.var(axis=1)

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第10张图片

  • 从运行结果得知:小黑的物理成绩波动较小,发挥更稳定。这里需要注意的是,Pandas中计算的方差为无偏样本方差(即方差和/样本数-1),NumPy中计算的方差就是样本方差本身(即方差和/样本数)。

4.1.8 标准差(数据标准化std()函数)

  • 在Python中通过调用DataFrame对象的std()函数求标准差,语法如下:
DataFrame.std(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对象。
  • 使用std()函数计算标准差,程序代码如下:
import pandas as pd
import numpy as np
data = [[110,120,110],[130,130,130],[130,120,130]]
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data,columns=columns)
new = df.std()
#增加一行数据(语文、数学和英语的标准差,忽略索引)
df=df.append(new,ignore_index=True)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第11张图片

4.1.9 求分位数(quantile()函数)

  • 分位数也称分位点,它以概率依据将数据分割成几个等份,常用的有中位数(即二分位数)、四分位数、百分位数等。分位数是数据分析中常用的一个统计量,经过抽样得到的一个样本值。例如,经常会听到老师说:“这次考试竟然有20%的同学不及格!”,那么这句话就体现了分位数的作用。在Python中通过DataFrame对象的quantile()函数求分位数,语法如下:
DataFrame.quantile(q=0.5,axis=0,numeric_only=True,interpolation='linear')
  • 参数说明:
    – q:浮点型或数组,默认为0.5(50%分位数),其值为0~1
    – axis:axis=1表示行,axis=0表示列,默认值为None(无)。
    – numeric_only:仅数字,布尔型,默认值为True
    – interpolation:内插值,可选参数,用于指定要使用的插值方法,当期望的分位数为数据点i~j时,线性:i + (j-i)x分数,其中分数是指被i和j包围的小数部分。较低:i。较高:j。最近:i或j二者最近者为准。中点:(i+j)/2
    – 返回值:返回Series对象或DataFrame对象。
  • 通过分位数淘汰35%的学生,首先使用quantile()函数计算35%的分位数,然后将学生成绩与分位数比较,筛选小于等于分位数的学生,程序代码如下:
import pandas as pd
#创建DataFrame数据(数学成绩)
data = [120,89,98,78,65,102,112,56,79,45]
columns = ['数学']
df = pd.DataFrame(data=data,columns=columns)
#计算35%的分位数
x=df['数学'].quantile(0.35)
#输出淘汰学生
df[df['数学']<=x]

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第12张图片

  • 从运行结果可知:即将被淘汰的学生有四名,分数分别是78、65、56和45。
  • 如果参数numeric_only=False,将计算日期、时间和时间增量数据的分位数,程序代码如下:
import pandas as pd
df = pd.DataFrame({'A': [1, 2],
                   'B': [pd.Timestamp('2019'),
                         pd.Timestamp('2020')],
                   'C': [pd.Timedelta('1 days'),
                         pd.Timedelta('2 days')]})
print(df.quantile(0.5, numeric_only=False))

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第13张图片

4.2 数据格式化

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

4.2.1 设置小数位数

  • 设置小数位数主要使用DataFrame对象的round()函数,该函数可以实现四舍五入,而它的decimals参数则用于设置保留小数的位数,设置后数据类型不会发生变化,依然是浮点型。语法如下:
DataFrame.round(decimals=0,*args,**kwargs)
  • decimals:每一列四舍五入的小数位数,整型、字典或Series对象。如果是整数,则将每一列四舍五入到相同的位置。否则,将字典和Series舍入到可变数目的位置;如果小数是类似于字典的,那么列名应该在键中;如果小数是级数,列名应该在索引中。没有包含在小数中的任何列都将保持原样。非输入列的小数元素将被忽略。
  • *args:附加的关键字参数
  • **kwargs:附加的关键字参数
  • 返回值:返回DataFrame对象
  • 使用round()函数四舍五入保留小数位数,程序代码如下:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.random([5, 5]),
     columns=['A1', 'A2', 'A3','A4','A5'])
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第14张图片

df.loc[:,'A1':'A3']=df.round(2)#将A1至A3列保留小数点后两位
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第15张图片

df.round({'A1': 1, 'A3': 2})              #A1列保留小数点后一位、A3列保留小数点后两位

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第16张图片

s1 = pd.Series([1, 0, 2], index=['A1', 'A2', 'A3']) #A1保留1位小数,A2列保留0位小数,A3列保留2位小数。
df.round(s1)                                 #设置Series对象小数位数

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第17张图片

  • 当然,保留小数位数也可以用自定义函数,例如,为DataFrame对象中的各个浮点值保留两位小数,主要代码如下:
df.applymap(lambda x: '%.2f'%x)             #通过自定义函数设置小数位数,返回类型为object

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第18张图片

经过自定义函数处理过的数据将不再是浮点型而是对象型,如果后续计算需要数据,则应先进行数据类型转换。

4.2.2 设置百分比

  • 在数据分析过程中,有时需要百分比数据。那么,利用自定义函数将数据进行格式化处理,处理后的数据就可以从浮点型转换成指定小数位数的百分比数据,主要使用apply()函数与format()函数。
  • 将A列的数据格式转化为百分比数据,程序代码如下:
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:'{:.0%}'.format(x))       #整列保留0位小数,也可以使用map函数
print(df)

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第19张图片

4.2.3 设置千位分隔符

  • 由于业务需要,有时需要将数据格式化为带千位分隔符的数据。那么,处理后的数据将不再是浮点型而是对象型。
  • 将图书馆码洋格式化为带千位分隔符的数据,程序代码如下:
import pandas as pd

data = [['零基础学Python','1月',49768889],['零基础学Python','2月',11777775],['零基础学Python','3月',13799990]]
columns = ['图书','月份','码洋']
df = pd.DataFrame(data=data, columns=columns)
df['码洋']=df['码洋'].apply(lambda x:format(int(x),','))
print(df)

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第20张图片

设置千位分隔符后,对于程序来说,这些数据将不再是数值型,而是数字和逗号组成的字符串,如果由于程序需要再变成数值型就会很麻烦,因此设置千位分隔符要慎重。

4.3 数据分组统计

  • 本节主要介绍分组统计函数groupby()的各种应用。

4.3.1 分组统计groupby()函数

  • 对数据进行分组统计,主要使用DataFrame对象的groupyby()函数,其功能如下:
  • (1)根据给定的条件将数据拆分成组
  • (2)每个组都可以独立应用函数(如求和函数sum()、求平均值函数mean()等)
  • (3)将结果合并到一个数据结构中
  • groupby()函数用于将数据按照一列或多列进行分组,一般与计算函数结合使用,实现数据的分组统计,语法如下:
DataFrame.group(by=None,axis=0,level=None,as_index=True,sort=True,group_keys=True,squeeze=False,observed=False)
  • 参数说明:
    – by:映射、字典或Series对象、数组、标签或标签列表。如果by是一个函数,则对象索引的每个值都调用它;如果传递了一个字典或Series对象,则使用该字典或Series对象值来确定组;如果传递了数组ndarray,则按原样使用这些值来确定组。
    – axis:axis=1表示行,axis=0表示列。默认值为0
    – level:表示索引层级,默认值为None(无)
    – as_index:布尔型,默认值为True,返回以组标签为索引的对象
    – sort:对组进行排序,布尔型,默认值为True
    – group_keys:布尔型,默认值为True,调用apply()函数时,将分组的键添加到索引以标识片段
    – squeeze:布尔型,默认值为False。如果可能,减少返回类型的维度;否则返回一致类型
    – observed:当以石斑鱼分类时,才会使用该参数。如果参数值为True,则仅显示分类石斑鱼的观测值;如果参数值为False,则显示石斑鱼的所有值
    – 返回值:返回DataFrameGroupBy,返回包含有关组的信息的groupby对象。

1.按照一列分组统计

  • 按照图书"一级分类"对订单数据进行分组统计求和,程序代码如下:
import pandas as pd  #导入pandas模块
df=pd.read_csv('JD.csv',encoding='gbk')
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第21张图片

#抽取数据
df1=df[['一级分类','7天点击量','订单预定']]
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第22张图片

df1=df1.groupby('一级分类').sum()       #分组统计求和
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第23张图片

2.按照多列分组统计

  • 多列分组统计,以列表形式指定列。
  • 按照图书"一级分类"和"二级分类"对订单数据进行分组统计求和,主要代码如下:
#抽取数据
df1=df[['一级分类','二级分类','7天点击量','订单预定']]
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第24张图片

df2=df1.groupby(['一级分类','二级分类']).sum()    #分组统计求和
df2

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第25张图片

3.分组并按指定列进行数据计算

  • 前面介绍的分组统计是按照所有列进行汇总计算的,那么如何按照指定类汇总计算呢?
  • 统计各编程语言的7天点击量,首先按"二级分类"分组,然后抽取"7天点击量"列并对该列进行求和运算,主要代码如下:
#抽取数据
df1=df[['二级分类','7天点击量']]
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第26张图片

df1=df1.groupby('二级分类')['7天点击量'].sum()
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第27张图片

4.3.2 对分组数据进行迭代

迭代一级分类的订单数据

  • 通过for循环对分组统计数据进行迭代(遍历分组数据)。
  • 按照"一级分类"分组,并输出每一分类中的订单数据,主要代码如下:
import pandas as pd  #导入pandas模块

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

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第28张图片

for name, group in df1.groupby('一级分类'):
        print(name)
        print(group)
数据库
   一级分类  7天点击量  订单预定
25  数据库     58     2
27  数据库    128    13
移动开发
    一级分类  7天点击量  订单预定
10  移动开发     85     4
19  移动开发     32     1
24  移动开发     85     2
28  移动开发     59     0
编程语言与程序设计
         一级分类  7天点击量  订单预定
0   编程语言与程序设计     35     1
1   编程语言与程序设计     49     0
2   编程语言与程序设计     51     2
3   编程语言与程序设计     64     1
4   编程语言与程序设计     26     0
5   编程语言与程序设计     60     1
6   编程语言与程序设计    227    11
8   编程语言与程序设计    122     3
9   编程语言与程序设计    111     5
11  编程语言与程序设计    165     5
12  编程语言与程序设计    131     1
13  编程语言与程序设计    149    10
15  编程语言与程序设计   1139    79
16  编程语言与程序设计    125     1
18  编程语言与程序设计    149     4
20  编程语言与程序设计     52     1
21  编程语言与程序设计    597    25
22  编程语言与程序设计    474    15
23  编程语言与程序设计     83     3
26  编程语言与程序设计    132     8
29  编程语言与程序设计     27     2
30  编程语言与程序设计    239    13
31  编程语言与程序设计     45     1
32  编程语言与程序设计     28     0
网页制作/Web技术
          一级分类  7天点击量  订单预定
7   网页制作/Web技术    100     7
14  网页制作/Web技术    188     8
17  网页制作/Web技术     57     0
  • 上述代码中,name是groupby()函数中"一级分类"的值,group是分组后的数据。如果groupby()函数对多列进行分组,那么需要在for循环中指定多列。

迭代两级分类的订单数据

  • 迭代"一级分类"和"二级分类"的订单数据,主要代码如下:
import pandas as pd  #导入pandas模块
df=pd.read_csv('JD.csv',encoding='gbk')

#抽取数据
df2=df[['一级分类','二级分类','7天点击量','订单预定']]
df2

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第29张图片

for (key1,key2), group in df2.groupby(['一级分类','二级分类']):
        print(key1,key2)
        print(group)
数据库 Oracle
   一级分类    二级分类  7天点击量  订单预定
25  数据库  Oracle     58     2
数据库 SQL
   一级分类 二级分类  7天点击量  订单预定
27  数据库  SQL    128    13
移动开发 Android
    一级分类     二级分类  7天点击量  订单预定
10  移动开发  Android     85     4
19  移动开发  Android     32     1
24  移动开发  Android     85     2
28  移动开发  Android     59     0
编程语言与程序设计 ASP.NET
         一级分类     二级分类  7天点击量  订单预定
0   编程语言与程序设计  ASP.NET     35     1
20  编程语言与程序设计  ASP.NET     52     1
编程语言与程序设计 C#
         一级分类 二级分类  7天点击量  订单预定
5   编程语言与程序设计   C#     60     1
8   编程语言与程序设计   C#    122     3
26  编程语言与程序设计   C#    132     8
编程语言与程序设计 C++/C语言
         一级分类     二级分类  7天点击量  订单预定
6   编程语言与程序设计  C++/C语言    227    11
9   编程语言与程序设计  C++/C语言    111     5
11  编程语言与程序设计  C++/C语言    165     5
18  编程语言与程序设计  C++/C语言    149     4
29  编程语言与程序设计  C++/C语言     27     2
31  编程语言与程序设计  C++/C语言     45     1
编程语言与程序设计 JSP/JavaWeb
         一级分类         二级分类  7天点击量  订单预定
4   编程语言与程序设计  JSP/JavaWeb     26     0
12  编程语言与程序设计  JSP/JavaWeb    131     1
编程语言与程序设计 Java
         一级分类  二级分类  7天点击量  订单预定
2   编程语言与程序设计  Java     51     2
13  编程语言与程序设计  Java    149    10
16  编程语言与程序设计  Java    125     1
23  编程语言与程序设计  Java     83     3
编程语言与程序设计 PHP
        一级分类 二级分类  7天点击量  订单预定
1  编程语言与程序设计  PHP     49     0
3  编程语言与程序设计  PHP     64     1
编程语言与程序设计 Python
         一级分类    二级分类  7天点击量  订单预定
15  编程语言与程序设计  Python   1139    79
21  编程语言与程序设计  Python    597    25
22  编程语言与程序设计  Python    474    15
30  编程语言与程序设计  Python    239    13
编程语言与程序设计 Visual Basic
         一级分类          二级分类  7天点击量  订单预定
32  编程语言与程序设计  Visual Basic     28     0
网页制作/Web技术 HTML
          一级分类  二级分类  7天点击量  订单预定
14  网页制作/Web技术  HTML    188     8
网页制作/Web技术 JavaScript
         一级分类        二级分类  7天点击量  订单预定
7  网页制作/Web技术  JavaScript    100     7
网页制作/Web技术 WEB前端
          一级分类   二级分类  7天点击量  订单预定
17  网页制作/Web技术  WEB前端     57     0

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

  • Python也可以实现像SQL中的分组聚合运算操作,主要通过groupby()函数和agg()函数实现。

对分组统计结果使用聚合函数

  • 按"一级分类"分组统计"7天点击量""订单预定"的平均值和总和,主要代码如下:
import pandas as pd  #导入pandas模块

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

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第30张图片

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

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第31张图片

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

  • 在上述示例中,还可以针对不同的列使用不同的聚合函数。例如,按“一级分类”分组统计“7天点击量”的平均值和总和、“订单预定”的总和,主要代码如下:
df1.groupby('一级分类').agg({'7天点击量':['mean','sum'],'订单预定':['sum']})

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第32张图片

通过自定义函数实现分组统计

  • 通过自定义函数实现数据分组统计。例如,统计1月份销售数据中,购买次数最多的产品,主要代码如下:
import pandas as pd  #导入pandas模块

df=pd.read_excel('1月.xlsx')  #导入Excel文件
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第33张图片

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

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第34张图片

4.3.4 通过字典和Series对象进行分组统计

1.通过字典进行分组统计

  • 首先创建字典建立对应关系,然后将字典传递给groupby()函数从而实现数据分组统计。
  • 统计各地区销量,业务要求将“北京”“上海”“广州”3个一线城市放在一起统计。那么首先创建一个字典将“北京出库销量”“上海出库销量”“广州出库销量”都对应“北上广”;然后使用groupy()函数进行分组统计。主要代码如下:
import pandas as pd  #导入pandas模块
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
df=pd.read_csv('JD.csv',encoding='gbk')  #导入csv文件
df=df.set_index(['商品名称'])
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第35张图片

#创建字典
mapping={'北京出库销量':'北上广','上海出库销量':'北上广',
         '广州出库销量':'北上广','成都出库销量':'成都',
         '武汉出库销量':'武汉','西安出库销量':'西安'}
df1=df.groupby(mapping,axis=1).sum()
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第36张图片

2.通过Series对象进行分组统计

  • 通过Series对象进行分组统计与字典的方法类似。
  • 首先,创建一个Series对象,主要代码如下:
import pandas as pd  #导入pandas模块
df=pd.read_csv('JD.csv',encoding='gbk')  #导入csv文件
df=df.set_index(['商品名称'])
data={'北京出库销量':'北上广','上海出库销量':'北上广',
         '广州出库销量':'北上广','成都出库销量':'成都',
         '武汉出库销量':'武汉','西安出库销量':'西安',}
s1=pd.Series(data)
s1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第37张图片

df1=df.groupby(s1,axis=1).sum()
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第38张图片

4.4 数据移位

  • 什么是数据移位?例如,分析数据时需要上一条数据怎么办?当然是移动至上一条,从而得到该条数据,这就是数据移位。在Pandas中,使用shift()方法可以获取上一条数据,该方法返回向下移位后的结果,从而得到上一条结果。例如,获取某学生上一次英语成绩,如图4.21所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第39张图片
  • shift()方法是一个非常有用的方法,用于数据位移与其他方法结合,能实现很多难以想象的功能,语法格式如下:
DataFrame.shift(periods=1,freq=1,axis=0)
  • 参数说明:
    – periods:表示移动的幅度,可以是正数,也可以是负数,默认值位1,1表示移动一次。注意这里移动的都是数据,而索引是不移动的,移动之后是没有对应值的,赋值为NaN.
    – freq:可选参数,默认值为None,只适用于时间序列,如果这个参数存在,那么会按照参数值移动时间索引,而数据值没有发生变化。
    – axis:axis=1表示行,axis=0表示列。默认值为0
  • 使用shift()统计学生每周英语测试成绩的升降情况,程序代码如下:
import pandas as pd

data = [110,105,99,120,115]
index=[1,2,3,4,5]
df = pd.DataFrame(data=data,index=index,columns=['英语'])

df['升降']=df['英语']-df['英语'].shift()
print(df)

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第40张图片

  • 这里再扩张下,通过10次周测来看下学生整体英语成绩的升降情况:
import pandas as pd
import matplotlib.pylab as plt

data = [110,105,99,120,115,112,118,120,109,113]
index=[1,2,3,4,5,6,7,8,9,10]
df = pd.DataFrame(data=data,index=index,columns=['英语'])
df['升降']=df['英语']-df['英语'].shift()
print(df)
df['升降'].plot(style='b')
plt.show()

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第41张图片

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第42张图片

  • shift()方法还有很多方面的应用。例如这样一个常见一个情景:分析股票数据,获取的股票数据中有股票的实时价格,也有每日的收盘价“close”,此时需要将实时价格和上一个工作日的收盘价进行对比,那么通过shift()方法就可以轻松解决。shift()方法还可以应用于时间序列,刚兴趣的读者可以再学习完后续章节进行尝试和探索。

4.5 数据转换

  • 数据转换一般包括一列数据转换为多列数据、行列数据、DataFrame转换为字典、DataFrame转换为列表和DataFrame转换为元组等。

4.5.1 一列数据转换为多列数据

  • 一列数据转换为多列数据的情况在日常工作中经常会用到,从各种系统中导出的订单号、名称、地址很多都是复合组成的(即由多项内容组成),那么,这些列在查找、统计、合并时就没办法使用,需要将它们拆分开。例如,地址信息由省市区街道门牌号等信息组成,如果按省、市或区统计数据,就需要将地址信息中的“省”“市”“区”拆分开,此时就应用到了一列数据转多列数据,通常使用以下方法。

1.split()方法

  • Pandas的DataFrame对象中是split()内置方法可以实现分隔字符串,语法如下:
Series.str.split(pat=None,n=1,expand=False)
  • 参数说明:
    – pat:字符串、符号或正则表达式,字符串分割的依据,默认以空格分割字符串。
    – n:整型,分割次数,默认值为-1,0 或-1都将返回所有拆分。
    – expand:布尔型,分割后的结果是否转换为DataFrame,默认值是False。
    – 返回值:系列、索引、DataFrame或多重索引
  • 首先,我们来看一组淘宝销售订单数据(部分数据),如图4.25所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第43张图片
  • 从图4.25中数据得知:不仅“收货地址”是复合的,“宝贝标题”也是复合的,即由多种产品组成。
  • 使用split()方法先对“收货地址”进行分割,程序代码如下:
import pandas as pd

#导入Excel文件指定列数据(“买家会员名”和“收货地址”)
df = pd.read_excel('mrbooks.xls',usecols=['买家会员名','收货地址'])
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第44张图片

#使用split方法分割“收货地址”
series=df['收货地址'].str.split(' ',expand=True)
df['省']=series[0]
df['市']=series[1]
df['区']=series[2]
df1=df.head()
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第45张图片

2.join()方法与split()方法结合

以逗号分隔多种产品数据。
  • 通过join()方法与split()方法结合,以逗号“,”分隔“宝贝标题”,主要代码如下:
import pandas as pd

#导入Excel文件部分列数据(“买家会员名”和“宝贝标题”)
df = pd.read_excel('mrbooks.xls',usecols=['买家会员名','宝贝标题'])
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第46张图片

#使用join方法和split方法分割“宝贝标题”
df = df.join(df['宝贝标题'].str.split(',', expand=True))
df1=df.head()
df1

在这里插入图片描述

  • 从运行结果得知:“宝贝标题”中含有多种产品的数据被拆分开,这样操作便于日后对每种产品的销量进行统计。
  • 将DataFrame中的tuple(元组)类型数据分隔成多列。
对元组数据进行分隔
  • 首先,创建一组包含元组的数据,程序代码如下:
import pandas as pd

df = pd.DataFrame({'a':[1,2,3,4,5], 'b':[(1,2), (3,4),(5,6),(7,8),(9,10)]})
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第47张图片

# apply函数分割元组
df[['b1', 'b2']] = df['b'].apply(pd.Series)
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第48张图片

#或者join方法结合apply函数分割元组
df= df.join(df['b'].apply(pd.Series))
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第49张图片

4.5.2 行列转换

  • 在Pandas处理数据过程中,有时需要对数据进行行列转换或重排,主要使用stack()方法、unstack()方法和pivot()方法,下面介绍这3种方法的应用。

1.stack()方法

  • stack()方法用于将原来的列索引转换成最内层的行索引,转换效果对比示意图如图4.31所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第50张图片
  • stack()方法的语法如下:
DataFrame.stack(level=-1,dropna=True)
  • 参数说明:
    – level:索引层级,定义为一个索引或标签,或索引或标签列表,默认值是-1
    – dropna:布尔型,默认值是True
    – 返回值:DataFrame对象或Series对象
  • 将学生英语成绩进行行列转换,程序代码如下:
import pandas as pd

df=pd.read_excel('grade.xls')      #导入Excel文件
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第51张图片

df = df.set_index(['班级','序号']) #设置2级索引“班级”和“序号”
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第52张图片

df = df.stack()
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第53张图片

2.unstack()方法

  • unstack()方法与stack()方法相反,它是stack()方法的逆操作,即将最内层的行索引转换成列索引,转换效果对比如图4.32所示。

  • unstack()方法的语法如下:
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第54张图片

DataFrame.unstack(level=-1,fill_value=None)
  • 参数说明:
    – level:索引层级,定义为一个索引或标签,或索引或标签列表,默认值为-1
    – fill_value:整型、字符串或字典,如果unstack()方法产生丢失值,则用这个值替换NaN
    – 返回值:DataFrame对象或Series对象。
  • 同样转换学生成绩表,主要代码如下:
import pandas as pd
#设置数据显示的列数和宽度
pd.set_option('display.max_columns',500)
pd.set_option('display.width',1000)
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
df=pd.read_excel('grade.xls',sheet_name='英语2')      #导入Excel文件
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第55张图片

df = df.set_index(['班级','序号','Unnamed: 2'])       #设置多级索引
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第56张图片

df.unstack()

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第57张图片

  • unstack()方法中有一个参数可以指定转换第几层索引,例如,unstack(0)就是把第一层索引转换为列索引,默认是将最内侧索引转换为列索引。

3.pivot()方法

  • pivot()方法针对列的值,即指定某列的值作为行索引,指定某列的值作为列索引,然后再指定哪些列作为索引对应的值。unstack()方法针对索引进行操作,pivot()方法针对值进行操作。但实际上,二者的功能往往可以互相实现。
  • pivot()方法的语法如下:
DataFrame.pivot(index=None,columns=None,values=None)
  • 参数说明:
    – index:字符串或对象,可选参数。列用于创建新DataFrame数据的索引。如果没有,则使用现有索引
    – columns:字符串或对象,列用于创建新的DataFrame的列
    – values:列用于填充新DataFrame的值,如果未指定,则将使用所有剩余的列,结果将具有分层索引
    – 返回值:DataFrame对象或Series对象
  • 使用pivot()方法转换学生成绩表,主要代码如下:
import pandas as pd

df=pd.read_excel('grade.xls',sheet_name='英语3')      #导入Excel文件
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第58张图片

df1=df.pivot(index='序号',columns='班级',values='得分')
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第59张图片

4.5.3 DataFrame转换为字典

  • DataFrame转换为字典主要使用DataFrame对象的to_dict()方法,以索引作为字典的键(key),以列作为字典的值(value)。例如,有一个DataFrame对象(索引为“类别”、列为“数量”),通过to_dict()方法就会生成一个字典,示意图如图4.34所示。如果DataFrame对象包含两列,那么to_dict()方法就会生成一个两层的字典(dict),第一层是列名作为字典的键(key),第二层以索引列的值作为字典的键(key),以列值作为字典的值(value)。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第60张图片
  • 使用to_dict()方法将按“宝贝标题”分组统计后的部分数据转换为字典,程序代码如下:
import pandas as pd
df = pd.read_excel('mrbooks.xls')
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第61张图片

mydict=df1.to_dict()
for i,j in mydict.items():
    print(i,':\t', j)

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第62张图片

4.5.4 DataFrame转换为列表

  • DataFrame转换为列表主要使用DataFrame对象的tolist()方法。
  • 将淘宝销售数据中的“买家会员名”转换为列表,程序代码如下:
import pandas as pd
df =pd.read_excel('mrbooks.xls')
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第63张图片

df1=df[['买家会员名']].head()
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第64张图片

list1=df1['买家会员名'].values.tolist()
for s in list1:
    print(s)

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第65张图片

4.5.5 DataFrame转换为元组

  • DataFrame转换为元组,首先通过循环语句按行读取DataFrame数据,然后使用元组函数tuple()将其转换为元组。
  • 将Excel表中的人物关系部分数据转换为元组,程序代码如下:
import pandas as pd
df = pd.read_excel('fl4.xls')
df

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第66张图片

df1=df[['label1','label2']].head()
df1

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第67张图片

tuples = [tuple(x) for x in df1.values]
for t in tuples:
    print(t)

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第68张图片

4.5.6 Excel转换为HTML网页格式

  • 日常工作中,有时会涉及财务数据的处理,而Excel应用最为广泛,但是对于展示数据来说,Excel并不友好,如果你想用其他格式的文件来向用户展示,那么,HTML网页格式是不错的选择。首先使用read_excel()方法导入Excel文件,然后使用to_html()方法将DataFrame数据导出为HTML格式,这样便实现了Excel转换为HTML格式。
  • 将淘宝部分订单数据转换为HTML网页格式,效果如图4.38所示。
import pandas as pd
df=pd.read_excel('mrbooks.xls',usecols=['买家会员名','宝贝标题']).head()
df.to_html('mrbooks.html',header = True,index = False,encoding='gbk') #编码要也可能是utf8

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第69张图片

4.6 数据合并

  • DataFrame数据合并主要使用merge()方法和concat()方法。

4.6.1 数据合并(merge()方法)

  • Pandas模块的merge()方法是按照两个DataFrame对象列名相同的列进行连接合并,两个DataFrame对象必须具有同名的列。merge()方法的语法如下:
Pandas.merge(right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=False,suffixes=('_x','_y'),copy=True,indicator=False,validate=None)
  • 参数说明:
    – right:合并对象,DataFrame对象或Series对象
    – how:合并类型,参数值可以是left(左合并)、right(右合并)、outer(外部合并)或inner(内部合并),默认值为inner。各个值的说明如下: left:只使用来自左数据集的键,类似于SQL左外部链接,保留键的顺序。right:只使用来自右数据集的键,类似于SQL左外部链接,保留键的顺序。outer:只使用来自两个数据集的键,类似于SQL左外部链接,按字典顺序对键进行排序。inner:只使用来自两个数据集的键的交集,类似于SQL左外部链接,保留左键的顺序。
    – on:标签、列表或数组,默认值为None。DataFrame对象连接的列或索引级别名称。也可以是DataFrame对象长度的数组或数组列表。
    – left_on:标签、列表或数组,默认值为None。要连接的左数据集的列或索引级名称,也可以是左数据集长度的数组或数组列表。
    – right_on:标签、列表或数组,默认值为None。要连接的右数据集的列或索引级名称,也可以是左数据集长度的数组或数组列表。
    – left_index:布尔型,默认值为False。使用左数据集的索引作为连接键。如果是多重索引,则其他数据中的键数(索引或列数)必须匹配索引级别数。
    – right_index:布尔型,默认值为False。使用右数据集的索引作为连接键。
    – sort:布尔型,默认值为False,在合并结果中按字典顺序对连接键进行排序。如果值为False,则连接键的顺序取决于连接类型how参数。
    – suffixes:元组类型,默认值为(‘_x’,‘_y’)。当左侧数据集和右侧数据集的列名相同时,数据合并后将带上’_x’和’_y’后缀。
    – copy:是否复制数据,默认值为True。如果值为False,则不复制数据。
    – indicator:布尔型或字符串,默认值为False。如果值为True,则添加一个列输出名为_Merge的DataFrame对象,其中包含每一行的信息。如果是字符串,将向输出的DataFrame对象中添加包含每一行信息的列,并将列命名为字符型的值。
    – validate:字符串,检查合并数据是否为指定类型。可选参数,其值说明如下:one_to_one或“1:1”:检查合并键在左、右数据集中是否都是唯一的。one_to_many或“1:m”:检查合并键在左、右数据集中是否唯一。many_to_one或“m:1”:检查合并键在右数据集中是否唯一。many_to_many或“m:m”:允许,但不检查。
    – 返回值:DataFrame对象,两个合并对象的数据集。

1.常规合并

  • 假设一个DataFrame对象包含了学生的“语文”“数学”“英语”成绩,而另一个DataFrame对象则包含了学生的“体育”成绩,现将它们合并,示意图如图4.39所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第70张图片
合并学生成绩表
import pandas as pd

df1 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
                    '语文':[110,105,109],
                    '数学':[105,88,120],
                    '英语':[99,115,130]})

df2 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
                    '体育':[34.5,39.7,38]})

df_merge=pd.merge(df1,df2,on='编号')
df_merge

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第71张图片

通过索引合并数据
  • 如果通过索引列合并,则需要设置right_index参数和left_index参数值为True。例如,上述举例,通过列索引合并,主要代码如下:
import pandas as pd

df1 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
                    '语文':[110,105,109],
                    '数学':[105,88,120],
                    '英语':[99,115,130]})

df2 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
                    '体育':[34.5,39.7,38]})

df_merge=pd.merge(df1,df2,left_index=True,right_index=True)
df_merge
Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第72张图片
图4.41
对合并数据去重
  • 从图4.41中的运行结果得知,数据中存在重复列(如编号),如果不想要重复列,可以设置按指定列和列索引合并数据,主要代码如下:
df_merge=pd.merge(df1,df2,on='编号',left_index=True,rith_index=True)
  • 还可以通过how参数解决这一问题。例如,设置该参数值为left,就是让df1保留所有的行列数据,df2则根据df1的行列进行补全,主要代码如下:
df_merge=pd.merge(df1,df2,on='编号',how='left')
import pandas as pd

df1 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
                    '语文':[110,105,109],
                    '数学':[105,88,120],
                    '英语':[99,115,130]})

df2 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
                    '体育':[34.5,39.7,38]})

# df_merge=pd.merge(df1,df2,on='编号',left_index=True,right_index=True)
# df_merge 
df_merge=pd.merge(df1,df2,on='编号',how='left')
df_merge
  • 在jup中注释部分代码会报错,运行结果如下:
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第73张图片

2.多对一的数据合并

  • 多对一是指两个数据集(df1、df2)的共有列中的数据不是一对一的关系,例如,df1中的“编号”是唯一的,而df2中的“编号”由重复的编号,类似这种就是多对一的关系,示意图如图4.43所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第74张图片
根据共有列中的数据进行合并
  • 根据共有列中的数据进行合并,df2根据df2的行列进行补全,程序代码如下:
import pandas as pd

df1 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
                    '学生姓名':['明日同学','高猿员','钱多多']})

df2 = pd.DataFrame({'编号':['mr001','mr001','mr003'],
                    '语文':[110,105,109],
                    '数学':[105,88,120],
                    '英语':[99,115,130],
                    '时间':['1月','2月','1月']})

df_merge=pd.merge(df1,df2,on='编号')
df_merge

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第75张图片

3.多对多的数据合并

  • 多对多是指两个数据集(df1、df2)的共有列中的数据不全是一对一的关系,都有重复数据,例如“编号”,示意图如图4.45所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第76张图片
合并数据并相互补全
  • 根据共有列中的数据进行合并,df2、df1相互补全,程序代码如下:
import pandas as pd

df1 = pd.DataFrame({'编号':['mr001','mr002','mr003','mr001','mr001'],
                    '体育':[34.5,39.7,38,33,35]})

df2 = pd.DataFrame({'编号':['mr001','mr002','mr003','mr003','mr003'],
                    '语文':[110,105,109,110,108],
                    '数学':[105,88,120,123,119],
                    '英语':[99,115,130,109,128]})

df_merge=pd.merge(df1,df2)
df_merge

Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第77张图片

4.6.2 数据合并(concat()方法)

pandas.concat(objs,axis=0,join='outer',ignore_index:bool = False,keys=None,levels=None,names=None,verify_integrity:bool=False,sort:bool=False,copy:bool=True)
  • 参数说明:
    – objs:Series、DataFrame或Panel对象的序列或映射。如果传递一个字典,则排序的键将用作键参数。
    – axis:axis=1表示行,axis=0表示列,默认值为0
    – join:值为inner(内连接)或outer(外连接),处理其他轴上的索引方式。默认值为outer
    – ignore_index:布尔值,默认值为False,保留索引,索引值为0,…,n-1。如果值为True,则忽略索引。
    – keys:序列,默认值为None。使用传递的键作为最外层构建层次索引。如果为多索引,应该使用元组。
    – levels:序列列表,默认值为None。用于构建MultiIndex的特定级别(唯一值);否则,它们将从键推断。
    – names:list列表,默认值为None。结果层次索引中的级别的名称。
    – verify_integrity:布尔值,默认值为False。检查新连接的轴是否包含重复项。
    – sort:布尔值,默认值为True(1.0.0以后版本默认值为False,即不排序)。如果连接为外连接(join=‘outer’),则对未对齐的非连接轴进行排序;如果连接为内连接(join=‘inner’),则该参数不起作用。
    – copy:是否复制数据,默认值为True,如果值为False,则不复制数据。
  • 下面介绍concat()方法不同的合并方式,其中dfs代表合并后的DataFrame对象,df1、df2等代表单个DataFrame对象,result代表合并后的结果(DataFrame对象)。

1.相同字段的表首尾相接

  • 表结构相同的数据将直接合并,表首尾相接,主要代码如下:
dfs=[df1,df2,df3]
result=pd.concat(dfs)
  • 例如,表df1、df2和df3结构相同,如图4.47所示。合并后的效果如图4.48所示。如果想要在合并数据时标记源数据来自哪张表,则需要在代码中加入参数keys,例如表名分别为“1月”“二月”“三月”,合并后的效果如图4.49所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第78张图片
  • 主要代码如下:
result=pd.concat(dfs,keys=['1月','2月','3月'])

2. 横向表合并(行对齐)

  • 当合并的数据列名称不一致时,可以设置参数axis=1,concat()方法将按行对齐,然后将不同列名的两组数据进行合并,缺失的数据用NaN填充,df1和df4合并前后效果如图4.50和图4.51所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第79张图片
  • 主要代码如下:
result=pd.concat([df1,df4],axis=1)

3.交叉合并

  • 交叉合并,需要在代码中加上join()参数,如果值为inner,结果是两张表的交集;如果值为outer,结果是两张表的并集。例如两张表交集,表df1和df4合并前后的效果如图4.52和图4.53所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第80张图片
  • 主要代码如下:
result=pd.concat([df1,df4],axis=1,join="inner")

4.指定表对齐数据(行对齐)

  • 如果指定参数join_axes,就可以指定根据哪张表来对齐数据。例如,根据df4对齐数据,就会保留表df4的数据,然后将表1的数据与之合并,行数不变,合并前后的效果与如图4.54和图4.55所示。
    Pandas统计分析中(数据计算、数据格式化、数据分组统计、数据移位、数据转换、数据合并、数据导出)_第81张图片
  • 主要代码如下:
result=pd.concat([df1,df4],axis=1,join_axes=[df4,index]

4.7 数据导出

4.7.1 导出为.xlsx文件

  • 导出数据为Excel,主要使用DataFrame对象的to_excel()方法,语法如下:
DataFrame.to_excel(excel_writer,sheet_name='Sheet1',na_rep='',float_format=None,columns=None,header=True,index=True,index_label=None,startrow=0,startcol=0,engine=None,merge_cells=True,encoding=None,inf_rep='inf',verbose=True,freeze_panes=None)
  • excel_writer:字符串或ExcelWriter对象。
  • sheet_name:字符串,默认值为Sheet1,包含DataFrame的表的名称
  • na_rep:字符串,默认值为’'。缺失数据的表示方式
  • float_format:字符串,默认值为None,格式化浮点数的字符串
  • columns:序列,可选参数,要编辑的列
  • header:布尔型或字符串列表,默认值为True。列名称,如果给定字符串列表,则表示它是列名称的别名
  • index:布尔型,默认值为True,行名(索引)
  • index_label:字符串或序列,默认值为None。如果需要,可以使用索引列的列标签;如果没有给出,标题和索引为True,则使用索引名称;如果数据文件使用多重索引,则需要使用序列。
  • startrow:指定从哪一行开始写入数据
  • startcol:指定从哪一列写入数据
  • engine:字符串,默认值为None,指定要使用的写引擎,如openyxl或xlsxwriter。也可以通过io.excel.xlsx.writer、io.excel.xls.writer和io.excel.xlsx.writer进行设置。
  • merge_cells:布尔型,默认值为True
  • encoding:指定Excel文件的编码格式,默认值为None
  • inf_rep:字符串,默认值为“正”,表示无穷大
  • verbose:布尔型,默认值为True。在错误日志中显示更多信息
  • freeze_panes:整数的元组,长度为2,默认值为None。指定要冻结的行列

将处理后的数据导出为Excel文件

  • 将数据合并后的结果导出为Excel文件,主要代码如下:
import pandas as pd

df1 = pd.DataFrame({'编号':['mr001','mr002','mr003','mr001','mr001'],
                    '体育':[34.5,39.7,38,33,35]})

df2 = pd.DataFrame({'编号':['mr001','mr002','mr003','mr003','mr003'],
                    '语文':[110,105,109,110,108],
                    '数学':[105,88,120,123,119],
                    '英语':[99,115,130,109,128]})

df_merge=pd.merge(df1,df2)
df_merge.to_excel('merge.xlsx')
df1.to_excel('df1.xlsx',sheet_name='df1')

4.7.2 导出为.csv文件

  • 导出数据为.csv文件,主要使用DataFrame对象的to_csv方法,语法如下:
DataFrame.to_csv(path_or_buf=None,sep=',',na_rep='',float_format=None,columns=None,header=True,index=True,index_label=None,mode='w',encoding=None,compression='infer',quoting=None,quotechar="",line_terminator=None,chunksize=None,data_format=None,doublequote=True,escapechar=None,decimal='.',errors='strict')
  • path_or_buf:要保存的路径及文件名
  • sep:分隔符,默认值为","
  • na_rep:指定空值的输出方式,默认值为空字符串
  • float_format:浮点数的输出方式,要用双引号括起来
  • columns:指定要导出的列,用列名列表表示,默认值为None
  • header:是否输出列名,默认值为True
  • index:布尔型,默认值为True,行名(索引)
  • index_label:索引列的列名,默认值为None
  • mode:Python写入模式,默认值为w
  • encoding:编码格式,默认值为utf8
  • compression:压缩模式,默认值为infer
  • quoting:导出.csv文件是否用引号,默认值为0,表示不加双引号;如果值为1,则每个字段都会加上引号,数值也会被当作字符串看待
  • quotechar:引用字符,当quoting=1时可以指定引号字符为双引号(“”)或单引号(‘’)
  • line_terminator:换行符,默认值为\n
  • chunksize:一次写入.csv文件的行数,当DataFrame对象数据特别大时需要分批写入
  • data_format:日期输出格式
  • doublequote:是否添加双引用符,默认值为True
  • escapechar:设置转义字符
  • decimal:可识别十进制分隔符的字符
  • errors:指定如何处理编码和解码错误,默认值为strict(严格的)

将处理后的数据导出为.csv文件

import pandas as pd

data = [['a',110,105,99],['b',105,88,115],['c',109,120,130],['d',112,115]]
index = [1,2,3,4]
columns = ['name','语文','数学','英语']
df = pd.DataFrame(data=data, index=index, columns=columns)
print(df)

#相对位置,保存在程序所在路径下
df.to_csv('Result1.csv',encoding='gb2312')
#绝对位置
df.to_csv('d:\Result.csv',encoding='gb2312')
#分隔符。使用问号(?)分隔符分隔需要保存的数据
df.to_csv('Result2.csv',sep='?',encoding='gb2312')
#替换空值,缺失值保存为NA
df.to_csv('Result3.csv',na_rep='NA',encoding='gb2312') 
#格式化数据,保留两位小数
df.to_csv('Result4.csv',float_format='%.2f',encoding='gb2312')
#保留某列数据,保存索引列和name列
df.to_csv('Result5.csv',columns=['name'],encoding='gb2312')
#是否保留列名,不保留列名
df.to_csv('Result6.csv',header=0,encoding='gb2312')
#是否保留行索引,不保留行索引
df.to_csv('Result7.csv',index=0,encoding='gb2312')

4.7.3 导出多个Sheet

  • 导出多个Sheet,应该先使用pd.ExcelWriter()方法打开一个Excel文件,然后再使用to_excel()方法导出指定的Sheet。

导处Excel中多个Sheet页的数据

  • 导出指定Sheet页中的数据,主要代码如下:
import pandas as pd

data = [['a',110,105,99],['b',105,88,115],['c',109,120,130],['d',112,115]]
index = [1,2,3,4]
columns = ['A','语文','数学','英语']
df1 = pd.DataFrame(data=data, index=index, columns=columns)

df1.to_excel('df1.xlsx',sheet_name='df1')
work=pd.ExcelWriter('df2.xlsx')  #打开一个Excel文件
df1.to_excel(work,sheet_name='df2')
df1['A'].to_excel(work,sheet_name='df3')
work.save()

你可能感兴趣的:(python自动化,利用Python进行数据分析,pandas,python,数据分析)