面向对象数据分析案例

2024-08-09 01:01:44 浏览数 (4)

某公司有两份数据文件:“2011年1月销售数据.txt”和“2011年2月销售数据JSON.txt”。前者是普通文本文件,使用逗号分隔数据记录,内容依次为日期、订单编号、销售额和销售省份;后者则是JSON格式的数据,内容依次为日期、订单编号、销售额和销售省份。现在需要对这两份数据进行分析和处理,要求是使用面向对象的编程思想来读取和处理数据,计算每日的销售额,并利用Pyecharts库以柱状图的形式展示结果。

文件部分数据如下:

【需求分析】

①数据定义类

代码语言:python代码运行次数:0复制
"""
数据定义类
Record类用于封装销售数据中每一条记录
"""
class Record:
    # 该构造方法接受日期、订单编号、销售额和省份,并将它们存储为类的实例变量
    def __init__(self,date,order_id,money,province):
        self.date = date            # 订单日期
        self.order_id = order_id    # 订单编号
        self.money = money          # 订单金额
        self.province = province    # 销售省份
    # 字符串表示法,方便打印Record对象的内容,返回一个格式化的字符串
    def __str__(self):
        return f"{self.date},{self.order_id},{self.money},{self.province}"

【分析】

Record 类的主要作用是将销售数据的每一条记录封装为一个对象,提供了一个清晰的结构来存储和访问这些数据。通过该类,可以方便地创建多个销售记录对象,并在需要时以易读的格式输出它们。在整个分析和可视化过程中,Record 类将被用于读取和存储来自两个数据文件的销售记录,之后便可通过遍历这些对象来计算每日的销售额,并利用 Pyecharts 库生成柱状图展示结果。

②文件读取类

代码语言:python代码运行次数:0复制
"""
文件相关的类定义
"""

# 导入 json 模块,用于处理JSON文件
import json
# 导入 Record 类,以便在其他类中创建记录对象
from data_define import Record

# 定义一个抽象类,用于顶层设计,定义了文件读取的接口
class FileReader:
    # 抽象方法,强制子类实现相应的读取方法,并返回一个包含Record对象的列表
    def read_data(self)->list[Record]:
        pass

# 子类TextFileReader继承父类FileReader,用于从文本文件中读取数据
class TextFileReader(FileReader):
    # 构造方法,接受文件路径,并将其存储为实例变量
    def __init__(self,path):
        self.path=path   # 定义成员变量记录文件的路径

    # 复写(实现抽象方法)父类的方法
    def read_data(self) ->list[Record]:
        # 打开指定路径的文本文件
        f=open(self.path,"r",encoding="UTF-8")
        # 初始化一个空的record_list来存储Record对象
        record_list:list[Record]=[]
        # 循环读取每一行数据
        for line in f.readlines():
            line=line.strip()   # 消除读取到的每一行数据中的 n
            data_list=line.split(",")
            # print(data_list)
            # 输出内容:['2011-01-01', '4b34218c-9f37-4e66-b33e-327ecd5fb897', '1689', '湖南省']……
            record=Record(data_list[0],data_list[1],int(data_list[2]),data_list[3])
            # print(record)
            # 输出内容:2011-01-01,4b34218c-9f37-4e66-b33e-327ecd5fb897,1689,湖南省
            record_list.append(record)

        f.close()
        return record_list


# 子类JsonFileReader继承自父类FileReader,用于从JSON文件中读取数据
class JsonFileReader(FileReader):
    def __init__(self,path):
        self.path=path   # 定义成员变量记录文件的路径

    def read_data(self) -> list[Record]:
        f = open(self.path, "r", encoding="UTF-8")

        record_list: list[Record] = []
        for line in f.readlines():
            # 将json数据转换为Python字典
            data_dict=json.loads(line)
            # 从字典中提取相应的字段
            record=Record(data_dict["date"],data_dict["order_id"],data_dict["money"],data_dict["province"])
            print(record)
            record_list.append(record)

        f.close()
        return record_list

【分析】

这段代码实现了一个简单的文本文件读取器,用于读取不同格式的文件(文本和 JSON),并将文件中的每一行数据转换为 Python 对象,便于在后续程序中管理和操作这些数据。

在本案例中,将文本文件中的每一行数据转换为 Python 对象的操作也可称为 “数据反序列化

  • 数据序列化: 将数据结构或对象状态转换为可存储或传输的格式的过程。这一过程使得数据能够被有效地保存到文件中或通过网络进行传输。在序列化过程中,数据被转换为一种特定格式,例如文本格式(如 JSON、XML)、二进制格式等,以便于存储和恢复。
  • 数据反序列化: 将已序列化的数据转换回其原始数据结构或对象状态的过程。反序列化是序列化的逆过程,使得应用程序能够再次使用以前存储或传输的数据信息。

实现数据反序列化的基本步骤

  1. 定义对象类
  2. 读取数据源:使用 Python 的内置 open() 函数打开文件并读取内容
  3. 解析数据:文本文件通常需要按行读取,使用字符串操作进行拆分;JSON文件需使用json模块解析为Python字典
  4. 创建对象
  5. 处理错误

思考:那为什么要将文件中的每一行数据转换为 Python 对象呢?

回答:

  1. 封装性: 对象可以将相关数据和方法封装在一起,使得数据结构更加清晰。例如,Record 对象可以包含日期、订单号、金额和省份等属性,所有相关信息集中到一起,便于管理。
  2. 易于操作: 对象可以包含操作其数据的方法,方便对数据进行处理(如排序、筛选、计算等),灵活性高。
  3. 可扩展性: 通过面向对象的设计,可以更容易地实现继承和多态,创建复杂数据结构和业务逻辑。如果未来需要追加新的属性或行为(例如添加方法计算订单的税费),可直接在 Record 类中进行扩展,而不必去修改数据读取的逻辑。
  4. 提高可读性和可维护性: 使用对象后,开发者可以通过方法名和属性名一目了然地理解程序的意图。除此之外,对象可以独立于其使用环境进行测试,简化了调试和维护流程。
  5. 模拟现实世界: 通过对象,可以更准确地模拟现实世界中的事物。例如,订单不仅仅包含数据,还可以有与之相关的行为和状态,使代码更贴近实际应用。

③数据计算以及图表绘制

代码语言:python代码运行次数:0复制
# 导入必要的库和之前定义的类
from file_define import FileReader,TextFileReader,JsonFileReader
from data_define import Record
from pyecharts.charts import Bar
from pyecharts.options import *
from pyecharts.globals import ThemeType

# 创建TextFileReader和JsonFileReader的实例,读取数据到列表中
text_file_reader=TextFileReader("D:/2011年1月销售数据.txt")
jan_data:list[Record]=text_file_reader.read_data()

json_file_reader=JsonFileReader("D:/2011年2月销售数据JSON.txt")
feb_data:list[Record]=json_file_reader.read_data()

# 将两个月份的数据合并为一个list来存储
all_data:list[Record]=jan_data feb_data

# 计算每日销售额
data_dict={}
# 遍历所有记录,将相同日期的销售额进行累加
for record in all_data:
    if record.date in data_dict.keys():
        # 当前日期已经有记录了,所以和老记录累加记录
        data_dict[record.date] =record.money
    else:
        data_dict[record.date]=record.money

print(data_dict)

# 可视化图表开发
bar=Bar(init_opts=InitOpts(theme=ThemeType.LIGHT))
# 添加x轴数据,显示日期
bar.add_xaxis(list(data_dict.keys()))
# 添加y轴数据,显示销售额
bar.add_yaxis("销售额",list(data_dict.values()),label_opts=LabelOpts(is_show=False))
bar.set_global_opts(
    title_opts=TitleOpts(title="每日销售额")
)
bar.render()

【分析】

这段代码读取了两个不同格式的销售数据文件(一个文本文件和一个JSON文件),合并了数据,计算了每日的销售额,并使用Pyecharts库进行了可视化。

运行后打开render.html文件并在浏览器中查看创建的柱状图。

程序实现流程:

  1. 定义数据类 Record 封装每条销售记录
  2. 设计抽象类 FileReader 定义文件读取接口,并实现两个子类 TextFileReader 和 JsonFileReader ,分别处理文本文件和 JSON 文件的读取逻辑。
  3. 进行数据需求的逻辑计算(计算每日销售额)
  4. 利用 Pyecharts 绘制柱状图展示销售数据

通过这种结构化的面向对象设计,代码结构分明,可维护性和可扩展性高。

0 人点赞