MatPlotLib入门|绘制图表:方便的统计学习时间

Netany ·
更新时间:2024-11-13
· 707 次阅读

1. 图表的目的:

作为一个老年多动症患者,在学习的时候走思去刷刷朋友圈看看B站动态似乎很难避免。明明脑子里还在思考着眼前MOOC的内容,但手却情不自禁的点开网页打开了知乎 (。≖ˇェˇ≖。)

为了改掉自己的这个毛病,我找到了手机上的Forest APP。这是一个简单好用的计时APP,当自己在学习的时候设定一个45分钟的时钟,这样在手情不自禁打开知乎的时候就会想到那个倒计时的时钟,阻止自己在走神的路上越走越远(๑•̀ㅂ•́)و✧

这个APP的计时功能是很好用,但我不是很喜欢它的统计页面:

一个条形图
在这里插入图片描述
这样的统计界面虽然看起来很好看,但却过于简陋了,并没有提供我们过多的信息。不会使用Excel的我,只好尝试使用Python解决这一问题了ヽ(✿゚▽゚)ノ

2. 准备工作 import matplotlib.pyplot as plt import json import datetime MOUTH = 3 FILENAME = 'DataOfMouth{}.json'.format(MOUTH)

这段代码是我们需要的库以及两个全局变量。

我们需要matplotlib库来画图,也需要json库来帮助我们保存数据。datetime让我们能方便的获得今天的时间,从而为我们的表格添加一些新内容。

由于我决定一次性绘制一个月的信息,所以我们指定一个变量MOUTH存储月份,我们想改变的时候也能快速的改变。我们在指定存储数据的文件时使用了format方法,在文件名中体现了月份信息。

3. 第一个函数:接受输入 def StartAndReceiveInfo(): '用于获取数据输入,对数据的准确性进行判断。' print('\n在输入数据前请确保您的数据是正确的,否则将产生不必要的后果. . . . . . \n') date_temp = int(input('请输入今天的日期:')) time_temp = int(input('请输入时长/分钟:')) print('\n请检查输入数据 . . . . . .\n') flag = int(input('若确定,请输入1;否则输入0:')) assert flag == 1,'请重启程序,确保数据正确性。' return date_temp,time_temp

这是我们的第一个函数。

其中的一些print()函数用来提醒自己输入数据时一定要准确。除了这些print()语句外,我们用了两个变量存储输入的日期和时长,例如APP上显示了今天的工作的时长是185分钟,那么我们就可以按照提示输入今天的信息和工作的时长。

之后我们又设置了一个强制的检查工作,要求用户检查一遍确认无误后输入1,再使用一个断言,保证在数据错误的时候能抛出Error、保证数据文件的正确性。

经过一些简单的检查,这个函数将返回获得的数据。

3. 第二个函数:初始化数据文件 def Initialize(): '用于初始化记录。' datas_dict = {} keys = [key for key in range(1,32)] values = [0 for _ in range(1,32)] for i in range(0,31): datas_dict[keys[i]] = values[i] with open(FILENAME,'x') as f_obj: f_obj.write(json.dumps(datas_dict))

如果我们第一次运行程序,或者换了一个月份,这些情况下我们实际上是没有数据文件的。我们需要进行一个简单的初始化。Python为我们提供了方便的散列表——字典类型。我们生成两个列表作为字典的键与值,其中,键自然是从1到31,对应了一个月的所有天数,而值在初始化的时候我们都设置为0。我们使用循环将这两个列表组合成字典。

之后,我们使用json库提供的dumps函数将字典转化为JSON文件格式,再写入到我们全局变量定义的路径的文件下。

4. 第三个函数:更新数据文件 def SaveData(today,time): '用于将单次输入的数据记录在文件中。' try: with open(FILENAME) as f_obj: pass except FileNotFoundError: Initialize() with open(FILENAME,'r') as f_obj: datas_dict = json.loads(f_obj.read()) datas_dict[str(today)] = time with open(FILENAME,'w') as f_obj: f_obj.write(json.dumps(datas_dict)) return datas_dict

首先,我们用一个try-except语句来尝试打开全局变量指定的路径的文件,如果抛出错误,说明我们需要进行一步初始化。这个结构帮助我们快速完成工作。

之后,我们将JSON格式的数据文件打开,使用json库提供的loads函数将其中存储的JSON格式的字典转换为Python格式,然后将函数的输入——输入的日期和对应的时间写入到字典。由于进行了JSON格式的转化,此时的字典的键是str类型,为了成功更新数据,我们也要将输入的日期转化为str格式。

更新完成后,我们将其重新写入数据文件中,同时利用return语句将字典传给其它函数。

5. 最后一个函数:绘图

这个函数看起来比较长,但其中涉及了matplotlib的基本用法,值得一读。我们将其分开展示:

def PlotChart(datas_dict): '将数据绘制成图表。' times_temp = list(datas_dict.values()) dates = list(datas_dict.keys()) times = [times_temp[i] / 60.0 for i in range(len(times_temp))] all_time = sum(times) max_time = max(times)

首先,我们将输入函数的字典分成两个列表,列表中分别包含了键与值,这是为绘图做准备。

同时,我们决定使用更加直观的小时表示时间,所以对值得列表用了除法。最后,我们使用sum()函数和max()函数来获得总的时间以及最大的时间,用来丰富图表信息。

plt.figure(figsize=(20,10)) plt.hlines(max_time, -1, 32,color='darkred',alpha=0.8,linestyle='-.') plt.text(x=-0.8,y=max_time,s='MAX',color='darkred',alpha=5) plt.hlines(8,-1,32,color='red',alpha=5,linestyle='-.') plt.text(x=-0.5,y=8.3,s='8h',color='red',alpha=5) plt.hlines(12,-1,32,color='red',alpha=5,linestyle='-.') plt.text(x=-0.8,y=12.3,s='12h',color='red',alpha=5) plt.plot(dates,times,color='deeppink',linestyle='--',marker='o',alpha=0.5) for date,time in zip(dates,times): plt.text(x=eval(date)-1.5,y=time+0.3,s='%.2f'%time,color='deeppink',alpha=1)

然后我们开始绘图:首先我们使用了figur函数创建了画布并在其中指定了画布大小,由于我们要展示一个月的数据,所以应该让画布尽量大一些。之后,我们要绘制一系列的水平线,使用hlines函数即可。我们分别在8、12以及最大时间处绘制了水平线,并指定了颜色参数color、透明度参数alpha以及线的形状参数linestyle。同时,我们也使用了text函数在水平线的附近标注了其含义。

完成这些用于丰富信息的工作之后,我们使用折线图绘制主要的内容:日期以及对应的工作时间,并且通过一个循环使用text函数来标记上对应的时间信息。为了使得标注的信息清楚,我们在指定其坐标是加上了一些值用来偏移、防止折现挡住文字。

其实,图表的主要部分是由上面的最后三行代码完成的,其它的只是一些信息的增添——不过这种可定制也是Python的乐趣。

now = datetime.date.today() plt.hlines(datas_dict[str(now.day)]/60.0,-1,32,color='orange',alpha=2,linestyle='-.') plt.text(x=-0.8,y=datas_dict[str(now.day)]/60.0,s='TODAY',color='orange',alpha=5) plt.scatter(str(now.day),datas_dict[str(now.day)]/60.0,color='orange')

接下来,我们又绘制了一条水平线,是今天的工作时长。我们使用datetime库获得今天的日期:其中的date.totay()给我们返回今天的日期信息对象,而对象的day属性则返回了今天的日期。在进行文字标注后,我们使用用来绘制散点的scatter函数将折线上今天的时间点加重。

plt.xlabel('dates') plt.ylabel('time') plt.axis([-1,32,-1,16]) plt.title('YOU HAVE WORK {:.2f}HOURS IN MOUTH{}'.format(all_time,MOUTH)) plt.grid(True) plt.savefig('ComeOn.png') plt.show()

最后,我们指定横坐标与纵坐标的标签、限制坐标范围以及指定图表标签。我们之前求了总的时间,图表的标题展现了这个信息。为了美观,我们将图表设置了网格。

剩下的工作只需要将这个图表保存以便我们可以方便的查看,同时使用show函数展示图片,同时将画布释放。

6. 最后的代码 if __name__ == "__main__": today,time = StartAndReceiveInfo() datas_dict = SaveData(today,time) PlotChart(datas_dict)

我们的函数之间的串联很简单,只需要三行代码。最终代码如下:

import matplotlib.pyplot as plt import json import datetime MOUTH = 3 FILENAME = 'DataOfMouth{}.json'.format(MOUTH) def StartAndReceiveInfo(): '用于获取数据输入,对数据的准确性进行判断。' print('\n在输入数据前请确保您的数据是正确的,否则将产生不必要的后果. . . . . . \n') date_temp = int(input('请输入今天的日期:')) time_temp = int(input('请输入时长/分钟:')) print('\n请检查输入数据 . . . . . .\n') flag = int(input('若确定,请输入1;否则输入0:')) assert flag == 1,'请重启程序,确保数据正确性。' return date_temp,time_temp def Initialize(): '用于初始化记录。' datas_dict = {} keys = [key for key in range(1,32)] values = [0 for _ in range(1,32)] for i in range(0,31): datas_dict[keys[i]] = values[i] with open(FILENAME,'x') as f_obj: f_obj.write(json.dumps(datas_dict)) def SaveData(today,time): '用于将单次输入的数据记录在文件中。' try: with open(FILENAME) as f_obj: pass except FileNotFoundError: Initialize() with open(FILENAME,'r') as f_obj: datas_dict = json.loads(f_obj.read()) datas_dict[str(today)] = time with open(FILENAME,'w') as f_obj: f_obj.write(json.dumps(datas_dict)) return datas_dict def PlotChart(datas_dict): '将数据绘制成图表。' times_temp = list(datas_dict.values()) dates = list(datas_dict.keys()) times = [times_temp[i] / 60.0 for i in range(len(times_temp))] all_time = sum(times) max_time = max(times) plt.figure(figsize=(20,10)) plt.hlines(max_time, -1, 32,color='darkred',alpha=0.8,linestyle='-.') plt.text(x=-0.8,y=max_time,s='MAX',color='darkred',alpha=5) plt.hlines(8,-1,32,color='red',alpha=5,linestyle='-.') plt.text(x=-0.5,y=8.3,s='8h',color='red',alpha=5) plt.hlines(12,-1,32,color='red',alpha=5,linestyle='-.') plt.text(x=-0.8,y=12.3,s='12h',color='red',alpha=5) plt.plot(dates,times,color='deeppink',linestyle='--',marker='o',alpha=0.5) for date,time in zip(dates,times): plt.text(x=eval(date)-1.5,y=time+0.3,s='%.2f'%time,color='deeppink',alpha=1) now = datetime.date.today() plt.hlines(datas_dict[str(now.day)]/60.0,-1,32,color='orange',alpha=2,linestyle='-.') plt.text(x=-0.8,y=datas_dict[str(now.day)]/60.0,s='TODAY',color='orange',alpha=5) plt.scatter(str(now.day),datas_dict[str(now.day)]/60.0,color='orange') plt.xlabel('dates') plt.ylabel('time') plt.axis([-1,32,-1,16]) plt.title('YOU HAVE WORK {:.2f}HOURS IN MOUTH{}'.format(all_time,MOUTH)) plt.grid(True) plt.savefig('ComeOn.png') plt.show() if __name__ == "__main__": today,time = StartAndReceiveInfo() datas_dict = SaveData(today,time) PlotChart(datas_dict)

这样,在每天完成学习任务后,利用自己的计时APP获得一天的工作时间,我们可以打开这个程序,输入自己的信息,获得统计图表。第一次使用,图表可能有些单薄,但使用时间长一点之后,这个图表能很好的反映我们的学习情况,激励我们去多学一点时间。Python提供的更多功能也能帮我们完善这个图表:在这里插入图片描述


作者:NumLock桌



统计学习 学习 统计学 matplotlib

需要 登录 后方可回复, 如果你还没有账号请 注册新账号