综合案例—面向对象+数据可视化

一、 案例简介

下面有2份文件,是某产品1月和2月的销售数据,我们需要对文件数据进行处理分析,计算每日的销售额并以柱状图表的形式进行展示。

(文件链接: https://pan.baidu.com/s/1FWQhkToiJT_xZfYGfIWyvQ?pwd=a2hi 提取码: a2hi )

文件数据格式如下图所示,1月销售数据是普通文本,使用逗号分割数据记录,从前到后分别是(日期,订单 id ,销售额,销售省份),2月销售数据是 JSON 数据,从前到后也是(日期,订单 id ,销售额,销售省份)。

回忆我们在综合案例---数据可视化---折线图、地图、柱状图中处理数据的步骤,现在我们要融合面向对象的思想去处理数据,思路如下:

二、读取数据与封装数据对象

2.1列表

我们要把读取处理完的数据放在一个(元素类型为类对象的)列表中,对象封装在类中,这个类对象的类命名为Record,对应操作: 新建模块"Record_define.py",定义类"Record",内容如下:

python 复制代码
class Record:

    def __init__(self,date,order_id,money,province):  #运用__init__构造方法,便于给类对象赋值
        self.date=date          #订单日期
        self.order_id=order_id  #订单ID
        self.money=money        #订单金融
        self.province=province  #销售省份

    def __str__(self):   #运用__str__构造方法,便于控制类对象转换为字符串
        return f'{self.date},{self.order_id},{self.money},{self.province}'

2.2读取数据

我们先定义一个抽象类FileReader用来做顶层设计,确定有哪些功能需要实现,需要实现成员方法read_data( ),用来读取文件的数据,将读到的每一条数据都转换为Record对象,将它们都封装到列表record_list内返回。

文件"2011年1月销售数据.txt"和"2011年2月销售数据JSON.txt"格式不同,需要具体情况具体分析。父类FileReader已经明确了需要有哪些功能实现,具体的方法实现,由子类去实现

子类TextFileReader 处理文件"2011年1月销售数据.txt",其以普通文本的格式存储数据,每行存储每日一个省份的销售数据,我们以readlines( )方法 读取文件(按照行的方式把整个文件中的内容一次性全部读取,返回一个列表,其中每一行的数据为一个元素),再使用split( )方法(字符串分割方法),把逗号作为分隔符,将订单日期,订单ID,订单金额,订单省份分隔开后放入类对象中,再把类对象放入列表中, 数据初步处理完成。

子类JSONFileReader处理文件"2011年2月销售数据JSON.txt",其以JSON格式存储数据,每行也是存储每日一个省份的销售数据。我们读取文件后需要先转换格式(将JSON格式数据转换为python数据格式),通过字典数据访问方式将订单日期,订单ID,订单金额,订单省份放入类对象中,再把类对象放入列表中, 数据初步处理完成。

对应操作: 新建模块"File_define.py",先定义抽象类"FileReader",再由子类TextFileReader和JSONFileReader具体实现对两种不同类型数据的处理,内容如下:

python 复制代码
import json
from Record_define import Record

# 先定义一个抽象类用来做顶层设计,确定有哪些功能需要实现
class FileReader:
    def read_data(self)->list[Record]:
        #读取文件的数据,将读到的每一条数据都转换为Record对象,将它们都封装到list内返回
        pass

#处理普通文本类型
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类对象的列表以存储数据
        record_list:list[Record]=[]
        for line in f.readlines():
            line= line.strip()  # 消除读取到的每一行数据中的\n
            list=line.split(',')
            record=Record(list[0],list[1],int(list[2]),list[3]) #必须将类Record中第三个成员变量强制转换为int类型,否则后面无法正常累加销售额
            record_list.append(record)

        f.close()
        return record_list

#处理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():
            dict_line=json.loads(line)
            record=Record(dict_line['date'],dict_line['order_id'],int(dict_line['money']),dict_line['province'])#必须将类Record中第三个成员变量强制转换为int类型,否则后面无法正常累加销售额
            record_list.append(record)
        f.close()
        return record_list
#仅供测试使用,找bug
if __name__=='__main__':
    text_file_reader = TextFileReader("E:/可视化案例数据/2011年1月销售数据.txt")
    json_file_reader = JSONFileReader("E:/可视化案例数据/2011年2月销售数据JSON.txt")
    list1 = text_file_reader.read_data()
    list2 = json_file_reader.read_data()

    for l in list1:
        print(l)

    for l in list2:
        print(l)

注意:

  • 在定义类TextFileReader中成员方法read_data( )时,有一行代码" line= line.strip() ",这是因为文件"2011年1月销售数据.txt"内每行数据的最后都有一个换行符,如果不去掉,换行符会被放入列表record_list中,作为一个个单独的元素被存储着,干扰后序数据处理,所以需要用strip( )方法消除读取到的每一行数据中的换行符"\n"。
  • 在将数据放入列表record_list前,即创建类对象record并传参时,一定要将订单金额强制转换为int类型,这样在模块"text.py"中计算当日总销售额时才能正常累加,如果忽略了这一步,销售额累加就会像字符串拼接一样,例如原本1+2=3,忽略了这一步就会变成1+2=12,会造成机械地拼接。

三、计算数据

把类设计完成后,新建模块"test.py",开始真正读取文件,将2个月份的数据合并为1个列表all_data来存储,然后计算数据,即求每日各个省份的销售额相加,步骤如下:

  • 首先准备一个字典,用来存储计算后的数据,其中key为日期,value为当日总销售金额(生成图表所需要的数据就是日期和当日总销售金额)。
  • 利用for循环,把列表all_data中每日各个省份的销售金额进行叠加。

代码如下:

python 复制代码
from File_define import TextFileReader, JSONFileReader
from Record_define import Record

#读取并处理数据
text_file_reader=TextFileReader('E:/可视化案例数据/2011年1月销售数据.txt')
json_file_reader=JSONFileReader("E:/可视化案例数据/2011年2月销售数据JSON.txt")
jan_data:list[Record]=text_file_reader.read_data()
feb_data:list[Record]=json_file_reader.read_data()
# 将2个月份的数据合并为1个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 #修改字典中key对应的value
    else:
        data_dict[record.date]=record.money  #新增字典元素

注意:for循环中的临时变量record是一个类对象。

四、绘图

处理完数据后开始绘图,X轴数据应为日期,我们需要把从字典中取出的全部日期数据转换成列表类型,以便程序正常运行,Y轴数据为当日销售金额,同理转换成列表类型。

python 复制代码
from pyecharts.charts import Bar
from pyecharts.options import *
#绘制图表
bar=Bar()#这样写也是在构建类对象
bar.add_xaxis(list(data_dict.keys()))  #添加X轴数据,将从字典中取出的全部日期数据转换成列表类型
bar.add_yaxis('销售额',list(data_dict.values()), label_opts=LabelOpts(is_show=False))  #添加Y轴数据,将从字典中取出的全部销售额数据转换成列表类型
bar.set_global_opts(
    title_opts=TitleOpts(title="每日销售额")
)
bar.render("每日销售额柱状图.html")

运行代码后生成的图表:

模块"text.py"的完整代码如下:

python 复制代码
from File_define import TextFileReader, JSONFileReader
from Record_define import Record
from pyecharts.charts import Bar
from pyecharts.options import *
from pyecharts.globals import ThemeType
#读取并处理数据
text_file_reader=TextFileReader('E:/可视化案例数据/2011年1月销售数据.txt')
json_file_reader=JSONFileReader("E:/可视化案例数据/2011年2月销售数据JSON.txt")
jan_data:list[Record]=text_file_reader.read_data()
feb_data:list[Record]=json_file_reader.read_data()
# 将2个月份的数据合并为1个list来存储
all_data: list[Record] = jan_data + feb_data

#计算数据,即求每日各个省份的销售额相加
data_dict={}  #创建字典,存储计算后的数据,日期:金额,例如:{"2011-01-01":1689,"2011-01-02":1532,......}
for record in all_data:
    if record.date in data_dict.keys():
        #当前日期已有记录,和老记录叠加
        data_dict[record.date]+=record.money #修改字典中key对应的value
    else:
        data_dict[record.date]=record.money  #新增字典元素

#绘制图表
bar=Bar()#这样写也是在构建类对象
bar.add_xaxis(list(data_dict.keys()))  #添加X轴数据,将从字典中取出的全部日期数据转换成列表类型
bar.add_yaxis('销售额',list(data_dict.values()), label_opts=LabelOpts(is_show=False))  #添加Y轴数据,将从字典中取出的全部销售额数据转换成列表类型
bar.set_global_opts(
    title_opts=TitleOpts(title="每日销售额")
)
bar.render("每日销售额柱状图.html")

五、总结

用面向对象思想去实现数据可视化最大的特点就是:把具体处理文件数据的操作步骤封装在类中,使用时直接调用。

从本案例中不难看出面向对象的3 大特性:封装、继承、多态。

  • 把具体处理文件数据的操作步骤封装在类中,可供多次调用。
  • 在模块"File_define.py"中先定义了一个抽象类FileReader,用来做顶层设计,FileReader作为父类,其中成员方法read_data()并不进行详细定义,而是在子类TextFileReader和JSONFileReader去详细定义了read_data(),即进行了复写。
  • 同样是源自父类FileReader,在模块"test.py"中调用处理1月销售数据和2月销售数据时,得到了不同的数据,同样的行为(函数),传入不同的对象,得到不同的状态,这体现了"多态"。
相关推荐
小魏冬琅9 分钟前
探索面向对象的高级特性与设计模式(2/5)
java·开发语言
lihao lihao11 分钟前
C++stack和queue的模拟实现
开发语言·c++
TT哇23 分钟前
【Java】数组的定义与使用
java·开发语言·笔记
天天进步201528 分钟前
Lodash:现代 JavaScript 开发的瑞士军刀
开发语言·javascript·ecmascript
假装我不帅37 分钟前
js实现类似与jquery的find方法
开发语言·javascript·jquery
look_outs41 分钟前
JavaSE笔记2】面向对象
java·开发语言
萧鼎41 分钟前
【Python】高效数据处理:使用Dask处理大规模数据
开发语言·python
互联网杂货铺1 小时前
Python测试框架—pytest详解
自动化测试·软件测试·python·测试工具·测试用例·pytest·1024程序员节
Ellie陈1 小时前
Java已死,大模型才是未来?
java·开发语言·前端·后端·python
@嘿1111 小时前
【Java】static静态变量(016)
java·开发语言