机器学习 —— 数据分析与图表绘制

news2024/11/28 8:34:33

本文使用工具
       Anaconda下载安装与使用
       Jupyter Notebook的使用

本文使用数据集
      机器学习实验所需内容.zip


    以朝阳医院2018年销售数据为例,目的是了解朝阳医院在2018年里的销售情况,这就需要知道几个业务指标,本次的分析目标是从销售数据中分析出以下业务指标:
(1)业务指标1:月均消费次数
    月均消费次数 = 总消费次数 / 月份数(同一天内,同一个人所有消费算作一次消费)
(2)业务指标2:月均消费金额
    月均消费金额 = 总消费金额 / 月份数
(3)客单价
    客单价 = 总消费金额 / 总消费次数
(4)消费趋势(可视化展示,并根据可视化结果给出下属问题分析得出的结论)
    a、分析每天的消费金额
    b、分析每月的消费金额
    c、分析药品销售情况(截取销售数量最多的前十种药品,并用条形图展示结果)
    数据分析基本过程 数据分析基本过程包括:获取数据、数据清洗、构建模型、数据可视化以及消费趋势分析。

(一)数据获取

1. 读取数据,并且返回表格的前几行数据

import pandas as pd
# 读取数据(最好使用 object 类型读取)
data = pd.read_excel("朝阳医院2018年销售数据.xlsx", dtype="object")
# 通过panda模块内置的read_excel方法读取格式为.xlsx的excel表格内容,以object类型读取,还有一个为read_csv方法读取的是格式为.csv的Excel表格
data.head()# 返回data的前几行数据,默认为前五行,括号内部可填入数字表示显示几行数据

在这里插入图片描述图1:读取数据,并且返回表格的前几行数据

2. 修改为 DataFrame 格式,并且查看数据的形状

# 修改为 DataFrame 格式
dataDF = pd.DataFrame(data)# 定义一个dataDF来存储修改为DataFrame格式的数据
# DataFrame是一种表格型的数据结构。它的每一列可以是不同的值类型(例如布尔型、数值型、字符串等),
# 此外它既有行索引index,又有列索引columns。我们可以将它看成是由Series组成的字典(将每一列看成是一个Series)。
 
 # 查看数据的形状,即几行几列
print(dataDF.shape)# 形状(shape) 打印出数据的形状
print("dataDF.index:{}".format(dataDF.index))# 行索引(index) 打印出数据的参数

在这里插入图片描述图2:修改为 DataFrame 格式,并且查看数据的形状

3. 查看每一列的列表头内容

# 查看每一列的列表头内容
print("dataDF.columns:{}".format(dataDF.columns))# 打印出数据的每个列表头的说明,以及数据的类型
print(dataDF.columns)# 列索引(columns)

在这里插入图片描述图3:查看每一列的列表头内容

4. 查看每一列数据统计数目

# 查看每一列数据统计数目
# count()返回每一列中的非空值的个数。
print("dataDF计数:{}".format(dataDF.count()))

在这里插入图片描述图4:查看每一列数据统计数目

(二)数据分析

        数据清洗过程包括:选择子集、列名重命名、缺失数据处理、数据类型转换、数据排序及异常值处理。

1. 列名重命名

# 使用 rename 函数,把"购药时间" 改为 "销售时间"
dataDF.rename(columns={"购药时间": "销售时间"}, inplace=True)
# 通过rename函数对于数据的列名(columns)里面的购药时间改成销售时间,inplace:是否替换,默认为False。
# inplace为False时返回修改后结果,变量自身不修改。inplace为True时返回None,变量自身被修改。
print("dataDF.columns:{}".format(dataDF.columns))
# 打印出修改后的数据结果,以及数据类型

在这里插入图片描述

图5:列名重命名

2. 缺失值处理

# 删除缺失值之前
# 打印出数据缺失值之前的类型(几行几列)
print("删除缺失值之前dataDF.shape:{}".format(dataDF.shape))
# 使用dropna函数删除缺失值
# 因为Excel中的空的cell读入pandas中是空值(NaN),这个NaN是个浮点类型,一般当作空值处理,所以要先去除NaN再进行分隔字符串。
dataDF = dataDF.dropna()# 通过内置的dropna函数删除缺失的数据
# 删除缺失值之后
# 打印出缺失的数据被删除后的数据类型(几行几列)
print("删除缺失值之后dataDF.shape:{}".format(dataDF.shape))
# 将字符串转为浮点型数据
# 将销售数量,应收金额,实收金额的数据类型由字符串转变为浮点数类型(float)
# 数据类型转换:astype函数:字符串转换成数值(浮点型)
dataDF["销售数量"] = dataDF["销售数量"].astype("f8")
dataDF["应收金额"] = dataDF["应收金额"].astype("f8")
dataDF["实收金额"] = dataDF["实收金额"].astype("f8")
print("dataDF.dtypes:{}".format(dataDF.dtypes))
 

在这里插入图片描述

图6:缺失值处理

3. 数据类型转换之自定义函数

# 将日期进行分割
# 自定义函数::分隔销售口期,获取销售日期
# 输入:timeColSer销售时间这一列,是个Series数据类型
# 输出:分割后的时间,返回的也是Series数据类型
def splitsaletime(timeColser):
    timelist = []
    for t in timeColser:# [0]表示选取的分片,这里表示切割完后选取第一个分片
        timelist.append(t.split(" ")[0])# split(" ")分割
        timeser = pd.Series(timelist)# 将列表转行为一维数据Series类型
    return timeser

在这里插入图片描述

图7:数据类型转换之自定义函数

4. 数据类型转换之调用自定义函数

# 获取"销售时间"这一列数据
t = dataDF.loc[:, "销售时间"]# 获取销售时间这一列数据的数据存储到t里面
# 调用函数去除星期,获取日期
timeser = splitsaletime(t)# 对字符串进行分割,获取销售日期
# 修改"销售时间"这一列日期
dataDF.loc[:, "销售时间"] = timeser
print(dataDF.head())

在这里插入图片描述

图8:数据类型转换之调用自定义函数

5. 数据类型转换

# 字符串转日期
# errors='coerce'如果原始数据不符合日期的格式,转换后的值为NaT
dataDF.loc[:, "销售时间"] = pd.to_datetime(dataDF.loc[:, "销售时间"], errors='coerce')
# 将原本是字符串的日期类型转变成日期datatime类型的,pandas提供了一个可选的参数errors,
# 传入errors=‘coerce’,pandas遇到不能转换的数据就会赋值为NaN(Not a Number)
print("dataDF.dtypes:{}".format(dataDF.dtypes))

在这里插入图片描述

图9:数据类型转换

6. 删除空值

# 转换日期过程中不符合日期格式的数值会被转换为空值None,
 # 这里删除为空的行
dataDF = dataDF.dropna()
print("dataDF.shape:{}".format(dataDF.shape))
# 按销售时间进行升序排序
dataDF = dataDF.sort_values(by='销售时间', # by :按几列排序
                            ascending=True)# ascending=True为升序,ascending=False为降序
print("dataDF.head():{}".format(dataDF.head()))
# 重置索引(index)
dataDF = dataDF.reset_index(drop=True)
# 通过reset进行索引的重置,drop=True表示删除用作新索引的列,也就是删除被用作索引的第一列

在这里插入图片描述

图10:删除空值

7. 删除异常值

# 查看描述统计信息
# 描述指标:“销售数量”值不能小于0
print(dataDF.describe())
# 删除异常值:通过条件判断筛选出数据
# 将"销售数量"这一列中小于0的数排除掉
pop = dataDF.loc[:, "销售数量"] > 0
dataDF = dataDF.loc[pop, :]

在这里插入图片描述

图11:删除异常值

8. 删除重复数据

# 排除异常值后再次查看描述统计信息
print(dataDF.describe())
# 计算总消费次数
# 删除重复数据
kpi1_Df = dataDF.drop_duplicates(subset=['销售时间', '社保卡号'])
# drop_duplicates是pandas内的一个删除函数,subset:表示要进去重的列名,默认为 None。

在这里插入图片描述

图12:删除重复数据

(三)构建模型及数据可视化

        数据清洗完成后,需要利用数据构建模型(就是计算相应的业务指标),并用可视化的方式呈现结果。

1. 计算总消费次数

# 计算总消费次数
# 总消费次数:同一天内,同一个人发生的所有消费算作一次消费
# 有多少行
totall = kpi1_Df.shape[0]# 统计有多少行的数据(总消费次数)
print('总消费次数:', totall)
# 按销售时间升序排序
kpi1_Df = kpi1_Df.sort_values(by='销售时间', ascending=True)
# 对销售时间这一列进行升序排序,ascending=True为升序,ascending=False为降序
# 重命名行名(index)
kpi1_Df = kpi1_Df.reset_index(drop=True)

在这里插入图片描述

图13:计算总消费次数

2. 业务指标1-3(月均消费次数、月均消费金额、客单价)

# 获取时间范围
# 最小时间值
startTime = kpi1_Df.loc[0, '销售时间']
# 最大时间值
endTime = kpi1_Df.loc[totall - 1, '销售时间']
# 计算天数
daysI = (endTime - startTime).days
# 月份数:运算符"//"表示取整除,返回商的整数部分
monthsI = daysI // 30
print('月份数:', monthsI)

# 计算月均消费次数
# 业务指标1:月均消费次数=总消费次数 / 月份数
kpi1_I = totall // monthsI
print('业务指标1:月均消费次数=', kpi1_I)

# 总消费金额
totalMoneyF = dataDF.loc[:, '实收金额'].sum()
# 月均消费金额
# 业务指标2:月均消费金额 = 总消费金额 / 月份数
monthMoneyF = totalMoneyF / monthsI
print('业务指标2:月均消费金额=', monthMoneyF)

# 业务指标3:客单价 = 总消费金额 / 总消费次数
# 客单价(per customer transaction)是指商场(超市)每一个顾客平均购买商品的金额,客单价也即是平均交易金额。
pct = totalMoneyF / totall
print('业务指标3:客单价=', pct)

在这里插入图片描述

图14:月均消费次数、月均消费金额、客单价

3. 业务指标:消费趋势(可视化展示)

# 业务指标:消费趋势,画图-折线图
import matplotlib.pyplot as plt
from pylab import mpl # 画图时用于显示中文字符
mpl.rcParams['font.sans-serif'] = ['SimHei']   # SimHei是黑体的意思
# 在操作之前先复制一份数据,防止影响清洗后的数据
groupDf = dataDF
# 重命名行(index)为销售时间所在列的值
groupDf.index = groupDf['销售时间']
groupDf.head()

在这里插入图片描述

图15:重命名行(index)为销售时间所在列的值

4. a、分析每天的消费金额

# a、分析每天的消费金额
plt.figure(figsize=(20,10))# 设置画布大小
plt.plot(groupDf['实收金额'])
# plt.plot(x, y, format_string, **kwargs)可以绘制点和线, 并且对其样式进行控制
# x               X轴数据,列表或数组,可选
# y               Y轴数据,列表或数组
# format_string   控制曲线的格式字符串,可选
# kwargs          第二组或更多(x,y,format_string),可画多条曲线
plt.title('按天消费金额(ZShiJ)')# 设置图像标题
plt.xlabel('时间')    # 设置x轴的标签文本
plt.ylabel('实收金额')# 设置y轴的标签文本
plt.savefig("day.png")# 保存图片
plt.show()            # 把图像显示出来。

在这里插入图片描述图16:a、分析每天的消费金额

在这里插入图片描述
图17:按天消费金额

        分析:由图17按天消费金额,可以看出,每天的消费金额有所不同,但是除了极个别天会出现消费的金额较大,大部分人消费情况基本都在500元以内。

5. b、分析每月的消费金额

# b、分析每月的消费金额
# 将销售时间聚合按月分组
gb = groupDf.groupby(groupDf.index.month)
print(gb)

图18:b、分析每月的消费金额

图18:b、分析每月的消费金额

6. 描绘按月消费金额图

# 描绘按月消费金额图
# 对进行按月份分组好数据进行求和,从而看到每个月份的销售数量,应收金额,实收金额的数据和
monthDF = gb.sum()
print(monthDF)
# plt.figure(figsize=(8,7))# 设置画布大小
plt.plot(monthDF['实收金额'])# 根据实收金额绘制按月消费金额图的线图
plt.title('按月消费金额(ZShiJ)')# 设置图像标题
plt.xlabel('时间')      # 设置x轴的标签文本
plt.ylabel('实收金额')  # 设置y轴的标签文本
plt.savefig("month.png")# 保存图片
plt.show()              # 把图像显示出来。

在这里插入图片描述

图19:描绘按月消费金额图

在这里插入图片描述

图20:按月消费金额

        分析:由图20按月消费金额的结果显示,我们可以看出7月消费金额最少,我认为这是因为7月份的数据不完整,所以不具参考价值。

        1月、4月、5月和6月的月消费金额差异不大,2月和3月的消费金额迅速降低,这可能是2月和3月处于春节期间,大部分人都回家过年的原因。

7. c、分析药品销售情况(截取销售数量最多的前十种药品,并用条形图展示结果)

# c、分析药品销售情况(截取销售数量最多的前十种药品,并用条形图展示结果)
# 聚合统计各种药品的销售数量
# 对“商品名称”和“销售数量”这两列数据进行聚合为Series形式
medicine = groupDf[['商品名称','销售数量']]
# groupby按照商品名称进行分组,算出商品名称对应相应的销售数量
bk = medicine.groupby('商品名称')[['销售数量']]
# 按照商品名称对药品的销售数量进行求和
re_medicine = bk.sum()

在这里插入图片描述

图21:c、分析药品销售情况

8. 降序排序截取销售数量最多的十种药品

# 对药品销售数量按降序排序
re_medicine = re_medicine.sort_values(by='销售数量', ascending=False)# 降序排序
re_medicine.head()
# 截取销售数量最多的十种药品
top_medicine = re_medicine.iloc[:10,:]
print(top_medicine)

在这里插入图片描述
图22:降序排序截取销售数量最多的十种药品

9. 条形图展示销售数量前十的药品


# 用条形图展示销售数量前十的药品
# 对数据的top_medicine进行条形图的可视化
top_medicine.plot(kind = 'bar',color = 'pink')
plt.title('销售前十的药品(ZShiJ)')# 设置图像标题
plt.xlabel('药品')             # 设置x轴的标签文本
plt.ylabel('数量')             # 设置y轴的标签文本
plt.savefig("top_medicine.png")# 保存图片
plt.show()                     # 把图像显示出来。

在这里插入图片描述

图23:条形图展示销售数量前十的药品

在这里插入图片描述

图24:销售前十的药品

        分析:由图24销售前十的药品可以得到销售数量最多的前十种药品信息,这些信息将会有助于加强医院对药房的管理,比如多进一些销售数量多的药品。

异常问题与解决方案

问题1:去重复值用错函数
在这里插入图片描述

图25:没有成功去重复值

解决方案:Dropna是删除空值和缺失值,删除重复值需要使用drop_duplicates,drop_duplicates是pandas内的一个删除函数,subset:表示要进去重的列名,默认为 None。
在这里插入图片描述

图26:计算总消费次数

问题2:需要注意数据类型转换
在这里插入图片描述

图27:数据类型转换

解决方法:一定要记得将原始数据字符串格式日期转换成正常的数据日期,否则会影响后面建模。

参考资料

[1] 详解pandas最常用的3种去重方法
[2] Pandas常用函数大合集
[3] plt.plot()函数解析
[4] Pandas数据排序
[5] 可视化之用pandas绘制简单的图形


回到文章开头

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1576969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Netty学习——源码篇13 命中缓存的分配

上一篇分析了DirectArena内存分配大小的大概流程(Netty池化内存管理机制),知道了其先命中缓冲,如果没有命中,再去分配一款连续内存。现在分析命中缓存的相关逻辑。前面说到PoolThreadCache中维护了三个缓存数组(实际上是6个,这里仅以Direct为…

matlab/simulink仿真全合集---电力电子的simulink仿真

simulink仿真新手大礼包,共整理了9份simulink仿真模型,每一份都是完美运行,适合电气工程专业/电力电子专业的新手学习。 1、Boost电路 simulink 仿真,boost 电路模块搭建和用传递函数进行验证, 电流开环控制 、电流闭…

基于Spring boot+Vue的业余排球俱乐部会员管理系统

5 系统功能模块的具体实现 5.1超级会员角色 5.1.1 登录 超级管理员登录通过用户名和密码去数据库查询用户表,该名称是否在用户表中存在,如果存在,则通过用户名和密码查询密码是否正确,然后吧用户的信息存在jwt的负载里&#xf…

C语言 | Leetcode C语言题解之第14题最长公共前缀

题目&#xff1a; 题解&#xff1a; char* longestCommonPrefix(char** strs, int strsSize) {if (strsSize 0) {return ""; } for (int i 0; i < strlen(strs[0]); i) {for (int j 1; j < strsSize; j) {if (strs[0][i] ! strs[j][i]){strs[0][i] \0;ret…

ics-05-攻防世界

题目 点了半天只有设备维护中心能进去 御剑扫一下 找到一个css 没什么用 再点击云平台设备维护中心url发生了变化 设备维护中心http://61.147.171.105:65103/index.php?pageindex试一下php伪协议 php://filter/readconvert.base64-encode/resourceindex.php base64解一下…

【二分查找】Leetcode 山脉数组的峰顶索引

题目解析 852. 山脉数组的峰顶索引 这到题使用暴力枚举的查找方法发现这段数组是有二段性的&#xff0c;峰顶左边的一段区间是一段递增区间&#xff0c;右边的一段区间是一段递减区间 算法讲解 class Solution { public:int peakIndexInMountainArray(vector<int>&am…

vue快速入门(十二)v-key索引标志

注释很详细&#xff0c;直接上代码 新增内容 v-key的使用场景数组筛选器的使用 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-…

漫谈:“标准”是一种幻觉 C++语言标准的意义

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 “标准”这个词很迷惑&#xf…

1688详情API接口:解锁多元化应用场景java php c++

随着互联网的快速发展&#xff0c;数据交换和信息共享已成为企业日常运营不可或缺的一部分。在这样的背景下&#xff0c;API&#xff08;应用程序接口&#xff09;接口作为实现数据互通的重要工具&#xff0c;受到了越来越多企业的青睐。1688详情API接口作为阿里巴巴旗下的重要…

黑盒测试—错误推测法

上一篇文章介绍了取款业务的场景测试法&#xff0c;在这里继续用上次的场景&#xff0c;对银行的ATM机进行存款&#xff0c;错误推测法算是对场景测试法的补充&#xff0c;错误推测法通常是根据经验来推测可能产生的结果&#xff0c;由原因推测结果。 上一篇文章地址&#xff…

分布式 SpringCloudAlibaba、Feign与RabbitMQ实现MySQL到ES数据同步

文章目录 ⛄引言一、思路分析⛅实现方式⚡框架选择 二、实现数据同步⌚需求分析⏰搭建环境⚡核心源码 三、测试四、源码获取⛵小结 ⛄引言 本文参考黑马 分布式Elastic search Elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助…

python(使用循环显示四种模式)

代码&#xff1a; # 模式A for i in range(1, 6):for j in range(1, 6):if i j:print(i, end"")else:print(" ", end"")print()# 模式B for i in range(1, 6):for j in range(1, 6):if i j 7:print(j, end"")else:print(" &q…

Java常用API_正则表达式_检验字符串是否满足规则——基础使用方法及综合练习

正则表达式可以校验字符串是否满足一定的规则&#xff0c;并用来校验数据格式的合法性。 简单举例&#xff1a; 校验一个qq号是否符合要求 要求&#xff1a;6位到20位之内&#xff0c;不能以0开头&#xff0c;必须全是数字 代码演示&#xff1a; public class Test1 {public…

FreeRTOS移植到标准库

源码下载 1&#xff1a;从官网获取freeRTOS源码 freeRTOS官网 2&#xff1a;FreeRtos源码文件阐述 3&#xff1a;移植FreeRtos源码 FreeRTOS移植步骤1&#xff1a;添加FreeRTOS源码&#xff0c;将FreeRTOS源码添加到基础工程&#xff0c;头文件等路径2&#xff1a;添加FreeR…

VRRP+MSTP+BFD

一、组网 二、要求 PC6&#xff08;vlan 10内PC&#xff09;访问1.1.1.1走JR-1——CORE1——MSR到1.1.1.1 PC7&#xff08;vlan 20内PC&#xff09;访问1.1.1.1走JR-2——CORE2——MSR到1.1.1.1 链路故障时切换路线&#xff0c;来回路径一致 三、配置步骤 SR bfd echo-sou…

Spring AI 来了,打造Java生态大模型应用开发新框架!

Spring AI 来了&#xff0c;打造Java生态大模型应用开发新框架&#xff01; Spring AI 开发框架设计理念Spring AI 主要功能特性如下 Spring AI 应用开发案例案例一&#xff1a;基于大模型的对话应用开发案例二&#xff1a;RAG 检索增强应用开发案例三&#xff1a;Function Cal…

基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的高校招生系统1拥有两种角色&#xff1a;管理员和用户 管理员&#xff1a;学生管理、专业管理、报名管理、录取通知管理、招生公告管理等 用户&#xff1a;登录注册、报…

智慧园区革新之路:山海鲸可视化技术引领新变革

随着科技的飞速发展&#xff0c;智慧园区已成为城市现代化建设的重要组成部分。山海鲸可视化智慧园区解决方案&#xff0c;作为业界领先的数字化革新方案&#xff0c;正以其独特的技术优势和丰富的应用场景&#xff0c;引领着智慧园区建设的新潮流。 本文将带大家一起了解一下…

【linux】基础IO(三)

上一节基础IO我们着重理解了重定向与缓冲区&#xff0c;这节我们需要重点理解文件再磁盘中是怎样存储。以及上一节我们没有涉及到的知识。 stderr到时有什么用&#xff1f; 目录 fd-> 0 1 2&#xff1a;初步理解2怎样将错误与正确输出都打印在一个文件&#xff1f; 文件在硬…

【Vue】我的第一个组件

文章目录 项目简介 项目简介 项目根目录中的index.html是项目的入口文件 加载index.html&#xff0c;vite解析。指向的src下的ts文件或者js文件 最后通过vue3的createApp函数创建一个应用&#xff0c;并挂载到指定div下 App.vue结构说明 特别注意:script脚本内&#xff0…