本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:本项目通过Python对药店销售数据进行全流程分析,涵盖数据预处理、探索、清洗、趋势分析、关联挖掘、客户聚类及销售预测。项目包含数据集、源码和说明文档,适合用于课程设计与大型作业。学习者将掌握Pandas、NumPy、Matplotlib、Seaborn等工具的使用,提升数据建模与商业洞察力,为零售决策提供数据支持。
用python分析处理药店销售数据.rar

1. Python数据分析流程概述

数据分析是挖掘数据价值的核心过程,Python凭借其丰富的库和简洁语法,成为数据分析领域的主流工具。本章将概述使用Python进行数据分析的完整流程,从数据获取、清洗、探索、建模到可视化呈现,构建对药店销售数据的系统性理解。

我们将重点介绍Pandas用于数据处理、NumPy进行数值运算、Matplotlib与Seaborn实现数据可视化等关键技术,结合药店销售场景,帮助读者理解不同工具在实际问题中的应用逻辑。通过本章学习,可为后续深入分析销售趋势、客户行为与门店运营打下坚实基础。

2. 药店销售数据集字段解析

2.1 数据集来源与结构

2.1.1 数据来源与采集方式

药店销售数据集的来源通常包括内部业务系统、第三方数据平台、API接口或历史报表文件。这些数据可能来自ERP系统、POS销售终端、库存管理系统,或是通过爬虫程序从公开渠道获取。采集方式上,常见的方法包括:

  • 数据库导出 :如从MySQL、PostgreSQL等数据库中导出CSV或Excel格式。
  • API接口获取 :通过RESTful API或GraphQL接口获取结构化数据。
  • 日志文件解析 :从销售系统日志中提取关键字段。
  • 爬虫抓取 :利用Scrapy、BeautifulSoup等工具从网页抓取数据。

以数据库导出为例,我们可以使用如下SQL语句将销售数据导出为CSV格式:

SELECT * FROM sales_records
INTO OUTFILE '/var/lib/mysql-files/sales_data.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';

逻辑分析与参数说明:
- SELECT * FROM sales_records :从 sales_records 表中提取所有记录。
- INTO OUTFILE :指定导出文件路径。
- FIELDS TERMINATED BY ',' :字段以逗号分隔。
- ENCLOSED BY '"' :字符串使用双引号包裹。
- LINES TERMINATED BY '\n' :每行以换行符结束。

导出后,可以使用Python中的 pandas 库进行加载:

import pandas as pd

df_sales = pd.read_csv('sales_data.csv')
print(df_sales.head())

2.1.2 数据字段的命名规范与含义

药店销售数据集通常包含多个字段,命名规范通常采用 小写字母+下划线 的形式,如 sale_date product_name 等。以下是常见的字段及其含义:

字段名 类型 含义说明
sale_id 整数型 销售记录唯一标识
sale_date 日期型 销售发生日期
product_id 整数型 药品唯一标识
product_name 字符串型 药品名称
price 浮点型 药品单价
quantity 整数型 销售数量
customer_id 整数型 客户唯一标识
customer_type 字符串型 客户类型(普通/会员)
store_id 整数型 门店编号
promotion 布尔型 是否参与促销活动

这些字段构成了药店销售数据的基本结构,为后续分析提供了基础。

2.2 核心字段分析

2.2.1 销售记录字段(如时间、药品名称、价格、销量)

销售记录字段是数据分析的核心部分,主要包括时间、药品名称、价格、销量等。这些字段直接反映了销售行为的发生情况。

例如,我们可以使用 pandas 对销售时间进行解析和提取周几信息:

df_sales['sale_date'] = pd.to_datetime(df_sales['sale_date'])
df_sales['weekday'] = df_sales['sale_date'].dt.weekday_name

逻辑分析与参数说明:
- pd.to_datetime() :将字符串日期转换为标准时间格式。
- dt.weekday_name :提取销售发生的星期几。

通过分析销售时间,我们可以识别销售高峰期,为库存调度和促销安排提供依据。

2.2.2 客户信息字段(如客户类型、地理位置)

客户信息字段包括客户类型(如普通客户、会员)和地理位置(如省、市、区)。这些字段有助于分析客户行为和区域销售表现。

例如,我们可以统计不同客户类型的购买频次:

customer_type_counts = df_sales.groupby('customer_type')['sale_id'].count()
print(customer_type_counts)

逻辑分析与参数说明:
- groupby('customer_type') :按客户类型分组。
- count() :统计每种客户类型的销售记录数。

2.2.3 店铺运营字段(如门店编号、促销信息)

店铺运营字段包括门店编号、是否参与促销活动等。这些字段用于分析门店绩效和促销效果。

例如,我们可以计算每个门店的总销售额:

df_sales['total_sales'] = df_sales['price'] * df_sales['quantity']
store_sales = df_sales.groupby('store_id')['total_sales'].sum()
print(store_sales)

逻辑分析与参数说明:
- price * quantity :计算每条记录的销售额。
- groupby('store_id') :按门店编号分组。
- sum() :汇总每个门店的总销售额。

2.3 字段间关系建模

2.3.1 数据表的主键与外键设计

药店销售数据通常由多个表组成,如销售表、客户表、药品表、门店表等。这些表之间通过主键和外键建立关联。

  • 主键(Primary Key) :唯一标识表中一条记录,如 sale_id product_id
  • 外键(Foreign Key) :用于关联其他表的主键,如 product_id 在销售表中作为外键关联药品表。

例如,在MySQL中定义销售表与药品表的关系:

CREATE TABLE sales_records (
    sale_id INT PRIMARY KEY,
    sale_date DATE,
    product_id INT,
    quantity INT,
    price DECIMAL(10, 2),
    FOREIGN KEY (product_id) REFERENCES products(product_id)
);

逻辑分析与参数说明:
- FOREIGN KEY (product_id) :定义外键。
- REFERENCES products(product_id) :关联药品表的主键。

2.3.2 多表关联逻辑与JOIN操作基础

在实际分析中,我们经常需要将多个表连接起来。常见的JOIN操作包括INNER JOIN、LEFT JOIN等。

例如,使用SQL将销售表与药品表进行INNER JOIN:

SELECT s.sale_id, p.product_name, s.quantity, s.price
FROM sales_records s
INNER JOIN products p ON s.product_id = p.product_id;

逻辑分析与参数说明:
- INNER JOIN :只返回两个表中匹配的记录。
- ON s.product_id = p.product_id :连接条件为药品ID相同。

在Python中,也可以使用 merge 函数进行JOIN操作:

df_merged = pd.merge(df_sales, df_products, on='product_id', how='inner')

逻辑分析与参数说明:
- on='product_id' :按药品ID连接。
- how='inner' :使用INNER JOIN方式。

2.4 数据字段的初步统计特征

2.4.1 各字段的分布情况

了解各字段的分布情况有助于识别数据特征和异常值。我们可以使用 describe() 函数快速获取数值型字段的统计信息:

print(df_sales.describe())

输出结果包括:
- count :记录数量
- mean :平均值
- std :标准差
- min/max :最小值/最大值
- 25%/50%/75% :分位数

对于非数值型字段,如药品名称,可以使用 value_counts() 查看分布:

print(df_sales['product_name'].value_counts())

2.4.2 常见异常值与无效数据识别

异常值可能包括价格为负、销量为零或极大值。我们可以使用箱线图(Boxplot)识别异常值:

import matplotlib.pyplot as plt

plt.boxplot(df_sales['price'])
plt.title('Price Distribution')
plt.ylabel('Price')
plt.show()

逻辑分析与参数说明:
- boxplot() :绘制箱线图。
- 异常值通常显示为图中的离群点。

对于无效数据,如药品名称为空,我们可以使用如下方式识别:

invalid_rows = df_sales[df_sales['product_name'].isnull()]
print(invalid_rows)

逻辑分析与参数说明:
- isnull() :检测空值。
- 返回包含空药品名称的记录。

数据字段关系流程图(Mermaid)

erDiagram
    SALES_RECORDS ||--o{ PRODUCTS : "product_id"
    SALES_RECORDS ||--o{ CUSTOMERS : "customer_id"
    SALES_RECORDS ||--o{ STORES : "store_id"
    PRODUCTS {
        int product_id
        string product_name
        string category
    }
    CUSTOMERS {
        int customer_id
        string customer_type
        string location
    }
    STORES {
        int store_id
        string city
        string region
    }
    SALES_RECORDS {
        int sale_id
        date sale_date
        int product_id
        int customer_id
        int store_id
        float price
        int quantity
        boolean promotion
    }

本章系统地介绍了药店销售数据集的字段构成、结构来源、核心字段分析、字段间关系建模以及初步统计特征。通过这些分析,我们不仅掌握了数据的基本情况,还为后续的数据清洗和建模打下了坚实基础。

3. 数据预处理与缺失值处理

在数据分析流程中,数据预处理是至关重要的一环。原始数据往往存在缺失值、异常值、格式不一致等问题,这些问题会严重影响后续分析的准确性与模型的性能。因此,本章将围绕药店销售数据集,系统讲解数据预处理的关键步骤,包括数据清洗、缺失值处理、数据类型转换与标准化,以及数据分组与聚合等内容,为后续的深入分析奠定坚实基础。

3.1 数据清洗流程

数据清洗是数据预处理的第一步,其主要目标是识别并修正数据集中存在的错误和不一致问题,包括重复记录、异常值、非法格式等。

3.1.1 重复数据的识别与删除

在药店销售数据中,重复记录可能来源于数据采集过程中的错误或系统故障。重复记录不仅浪费存储空间,还会导致统计结果偏高,影响分析的准确性。

操作步骤:

import pandas as pd

# 加载销售数据
df_sales = pd.read_csv('drug_sales.csv')

# 检查重复记录
duplicate_rows = df_sales[df_sales.duplicated()]
print(f"发现 {len(duplicate_rows)} 条重复记录")

# 删除重复记录
df_sales_cleaned = df_sales.drop_duplicates()

代码逻辑分析:

  • df_sales.duplicated() 返回一个布尔序列,标记每一行是否为重复记录。
  • drop_duplicates() 函数默认保留第一次出现的记录,其余重复行被删除。
  • 若需根据特定字段去重,可传入 subset=['字段名'] 参数。

3.1.2 异常值的检测与处理

异常值是指明显偏离正常范围的数据点,可能由输入错误、测量误差或极端事件引起。在药店销售数据中,异常值常见于价格、销量等字段。

检测方法:

  • Z-score 方法 :适用于正态分布数据。
  • IQR 方法 :适用于非正态分布数据。

示例代码:

# 使用IQR法检测销量字段的异常值
Q1 = df_sales_cleaned['销量'].quantile(0.25)
Q3 = df_sales_cleaned['销量'].quantile(0.75)
IQR = Q3 - Q1

# 定义异常值范围
outlier_mask = (df_sales_cleaned['销量'] < (Q1 - 1.5 * IQR)) | (df_sales_cleaned['销量'] > (Q3 + 1.5 * IQR))

# 打印异常值
outliers = df_sales_cleaned[outlier_mask]
print(f"发现 {len(outliers)} 条销量异常记录")

参数说明:

  • quantile() 用于计算分位数。
  • IQR = Q3 - Q1 是四分位距。
  • 通常认为超出 Q1 - 1.5*IQR Q3 + 1.5*IQR 的值为异常值。

处理策略:

  • 删除异常记录 :适用于数据量充足且异常值比例较小的情况。
  • 替换为上下限值 :适用于需要保留记录但修正极端值的情况。
  • 使用中位数填充 :适用于异常值可视为缺失处理的情况。

3.2 缺失值的识别与处理

缺失值是数据分析中常见的问题,处理不当将影响模型的训练和预测效果。本节将介绍如何识别缺失值,并探讨多种处理策略。

3.2.1 缺失值的统计方法

首先需要识别数据集中哪些字段存在缺失值,并统计其缺失比例。

示例代码:

# 查看各字段缺失值数量
missing_values = df_sales_cleaned.isnull().sum()

# 计算缺失比例
missing_ratio = (missing_values / len(df_sales_cleaned)) * 100

# 合并输出
missing_df = pd.DataFrame({'缺失值数量': missing_values, '缺失比例(%)': missing_ratio})
print(missing_df)

输出示例:

字段名 缺失值数量 缺失比例(%)
价格 23 0.15
客户类型 0 0.00
门店编号 5 0.03

逻辑分析:

  • isnull().sum() 统计每列的缺失值数量。
  • 缺失比例有助于判断是否需要保留该字段进行处理。

3.2.2 缺失值的填充策略(均值、中位数、插值等)

处理缺失值的常见策略包括:

策略名称 适用场景 特点
均值填充 数值型数据,分布较均匀 快速,但可能引入偏差
中位数填充 存在极端值 对异常值不敏感
插值填充 时间序列或有序数据 适用于连续性数据
热卡填充 类别型数据 用相似记录填充

示例代码:

# 使用中位数填充价格字段缺失值
median_price = df_sales_cleaned['价格'].median()
df_sales_cleaned['价格'].fillna(median_price, inplace=True)

# 使用前向插值填充时间字段
df_sales_cleaned['销售时间'].fillna(method='ffill', inplace=True)

参数说明:

  • fillna() 是填充缺失值的核心方法。
  • method='ffill' 表示使用前一个有效值进行填充(Forward Fill)。

3.2.3 删除缺失记录的适用场景

在缺失比例较低(如小于5%)且缺失随机分布的情况下,删除记录是一种简单有效的处理方式。

示例代码:

# 删除含有缺失值的行
df_sales_cleaned = df_sales_cleaned.dropna()

# 查看处理后数据量
print(f"处理后记录数:{len(df_sales_cleaned)}")

逻辑分析:

  • dropna() 默认删除任何包含缺失值的行。
  • 若需删除整列缺失值,可使用 axis=1 参数。

3.3 数据类型转换与标准化

数据类型不一致会导致计算错误或模型训练失败,标准化处理则有助于提升模型的收敛速度与准确性。

3.3.1 时间字段的格式统一

时间字段在数据分析中至关重要,统一格式是进行时间维度分析的前提。

示例代码:

# 将字符串转换为datetime格式
df_sales_cleaned['销售时间'] = pd.to_datetime(df_sales_cleaned['销售时间'])

# 提取日期部分
df_sales_cleaned['销售日期'] = df_sales_cleaned['销售时间'].dt.date

逻辑分析:

  • pd.to_datetime() 将字符串转换为标准时间格式。
  • dt.date 提取日期部分,便于后续按日分组分析。

3.3.2 类别型数据的编码处理(One-Hot、Label Encoding)

机器学习模型无法直接处理字符串类型数据,需将其转换为数值形式。

编码方式对比:

方法 适用场景 特点
Label Encoding 有序类别(如等级) 保留顺序信息
One-Hot Encoding 无序类别(如药品名称) 避免引入顺序偏差

示例代码(One-Hot):

# 对药品名称进行One-Hot编码
df_encoded = pd.get_dummies(df_sales_cleaned, columns=['药品名称'])

# 查看新字段
print(df_encoded.columns)

逻辑分析:

  • pd.get_dummies() 自动生成多个二进制字段。
  • 若类别较多,建议使用 drop_first=True 避免多重共线性。

3.3.3 数值型数据的标准化与归一化

标准化(Z-score)和归一化(Min-Max)是常用的数值处理方法。

示例代码:

from sklearn.preprocessing import StandardScaler, MinMaxScaler

# 标准化
scaler = StandardScaler()
df_sales_cleaned['价格标准化'] = scaler.fit_transform(df_sales_cleaned[['价格']])

# 归一化
minmax_scaler = MinMaxScaler()
df_sales_cleaned['价格归一化'] = minmax_scaler.fit_transform(df_sales_cleaned[['价格']])

逻辑分析:

  • StandardScaler 将数据转换为均值为0、方差为1的标准分布。
  • MinMaxScaler 将数据缩放到 [0, 1] 区间,适用于图像处理等场景。

3.4 数据分组与聚合

数据分组与聚合是探索性数据分析的重要工具,可以按时间、药品、客户等维度进行统计汇总。

3.4.1 按时间、药品、客户维度分组统计

示例代码:

# 按药品名称和销售日期分组,计算销量总和
grouped = df_sales_cleaned.groupby(['药品名称', '销售日期'])['销量'].sum().reset_index()

# 查看前10条结果
print(grouped.head(10))

逻辑分析:

  • groupby() 按指定字段分组。
  • sum() 是聚合函数,还可使用 mean() , count() , max() 等。

3.4.2 分组聚合函数的使用方法

多聚合函数使用:

# 分组后计算多个统计量
grouped_multi = df_sales_cleaned.groupby('药品名称').agg(
    总销量=('销量', 'sum'),
    平均价格=('价格', 'mean'),
    销售天数=('销售时间', 'nunique')
).reset_index()

print(grouped_multi)

逻辑分析:

  • agg() 支持多字段多函数的灵活聚合。
  • nunique() 计算唯一值数量,用于统计销售天数。

数据分组与聚合流程图(mermaid)

graph TD
    A[原始数据] --> B{选择分组字段}
    B --> C[按药品名称分组]
    B --> D[按销售日期分组]
    B --> E[按客户类型分组]
    C --> F[应用聚合函数]
    D --> F
    E --> F
    F --> G[生成汇总表]

总结:

通过本章内容,我们系统学习了药店销售数据的预处理流程,包括数据清洗、缺失值处理、数据类型转换与标准化、以及分组聚合操作。这些步骤是确保后续分析结果准确、模型训练高效的关键环节。下一章我们将进入数据探索与描述性统计分析,进一步挖掘数据中的隐藏信息。

4. 数据探索与描述性统计分析

数据分析的探索阶段是整个流程中最关键的环节之一,它帮助我们从数据中获取初步洞察,理解变量的基本特性以及它们之间的关系。本章将围绕药店销售数据展开,从单变量分析、多变量相关性、时间维度销售趋势到地理位置影响等维度,进行系统性的探索性分析。通过统计量、图表可视化和逻辑推理,我们将揭示数据背后的规律,为后续的建模和预测提供基础支撑。

4.1 单变量分析

单变量分析关注的是单个变量的分布情况,通过计算其基本统计量,如均值、方差、标准差、中位数、极值等,来理解该变量的集中趋势和离散程度。在药店销售数据中,我们重点分析“药品销量”和“销售额”两个关键指标。

4.1.1 药品销量的基本统计量(均值、方差、分布)

药品销量是衡量药店运营效率的重要指标。我们使用Pandas对药品销量字段进行描述性统计。

import pandas as pd

# 假设df是加载好的销售数据
print(df['销量'].describe())

执行逻辑说明:
- df['销量'] :选取“销量”列数据。
- .describe() :计算并输出该列的基本统计量,包括计数、均值、标准差、最小值、25%分位数、中位数(50%)、75%分位数、最大值。

输出示例:

统计量
count 10000
mean 25.3
std 15.6
min 1
25% 12
50% 24
75% 36
max 120

参数说明:
- mean :平均销量为25.3,表示平均每单药品销售数量。
- std :标准差为15.6,说明销量波动较大。
- min/max :销量最低为1,最高为120,说明存在极端值或促销活动导致的销量突增。

此外,我们还可以绘制销量的直方图以观察其分布形态:

import matplotlib.pyplot as plt

plt.hist(df['销量'], bins=30, edgecolor='black')
plt.title('药品销量分布')
plt.xlabel('销量')
plt.ylabel('频数')
plt.show()

执行逻辑说明:
- plt.hist() :绘制直方图,观察销量的分布。
- bins=30 :将销量划分为30个区间。
- edgecolor='black' :设置柱子边框颜色,提升可读性。

结论:
从直方图可以看出销量是否符合正态分布或偏态分布,这对后续建模时是否需要进行变换或使用非参数方法具有指导意义。

4.1.2 销售额的集中趋势与离散程度

销售额是另一个关键变量,它反映了药店的整体收入情况。我们同样使用描述性统计和可视化手段来分析其特性。

print(df['销售额'].describe())

输出示例:

统计量
count 10000
mean 150.2
std 90.5
min 5
25% 70
50% 140
75% 210
max 1000

分析:
- 销售额均值为150.2元,说明平均每单销售金额为150元左右。
- 标准差为90.5,波动较大,可能存在大额订单或某些药品单价较高。

绘制销售额的箱线图可以识别异常值:

plt.boxplot(df['销售额'])
plt.title('销售额箱线图')
plt.ylabel('销售额(元)')
plt.show()

执行逻辑说明:
- plt.boxplot() :绘制箱线图,识别销售额中的异常值。
- 箱线图的“须”表示正常范围,点表示异常值。

结论:
若箱线图中出现大量异常点,说明销售额存在极端值,需进一步检查是否为输入错误或特殊促销活动。

4.2 多变量相关性分析

在数据分析中,变量之间的相关性分析有助于理解变量之间的关系,并为后续的建模提供变量选择依据。我们重点分析“销售量”与“销售额”的关系,以及“客户类型”与“购买频率”的关系。

4.2.1 销售量与销售额的相关性

销售量与销售额之间理论上存在强正相关性,因为销售额 = 单价 × 销量。我们使用Pandas计算皮尔逊相关系数来验证这一关系。

import seaborn as sns

corr = df[['销量', '销售额']].corr()
sns.heatmap(corr, annot=True, cmap='coolwarm')
plt.title('销量与销售额相关性热力图')
plt.show()

执行逻辑说明:
- corr() :计算销量与销售额之间的相关系数。
- sns.heatmap() :绘制热力图,展示变量之间的相关性。

输出示例:

变量 销量 销售额
销量 1.00 0.87
销售额 0.87 1.00

结论:
销量与销售额之间的皮尔逊相关系数为0.87,说明两者具有高度正相关性,验证了理论模型的合理性。

4.2.2 客户类型与购买频率的关系

客户类型通常分为“普通客户”、“会员客户”等,购买频率是指客户在一段时间内的购买次数。我们使用交叉表和柱状图来分析不同类型客户的购买频率分布。

import pandas as pd
import matplotlib.pyplot as plt

# 假设'客户类型'列为分类变量,'购买频率'为数值变量
cross_tab = pd.crosstab(index=df['客户类型'], columns=df['购买频率'])
cross_tab.plot(kind='bar', stacked=True)
plt.title('客户类型与购买频率交叉分布')
plt.xlabel('客户类型')
plt.ylabel('频数')
plt.show()

执行逻辑说明:
- pd.crosstab() :生成客户类型与购买频率的交叉表。
- plot(kind='bar') :绘制堆叠柱状图,比较不同类型客户的购买频率分布。

结论:
通过图表可以观察到不同客户类型在购买频率上的差异。例如,会员客户可能在高频购买群体中占比较高,这对营销策略制定具有指导意义。

4.3 时间维度的销售分析

时间维度是销售分析中不可或缺的变量,它可以帮助我们识别销售趋势、周期性波动和节假日效应。

4.3.1 每日销售总额的波动趋势

我们将数据按“日期”字段进行分组,计算每日销售总额,并绘制趋势图。

df['日期'] = pd.to_datetime(df['日期'])
daily_sales = df.groupby('日期')['销售额'].sum().reset_index()

plt.plot(daily_sales['日期'], daily_sales['销售额'], marker='o', linestyle='-')
plt.title('每日销售总额趋势')
plt.xlabel('日期')
plt.ylabel('销售总额(元)')
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

执行逻辑说明:
- pd.to_datetime() :将“日期”字段转换为时间类型。
- groupby('日期') :按日期分组计算每日销售总额。
- plt.plot() :绘制时间序列图,观察销售总额的波动趋势。

结论:
从趋势图中可以识别销售的上升或下降趋势,是否存在节假日效应或促销活动带来的高峰。

4.3.2 不同门店销售的周期性表现

我们还可以按门店编号进行分组,分析各门店的销售周期性表现。

import seaborn as sns

df['星期'] = df['日期'].dt.day_name()
grouped = df.groupby(['门店编号', '星期'])['销售额'].mean().reset_index()

sns.lineplot(data=grouped, x='星期', y='销售额', hue='门店编号')
plt.title('各门店按星期的平均销售额趋势')
plt.xlabel('星期')
plt.ylabel('平均销售额(元)')
plt.xticks(rotation=45)
plt.legend(title='门店编号')
plt.show()

执行逻辑说明:
- dt.day_name() :提取日期对应的星期名称。
- groupby(['门店编号', '星期']) :按门店和星期分组计算平均销售额。
- sns.lineplot() :绘制多门店的周销售趋势图,比较周期性表现。

结论:
某些门店可能在周末销售表现更佳,而另一些门店则在工作日表现更好,这对门店排班和库存管理具有指导意义。

4.4 地理位置与销售表现

地理位置信息在药店销售分析中具有重要意义,可以帮助识别销售热点区域和潜在增长点。

4.4.1 各地区销售额的分布情况

我们按地区分组计算销售额总和,并使用柱状图进行可视化。

region_sales = df.groupby('地区')['销售额'].sum().reset_index()
plt.bar(region_sales['地区'], region_sales['销售额'])
plt.title('各地区销售总额分布')
plt.xlabel('地区')
plt.ylabel('销售总额(元)')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

执行逻辑说明:
- groupby('地区') :按地区分组计算销售额总和。
- plt.bar() :绘制柱状图,展示各地区销售额差异。

结论:
某些地区的销售额显著高于其他地区,可能与其人口密度、消费水平或门店密度有关。

4.4.2 热点区域识别与地图可视化

为了更直观地展示销售热点区域,我们可以使用地理信息系统(GIS)工具如 geopandas folium 进行地图可视化。

import folium
from folium.plugins import MarkerCluster

# 假设df包含'纬度'和'经度'字段
m = folium.Map(location=[39.9042, 116.4074], zoom_start=10)
marker_cluster = MarkerCluster().add_to(m)

for i, row in df.iterrows():
    folium.Marker(location=[row['纬度'], row['经度']], popup=f"销售额:{row['销售额']}元").add_to(marker_cluster)

m.save('sales_map.html')

执行逻辑说明:
- folium.Map() :创建地图对象。
- MarkerCluster() :创建标记集群,避免地图过载。
- folium.Marker() :为每条记录添加带销售额信息的标记。
- m.save() :保存地图为HTML文件,可在浏览器中查看。

结论:
地图可视化可以直观识别销售热点区域,辅助门店选址和市场拓展。

本章通过单变量统计、多变量相关性、时间维度分析和地理位置可视化等手段,系统性地探索了药店销售数据。这些分析为后续的建模和预测提供了坚实的数据基础,也为业务决策提供了有力支持。下一章我们将深入分析销售趋势的时间分组表现,包括按月和季度的销售波动分析。

5. 销售趋势按时间分组分析(月/季度)

5.1 时间序列数据构建

在药店销售数据分析中,时间维度是理解销售趋势的关键因素之一。为了构建时间序列数据,首先需要确保数据集中包含有效的时间字段,例如销售日期( sale_date )。我们可以使用Pandas库对时间字段进行解析并设置为索引,从而构建时间序列格式的数据集。

5.1.1 时间字段的解析与索引设置

以下是一个将字符串格式的时间字段转换为 datetime 类型,并将其设置为索引的示例代码:

import pandas as pd

# 假设数据集为 sales_df,包含 'sale_date' 字段
sales_df = pd.read_csv('pharmacy_sales.csv')

# 将 'sale_date' 转换为 datetime 类型
sales_df['sale_date'] = pd.to_datetime(sales_df['sale_date'])

# 设置 'sale_date' 为索引
sales_df.set_index('sale_date', inplace=True)

# 查看前5行数据
print(sales_df.head())

执行上述代码后, sale_date 列将被用作索引,便于后续进行时间维度的聚合和分析。

5.1.2 按月/季度聚合销售数据

在时间序列构建完成后,我们可以使用 resample 方法按月或季度对销售数据进行聚合。以销售额( sales_amount )为例:

# 按月聚合销售额
monthly_sales = sales_df['sales_amount'].resample('M').sum()

# 按季度聚合销售额
quarterly_sales = sales_df['sales_amount'].resample('Q').sum()

# 查看按月聚合结果
print(monthly_sales.head())
时间 月度销售额
2023-01-31 25000.00
2023-02-28 23500.50
2023-03-31 27800.75
2023-04-30 26000.25
2023-05-31 28900.00

通过上述操作,我们成功构建了按月和季度聚合的销售数据,为后续趋势分析打下基础。

5.2 月度与季度销售趋势分析

5.2.1 销售总量与销售额的月度变化

在构建了按月聚合的数据后,我们可以通过可视化手段分析销售总量和销售额的变化趋势。以下是一个使用Matplotlib绘制月度销售额变化趋势的示例:

import matplotlib.pyplot as plt

# 绘制月度销售额趋势图
plt.figure(figsize=(12, 6))
monthly_sales.plot(kind='line', title='Monthly Sales Trend (2023)')
plt.xlabel('Month')
plt.ylabel('Sales Amount')
plt.grid(True)
plt.show()

该图将展示销售额随时间的变化趋势,帮助我们识别是否存在增长或下降趋势。

5.2.2 季节性波动与节假日影响

药店销售数据往往受到季节性和节假日的影响。例如,冬季感冒药销量可能激增,春节前后保健品销售可能上升。我们可以将销售数据与节假日数据进行合并分析:

# 假设有一个节假日列表 holidays_df
holidays_df = pd.DataFrame({
    'date': ['2023-01-01', '2023-02-11', '2023-04-05', '2023-06-22'],
    'holiday': ['New Year', 'Spring Festival', 'Qingming Festival', 'Dragon Boat Festival']
})

# 将节假日日期转换为 datetime 类型
holidays_df['date'] = pd.to_datetime(holidays_df['date'])

# 提取节假日所在月份
monthly_sales['is_holiday_month'] = monthly_sales.index.to_period('M').isin(holidays_df['date'].dt.to_period('M'))

# 查看节假日月份的销售额
print(monthly_sales[monthly_sales['is_holiday_month']])

通过分析节假日月份的销售额,可以判断是否存在显著增长或下降,为营销策略提供依据。

5.3 药品类别的时间趋势分析

5.3.1 各类药品的月度销售变化

为了分析不同药品类别的销售趋势,我们需要对药品类别( product_category )与销售数据进行分组,并按月进行聚合:

# 按药品类别和月份分组汇总销售额
category_monthly_sales = sales_df.groupby([pd.Grouper(freq='M'), 'product_category'])['sales_amount'].sum().unstack()

# 查看前几行数据
print(category_monthly_sales.head())
product_category Antibiotics Cough Medicine Vitamins Painkillers
sale_date
2023-01-31 8000.00 5000.00 6000.00 6000.00
2023-02-28 7500.00 5200.00 5800.00 5000.00
2023-03-31 8200.00 5100.00 6200.00 5300.00

5.3.2 高增长与低波动药品识别

我们可以计算每个药品类别销售额的月增长率,并识别出高增长类别:

# 计算每个药品类别的月增长率
growth_rates = category_monthly_sales.pct_change() * 100

# 查看增长率数据
print(growth_rates.tail())

通过分析增长率数据,可以识别出哪些药品类别在特定月份增长迅速,哪些表现稳定或波动较小,从而指导库存和促销策略。

5.4 预测趋势与可视化展示

5.4.1 使用移动平均法平滑趋势

为了消除短期波动,我们可以使用移动平均法对销售额趋势进行平滑处理:

# 计算3个月移动平均
monthly_sales_ma = monthly_sales.rolling(window=3).mean()

# 绘制原始数据与移动平均线
plt.figure(figsize=(12, 6))
monthly_sales.plot(kind='line', label='Original')
monthly_sales_ma.plot(kind='line', label='3-Month MA', color='red')
plt.title('Monthly Sales with Moving Average')
plt.xlabel('Month')
plt.ylabel('Sales Amount')
plt.legend()
plt.grid()
plt.show()

该图展示了原始销售趋势与平滑后的趋势线,有助于识别长期趋势方向。

5.4.2 利用Matplotlib/Seaborn绘制趋势图

使用Seaborn库可以更美观地展示趋势变化:

import seaborn as sns

# Seaborn样式设置
sns.set(style="whitegrid")

# 绘制趋势图
plt.figure(figsize=(12, 6))
sns.lineplot(x=monthly_sales.index, y=monthly_sales.values)
plt.title('Monthly Sales Trend')
plt.xlabel('Month')
plt.ylabel('Sales Amount')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

通过上述代码,我们可以生成清晰、美观的趋势图,用于展示销售数据的时间变化特征。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:本项目通过Python对药店销售数据进行全流程分析,涵盖数据预处理、探索、清洗、趋势分析、关联挖掘、客户聚类及销售预测。项目包含数据集、源码和说明文档,适合用于课程设计与大型作业。学习者将掌握Pandas、NumPy、Matplotlib、Seaborn等工具的使用,提升数据建模与商业洞察力,为零售决策提供数据支持。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐