本例数据是有346个字典元素的列表形式的数据,列表中每个字典代表该列表的一个元素,每个字典内容为一天的有关股价的数据包括当天日期,当天所在月份,当天所在周,所在天以及当天股价,每个字典五个键-值对,而这种字典有346个,就构成了一个列表,所以数据就是346天的有关这5个信息的json格式数据。格式如下;
[{'date': '2017-01-01', 'month': '01', 'week': '52', 'weekday': 'Sunday', 'close': '6928.6492'},.........,{'date': '2017-12-12', 'month': '12', 'week': '50', 'weekday': 'Tuesday', 'close': '113732.6745'}]
本文章选取对该数据收盘价月日均值的可视化作为例子解释其中遇到的一个问题。
import json
filename='btc_close_2017.json'
with open(filename) as f:#读取数据
btc_data=json.load(f)#加载数据
#为对数据加工作准备,用于存储数据的不同信息
dates=[]
months=[]
weeks=[]
weekdays=[]
close=[]
#遍历列表获取每天有关信息,总共循环346次
for btc_dict in btc_data:# btc_dict代表其中一个字典
#将获取的每个字典信息进行整理,循环结束后每个列表都会有346个同类信息
dates.append(btc_dict['date'])#346个日期
months.append(int(btc_dict['month']))#346个月份
weeks.append(int(btc_dict['week']))#346个周数
weekdays.append(btc_dict['weekday'])#346个天名
close.append(int(float(btc_dict['close'])))#346个股价(字符串类型小数点数字先浮点化再正数化)
import pygal#加载可视化工具库
from itertools import groupby#加载分组工具
#定义画图函数,有4个参数
def draw_line(x_data,y_data,title,y_legend):
xy_map=[]#为存储所需横纵坐标值设空list
for x, y in groupby(sorted(zip(x_data, y_data)), key=lambda _: _[0]):#对所给数据组合排序分组
y_list=[v for _,v in y]
xy_map.append([x,sum(y_list)/len(y_list)])
x_unique,y_mean=[*zip(*xy_map)]
#函数可视化部分
linechart=pygal.Line()
linechart.title=title
linechart.x_labels=x_unique
linechart.add(y_legend,y_mean)
linechart.render_to_file(title+'.svg')
return linechart
#带入实参
idx_month=dates.index('2017-12-01')#2017年12有关数据不完整,所以选取其他11月的数据,其中idx_month回复'2017-12-01'在dates列表中的索引334
linechart_month=draw_line(months[:idx_month],close[:idx_month],'收盘价月日均值(¥)',
'月日均值')#传入参数时选取前335个月份数,前335个股价以及其他两个实参
linechart_month#显示图画
想必大家对其中对函数前半部分有一定疑惑🤔!我在这大概解释一下其中原理!
def draw_line(x_data,y_data,title,y_legend):
xy_map=[]#为存储所需横纵坐标值设空list
for x, y in groupby(sorted(zip(x_data, y_data)), key=lambda _: _[0]):#对所给数据组合排序分组
y_list=[v for _,v in y]
xy_map.append([x,sum(y_list)/len(y_list)])
x_unique,y_mean=[*zip(*xy_map)]
首先传入实参,本例中传入335个月份名(每个月都重复多次)和与其一一对应的335个股价数字以及其他两个实参。
传入参数后,进入函数执行部分:
第一步:通过zip()函数对335个月份和股价进行组合,形式为(1,6929),共形成335个元组。
第二步:通过sorted函数335对元组按月份大小进行升序排序。[(1,6929),(1,7070),.........,(6,16694),.......,(11,65583)]
第三步:根据月份对排序好的结果分组
key=lambda _: _[0]的意思是分组依据为月份,即以[(1,6929),(1,7070),.........,(6,16694),.......,(11,65583)]内元组元素的的第一个作为值作为分组依据(这里的下划线代表列表内的元组,可以由其他字母替代,但不能省略)。
分组结果为[(1,[(1,6929),...,(1,6658)]),...,(11,[(11,44572),...,(11,65583)])]
(在这儿说明一下lambda函数用法:lambda函数意思主要是对给定的元素采取一定的措施,其中lambda 后面的下划线代表已有数据,而冒号后面的包含下划线的表达式就是对表达式要采取的措施。)
第四步:根据第三部,该例子中x对应的是对应组数,从1到11;y代表每个月月份与股价组成的元组构成的列表,总共11个循环11个列表。
第一个循环的 y=[(1,6929),...,(1,6658)]
第五步:y_list=[v for _,v in y]
其中y代表各月份的列表,比如[(1,6929),...,(1,6658)]代表1月份的股价数据。
这一步中下划线代表的就是y的每个元组元素的第一个值,因为在这不需要元组第一个值,所以用下划线代表该值,而第二个值则是我们需要的数据,因此用v变量来代表。(其中下划线可以用其他字母代替,但是不能省略,这是由数据结构决定的)
所以第一次循环的
x=1
y=[(1,6929),...,(1,6658)]
y_list=[6929,.......,6658]
第六步:
紧接着计算第一个循环的月均值并加入已有空列表。因此跑完循环后xy_map是由月份和对应月均值组成的列表组成的列表。
[[1, 6285.87], [2, 7315.71], [3, 7789.03], [4, 8390.47], [5, 12963.94], [6, 18092.17], [7, 17146.16], [8, 26092.65], [9, 26865.63], [10, 35460.68], [11, 51436.17]]
下一步,通过zip函数对xy_maplie列表的月份和均值数据进行重新组合,结果为如下:
[(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),(6285.87, 7315.71, 7789.03, 8390.47, 12963.94, 18092.17, 17146.16, 26092.65, 26865.63, 35460.68, 51436.17)]
因此x_unique代表的是月份构成的元组,y_mean代表11个月份的股价均值构成的元组。
本例可视化结果如下:
其他周均值和日均值等可以修改实参来获取相应可视化结果。