【python数据分析09】——Pandas统计分析(DataFrame常用操作)

前言

DataFrame是最常用的pandas对象。完成数据读取后,数据就以DataFrame数据结构存储在内存中,但此时并不能直接开始统计分析工作,需要使用DataFrame的属性与方法对数据的分布、大小等基本的数据状况有一个了解。只有对数据基本状况有了一个深度的了解,才能够依据数据的状况,进行量身定制的统计分析。

1 查看DataFrame的常用属性

DataFrame基础属性有values、index、columns和dtypes,分别可以获取元素、索引、列名和类型。
例如,订单性详情表的基本属性如下:

from sqlalchemy import create_engine
import pandas as pd
## 创建数据库连接
## 创建一个mysql连接器,用户名为root,密码为1234
username = 'root'  # 替换为你的数据库用户名
password = '1234'  # 替换为你的数据库密码
host = 'localhost'          # 数据库地址
database = 'testdb'  # 数据库名称
 
# 创建数据库连接
engine = create_engine(f'mysql+pymysql://{username}:{password}@{host}/{database}')
detail= pd.read_sql_table('meal_order_detail1',con = engine)
print('订单详情表的索引为:', detail.index)

print('订单详情表的所有值为:','\n', detail.values)
print('订单详情表的列名为:','\n', detail.columns)
print('订单详情表的数据类型为:','\n', detail.dtypes)

输出:
在这里插入图片描述
除上述4个基本属性,size、nidm和shape这几个属性能够获取DataFrame的元素个数、维度数和数据形状(行列数目),如下所示:

## 查看DataFrame的元素个数
print('订单详情表的元素个数为:', detail.size)
print('订单详情表的维度数为:', detail.ndim) ## 查看DataFrame的维度数
print('订单详情表的形状为:', detail.shape) ## 查看DataFrame的形状

输出:
在这里插入图片描述
另外,T属性能够实现DataFrame的转置(行列转换)。在某些特殊场景下,某些函数方法只能作用于列或者行,此时就可以试着用转置解决问题,如下:

print('订单详情表转置前形状为:',detail.shape)
print('订单详情表转置后形状为为:',detail.T.shape)

输出:
在这里插入图片描述

2 增删改查DataFrame数据

DataFrame作为一种二维数据表结构,能够像数据库一样实现增删改查操作,如添加一行,删除一行,添加一列,删除一列等。

2.1 查DataFrame数据

2.1.1 基本查看方式

DataFrame的单列数据为一个Series,根据DataFrame的定义,DataFrame是一个带有标签的二维数组,每个标签相当于每一列的列名。

使用字典访问内部数据的方式访问DataFrame单列数据

## 使用访问字典方式取出orderInfo中的某一列
order_id = detail['order_id']
print('订单详情表中的order_id的形状为:','\n',order_id.shape)

输出:
在这里插入图片描述
使用访问属性的方式访问DataFrame单列数据

## 使用访问属性方式取出orderInfo中的菜品名称列
dishes_name = detail.dishes_name
print('订单详情表中的dishes_name的形状为:',dishes_name.shape)

输出:
在这里插入图片描述
以上两种方法均可以获得DataFrame中的某一列数据,但是使用属性的方法访问数据并不建议使用。因为多数时候数据的列名为英文,以属性方式访问某一列的形式和DataFrame属性访问,其方法和使用的格式相同,难免存在部分列名和pandas提供的方法相同,这时候会引起程序混乱。

访问DataFrame中某一列的某几行时,单独一列的DataFrame可以视为一个Series,而访问一个Series和访问一个一维的ndarray基本相同。

DataFrame单列多行数据获取

dishes_name5 = detail['dishes_name'][:5]
print('订单详情表中的dishes_name前5个元素为:','\n',dishes_name5)

输出:
在这里插入图片描述
访问DataFrame多列的多行数据

orderDish = detail[['order_id','dishes_name']][:5]
print('订单详情表中的order_id和dishes_name前5个元素为:', '\n',orderDish)

在这里插入图片描述

如果只需要访问DataFram某几行数据,则实现方式和上述的访问多列多行相似,选择所有列,使用“:”代替即可

order5 = detail[:][1:6]
print('订单详情表的1-6行元素为:','\n',order5)

输出:
在这里插入图片描述
通过DataFrame提供的方法head和tail也可以得到多行数据,但是用这两种方法得到的数据都是从开始或者末尾获取的连续数据。
如下:

print('订单详情表中前五行数据为','\n',detail.head())
print('订单详情表中后五个元素为:','\n',detail.tail())

输出:
在这里插入图片描述
在这里插入图片描述
上述代码中的head和tail方法使用的都是默认参数,所以访问的是前。后5行,只要在方法后的()中输入访问行数,即可实现目标行数的查看。

2.1.2 DataFrame的loc、iloc访问方式

pandas提供了loc和iloc访问方式,更加灵活的实现数据访问。

  • loc方法:是针对DataFrame索引名称的切片方法,如果传入的不是索引名称,那么切片操作将无法执行。利用该方法可以实现所有单层索引切片操作。loc方法的使用方法如下:
    DataFrame.loc[行索引名称或条件,列索引名称]
  • iloc方法:iloc接受的必须是行索引和列索引的位置,方法如下:
    DataFrame.iloc[行索引名位置,列索引位置]

使用loc和iloc实现单列切片

dishes_name1 = detail.loc[:,'dishes_name']
print('使用loc提取dishes_name列的size为:', dishes_name1.size)

dishes_name2 = detail.iloc[:,3]
print('使用iloc提取第3列的size为:', dishes_name2.size)

输出:
在这里插入图片描述
使用loc方法和iloc实现多列切片,其原理就是将多列的列名或者位置作为一个列表或者数据传入,如下:

orderDish1 = detail.loc[:,['order_id','dishes_name']]
print('使用loc提取order_id和dishes_name列的size为:', orderDish1.size)

orderDish2 = detail.iloc[:,[1,3]]
print('使用iloc提取第1和第3列的size为:', orderDish2.size)

输出:
在这里插入图片描述
使用loc。iloc方法可以取出DataFrame中的任意数据,如下:

print('列名为order_id和dishes_name的行名为3的数据为:\n',
      detail.loc[3,['order_id','dishes_name']])
print('列名为order_id和dishes_name行名为2,3,4,5,6的数据为:\n',
      detail.loc[2:6,['order_id','dishes_name']])
print('列位置为1和3行位置为3的数据为:\n',detail.iloc[3,[1,3]])
print('列位置为1和3行位置为2,3,4,5,6的数据为:\n',
      detail.iloc[2:7,[1,3]])

输出:
在这里插入图片描述
在使用loc方法时,如果内部传入的行索引名称为一个区间,则前后均为闭区间;使用iloc方法时,如果内部传入的行索引位置或列索引位置为区间,则为前闭后开区间

loc内部还可以传入表达式,结果会返回满足表达式的所有值。

## loc内部传入表达式
print('detail中order_id为458的dishes_name为:\n',
     detail.loc[detail['order_id']=='458',
     ['order_id','dishes_name']])

输出:
在这里插入图片描述

print('detail中order_id为458的第1,5列数据为:\n',
     detail.iloc[detail['order_id']=='458',[1,5]])

输出:
在这里插入图片描述
上述出错,是因为此处条件返回的为一个布尔值Series,而iloc可以接收的数据烈性并不包括Series。根据Series的构成,只要取出Series的values即可。

print('detail中order_id为458的第1,5列数据为:\n',
      detail.iloc[(detail['order_id']=='458').values,[1,5]])

输出:
在这里插入图片描述
总的来说,loc更加灵活多变,可读性更高;iloc代码简洁,可读性不高。

2.2 改DataFrame数据

更改DataFrame中的数据的原理是将这部分数据提取出来,重新赋值为新的数据,如下:

##将order_id为458的,变换为45800
detail.loc[detail['order_id']=='458','order_id'] = '45800'
print('更改后detail中order_id为458的order_id为:\n',
     detail.loc[detail['order_id']=='458','order_id'])
print('更改后detail中order_id为45800的order_id为:\n',
     detail.loc[detail['order_id']=='45800','order_id'])

输出:
在这里插入图片描述
注意:数据更改时直接对DataFrame原数据更改,操作无法撤销。如果做出更改,则需要对更改条件进行确认或对数据备份。

2.3 增添数据

添加一列只需要新建一个列索引,并对该索引下的数据进行赋值操作即可。

为DataFrame新增一列非定值

detail['payment'] =  detail['counts']*detail['amounts']
print('detail新增列payment的前五行为:','\n',
      detail['payment'].head())

输出:
在这里插入图片描述
如果新增一列值是相同的,则直接赋值一个常量即可。例如:

detail['pay_way'] = '现金支付'
print('detail新增列pay_way的前五行为:','\n',
      detail['pay_way'].head())

输出:
在这里插入图片描述

2.4 删除数据

删除某列或某行数据是drop方法,用法如下:

DataFrames.drop(labels,axix=0,level=None,inplace=False,errors='raise')

参数说明:

参数说明
labels接收string或array,代表删除的行或列的标签。无默认
axix接收0或1,操作的轴向,默认为0
level接收int或者索引名,代表标签所在级别,默认为None
inplace接收boolean,代表操作是否对原数据生效,默认为False

例如:

print('删除pay_way前deatil的列索引为:','\n',detail.columns)
detail.drop(labels = 'pay_way',axis = 1,inplace = True)
print('删除pay_way后detail的列索引为:','\n',detail.columns)

输出:
在这里插入图片描述
要删除某行数据,只需要将drop方法参数中的labels参数换成对应的行索引,将axis=0即可。

print('删除1-10行前detail的长度为:',len(detail))
detail.drop(labels = range(1,11),axis = 0,inplace = True)
print('删除1-10行后detail的列索引为:',len(detail))

输出:
在这里插入图片描述

3 描述分析DataFrame数据

描述性统计是用来概括、表述事物整体状况,以及事物间关联、类属关系的统计方法,通过几个统计值可表示一组数据的集中趋势和离散程度。

3.1 数值型特征的描述性统计

数值型特征的描述性统计包括:数据的完整情况、最大值、均值、中位数、最大值、四分位数、极差、标准差、方差、协方差和变异系数等

numpy库中已经有很多统计函数,pandas库基于numpy,自然也可以用这些统计函数对数据进行描述性统计。例如

通过函数求菜品销售价格的均值

print('订单详情表中amount(价格)的平均值为:', detail['amounts'].mean())

输出:
在这里插入图片描述
同时,pandas还提供了一个叫做describe的方法,能够一次性得出所有数值型特征的非空值数目、均值、四分位数和标准层。例如:

print('订单详情表counts和amounts两列的描述性统计为:\n',
      detail[['counts','amounts']].describe())

输出:
在这里插入图片描述
另外,pandas还提供了与统计相关的主要方法,如下表

方法说明方法说明
min最小值max最大值
mean均值ptp极差
median中位数std标准差
var方差cov协方差
sem标准误差mode众数
skew样本偏度kurt样本峰度
quantile四分位数count非空值数目
descirbe描述统计mad平均绝对高差

3.2 类别型特征的描述性统计

类别型特征的分布状况,可以使用频数统计表,pandas库中实现频数统计的方法为values_counts
对菜品销售数据中的菜品名aname进行频数统计,取排名靠前的10条

print('订单详情表dishes_name频数统计结果前10为:\n',
      detail['dishes_name'].value_counts()[0:10])

输出:
在这里插入图片描述
除上述频率分布表外,pandas提供了category类,可以使用astype方法将目标特征的数据类型转换为category类型。如下:

detail['dishes_name'] = detail['dishes_name'].astype('category')
print('订单信息表dishes_name列转变数据类型后为:',detail['dishes_name'].dtypes)

输出:
在这里插入图片描述
describe方法除了支持传统数值型数据以外,还能够支持对category类型的数据进行描述性统计,4个统计量分别为列非空元素的数目、类别的数目、数目最多的类别和数目最多类别的数目,如下:

print('订单信息表dishes_name的描述统计结果为:\n',
      detail['dishes_name'].describe())

输出:
在这里插入图片描述

4 小案例

4.1 查看餐饮数据的大小和维度

查看餐饮数据基本信息,主要从数据的维度、形状、元素的个数3个方面进行

from sqlalchemy import create_engine
import pandas as pd
# 数据库连接配置
username = 'root'  # 替换为你的数据库用户名
password = '1234'  # 替换为你的数据库密码
host = 'localhost'          # 数据库地址
database = 'testdb'  # 数据库名称
 
# 创建数据库连接
engine = create_engine(f'mysql+pymysql://{username}:{password}@{host}/{database}')

detail = pd.read_sql_table('meal_order_detail1',
      con = engine)
order = pd.read_table('C:/Users/Lenovo/jupyter/data/meal_order_info.csv',
      sep = ',',encoding = 'gbk')
user = pd.read_excel('C:/Users/Lenovo/jupyter/data/users.xlsx')
print('订单详情表的维度为:', detail.ndim)
print('订单信息表的维度为:', order.ndim)
print('客户信息表的维度为:', user.ndim)

print('订单详情表的形状为:', detail.shape)
print('订单信息表的形状为:', order.shape)
print('客户信息表的形状为:', user.shape)

print('订单详情表的元素个数为:', detail.size)
print('订单信息表的元素个数为:', order.size)
print('客户信息表的元素个数为:', user.size)

输出:
在这里插入图片描述

4.2 统计餐饮菜品销售状况

餐饮菜品的销售信息统计主要指统计菜品的销量、菜品的平均售价和热销菜品等信息。

print('订单详情表counts和amounts两列的描述性统计为:\n',
      detail.loc[:, ['counts','amounts']].describe())

detail['order_id'] = detail['order_id'].astype('category')
detail['dishes_name'] = detail['dishes_name'].astype('category')
print('''订单信息表order_id(订单编号)与dishes_name(菜品名称)
的描述性统计结果为:''', '\n',
detail[['order_id','dishes_name']].describe())

输出:
在这里插入图片描述

4.3 剔除全为空值或者所有元素取值相同的列

## 定义一个函数去除全为空值的列和标准差为0的列
def dropNullStd(data):
    beforelen = data.shape[1]
    colisNull = data.describe().loc['count'] == 0
    for i in range(len(colisNull)):
        if colisNull[i]:
            data.drop(colisNull.index[i],axis = 1,inplace =True)

    stdisZero = data.describe().loc['std'] == 0
    for i in range(len(stdisZero)):
        if stdisZero[i]:
            data.drop(stdisZero.index[i],axis = 1,inplace =True)
    afterlen = data.shape[1]
    print('去除的列的数目为:',beforelen-afterlen)
    print('去除后数据的形状为:',data.shape)
dropNullStd(detail)

##使用dropNullStd函数对订单信息表操作
dropNullStd(order)

##使用dropNullStd函数对客户信息表操作
dropNullStd(user)

输出:
在这里插入图片描述

  • 26
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值