新手必备!以制作交易收盘价走趋图为例,来可视化处理json格式的文件

在这里,我们将会用json模块来处理json格式文件。Pygal提供了一个适合初学者使用的绘图工具,我们在这里将使用它来对收盘价数据进行可视化,以帮助我们掌握基础技能。(本文所需要的文件都在资源中,记得要把文件下载到运行代码的相同文件夹下)

import json
import pygal

filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_date = json.load(f)
#每一天的信息
for btc_dict in btc_date:
	date=btc_dict['date']
	month=btc_dict['month']
	week=btc_dict['week']
	weekdays=btc_dict['weekday']
	close=btc_dict['close']

首先导入模块json,然后load()读取文件,将数据存储到btc_date中,之后遍历btc_date中每个元素。每个元素都是字典,包含五个键-值对,btc_dict用来存储字典中的每个键-值对。接下来,我们提取出所有键的值,并将日期、月份、周数、周几和收盘价相关联的值分别存储到列表中(可以输入print("{} is month {} week {},{} the close priceis{}RMB".format(date,month,week,weekday,close))来确定是否正确,会输出下图)
在这里插入图片描述

这就是检验得到的结果啦(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦

import json
import pygal

filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_date = json.load(f)
#创建五个列表
dates=[]
months=[]
weeks=[]
weekdays=[]
close=[]
#每一天的信息
for btc_dict in btc_date:
	dates.append(btc_dict['date'])
	months.append(int(btc_dict['month']))
	weeks.append(int(btc_dict['week']))
	weekdays.append(btc_dict['weekday'])
	close.append(int(float(btc_dict['close'])))

btc_close_2017.json中的每个键和值都是字符串。为了能和后面的内容中对交易数据进行计算,需要将表示月数、周数和收盘价的字符串转化为数值类型(敲黑板注意:close里存储的是带小数点的数,所以需要先将字符串转化为浮点型,然后再转化为整型,不能直接转换)。之后我们创建几个列表来存储数据。遍历btc_date,将转化为合适格式的数据存储到对应的列表中。(这里就不进行检验了,小伙伴们记得别出错哦)(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦~)

import json
import pygal

filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_date = json.load(f)
#创建五个列表
dates=[]
months=[]
weeks=[]
weekdays=[]
close=[]
#每一天的信息
for btc_dict in btc_date:
	dates.append(btc_dict['date'])
	months.append(int(btc_dict['month']))
	weeks.append(int(btc_dict['week']))
	weekdays.append(btc_dict['weekday'])
	close.append(int(float(btc_dict['close'])))

line_chart = pygal.Line(x_label_rotation=22,show_minor_x_labels = False)
line_chart.title='收盘价变换(¥)'
line_chart.x_labels = dates
N=20#每隔20天显示一次
line_chart.x_labels_major = dates[::N]
line_chart.add('收盘价',close)
line_chart.render_to_file('收盘价折线图(¥).svg')

首先导入pygal模块,再然后创建Line实例时,分别设置了x_label_rotation与show_minor_x_labels作为初始化参数。x_label_rotation = 20让x轴上的时期标签顺时针旋转22°,show_minor_x_labels = False则表示图形不用显示所有的x轴标签。
title()设置图形标题,x_labels()设置了x轴的标签。我们配置x_labels_major属性,让坐标轴每隔20天显示一次,这样x轴就不会显得拥挤了。render_to_file()会在该代码文件夹中生成svg格式文件,用游览器就可以看。最终效果图如下:
在这里插入图片描述
从图中我们可以看出,价格从2017年11月12日到2017年12月12日快速增长,平均每天增值约2500元人民币。总体趋势是非线性的,而且增长幅度不断增大,似乎呈指数分布。我们还发现,在每个季度末(3,6,9月)似乎有一些相似的波动。尽管呗增长的趋势所掩盖,不过其中也许有周期性。为了验证周期性的假设,需要先将非线性的趋势消除。(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦~)

import json
import pygal
import math

filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_date = json.load(f)
#创建五个列表
dates=[]
months=[]
weeks=[]
weekdays=[]
close=[]
#每一天的信息
for btc_dict in btc_date:
	dates.append(btc_dict['date'])
	months.append(int(btc_dict['month']))
	weeks.append(int(btc_dict['week']))
	weekdays.append(btc_dict['weekday'])
	close.append(int(float(btc_dict['close'])))

line_chart = pygal.Line(x_label_rotation=20,show_minor_x_labels = False)
line_chart.title='收盘价对数变换(¥)'
line_chart.x_labels = dates
N=20#每隔20天显示一次
line_chart.x_labels_major = dates[::N]
close_log= [math.log10(_) for _ in close]
line_chart.add('log收盘价',close_log)
line_chart.render_to_file('收盘价对数变换折线图(¥).svg')

首先导入模块math,将列表close里的值都取对数(这里用以10为底的对数函数,math.log10计算收盘价)赋给close_log,运行程序会出现下图:
在这里插入图片描述
现在,用对数变换剔除非线性趋势后,整体上涨的趋势更接近线性增长。从图中我们可以清晰的看出,收盘价在每个季度末似乎有显著的周期性——3月、6月和9月都出现了剧烈的波动。那么,12月是否也会出现这种现象呢?让我们来看一下收盘价的月日均值和周日均值(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦~)

import json
import pygal
import math
from itertools import groupby

filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_date = json.load(f)
#创建五个列表
dates=[]
months=[]
weeks=[]
weekdays=[]
close=[]
#每一天的信息
for btc_dict in btc_date:
	dates.append(btc_dict['date'])
	months.append(int(btc_dict['month']))
	weeks.append(int(btc_dict['week']))
	weekdays.append(btc_dict['weekday'])
	close.append(int(float(btc_dict['close'])))

def draw_line(x_date,y_date,title,y_legend):
	xy_map=[]
	for x,y in groupby(sorted(zip(x_date,y_date)),key=lambda _: _[0]):
		y_list=[v for _ ,v in y]
		""" 与该行代码相等
		y_list=[]
			for _,v in y:
   			 	y_list.append(v)"""
		xy_map.append([x,sum(y_list)/len(y_list)])
	x_unique,y_mean =[*zip(*xy_map)]
	line_chart=pygal.Line()
	line_chart.title = title
	line_chart.x_labels = x_unique
	line_chart.add(y_legend,y_mean)
	line_chart.render_to_file(title+'.svg')
	return line_chart

idx_month = dates.index('2017-12-01')
line_chart_month = draw_line(months[:idx_month],close[:idx_month],'收盘价月日均值(¥)','月日均值')
line_chart_month

利用文件中的数据,绘制2017年前11个月的日均值。我们将之前的绘图代码封装成函数,以便重复利用。
首先,我们导读Python标准库中模块itertools的函数groupby,(合并)zip()将两个列表压缩成元组的列表后,(排序)sorted将这个列表排序,(分组)再用groupby将其分组(下划线表示临时变量,仅用一次之后销毁,这里指代),lambda函数用于指定对列表中所有元素进行排序的准则(标准形式:lambda argument_list: expression,lambda函数有输入和输出:输入是传入到参数列表argument_list的值,输出是根据表达式expression计算得到的值。)
for循环条件中,zip(x_data, y_data)表示将传入的日期列表months和收盘价列表close,分别按顺序各取一个元素打包成元组列表组合成一个新的迭代器,即[(1,6928), (1,7070) …… (11,65583)],紧接着第二层的sorted函数对元组列表进行排序,得到了按照月份从小到大,同一月份的收盘价从小到大排序的元组列表[(1, 5383), (1,5566) ,(1,6928), (1,7070) …(11,65583)]。第三层的groupby函数,是一个分组聚合函数,key=lambda _: _[0]是用匿名函数。key=lambda _: _[0]就表示取列表中索引为[0]的值,并将返回值赋给key,key这个表达式表示groupby分组的准则,意思是必须按照元组列表的第一个元素进行分类。每循环一次,得到一组数据,x就是分类的key值,循环十一次,y则是对应的元组列表,得到:
1 [(1,5383), (1,5566) …… (1,7835)]
2 [(2,6793), (2,6811) …… (2,8206)]
y_list = [v for _, v in y]———
通过列表生成式,将元组列表中的值取出,形成一个新的列表赋给y_list。
sum(y_list)/len(y_list)———
计算出每个月的平均收盘价,与x一起添加到xy_map中,得到xy_map=[[1, 6285.870967741936], [2, 7315.714285714285], [3, 7789.032258064516], [4, 8390.466666666667], [5, 12963.935483870968], [6, 18092.166666666668], [7, 17146.16129032258], [8, 26092.645161290322], [9, 26865.633333333335], [10, 35460.67741935484], [11, 51436.166666666664]]。
x_unique, y_mean = [*zip(*xy_map)]———
zip函数的逆过程,可将zip函数处理后的结果恢复到之前的样子,所以它将xy_map中每个元组中的第一个元素取出,赋给x_unique,所以我们有x_unique=(1,2,3,4,5,6,7,8,9,10,11),第二个元素取出,赋给y_mean,我们有y_mean=(6285.870967741936, 7315.714285714285, 7789.032258064516, 8390.466666666667, 12963.935483870968, 18092.166666666668, 17146.16129032258, 26092.645161290322, 26865.633333333335, 35460.67741935484, 51436.166666666664)。
由于2017年12月的数据并不完整,我们只取2017年1月到11月的数据,通过index()函数在dates列表内查找2017-12-01的索引位置,确定周数和收盘价的取值范围。运行代码,收盘价月日均值如下图:
在这里插入图片描述
从图中我们可以看出,除了7月相比下个月有所下降,其他个月都是增长的。11月相比10月的增幅非常惊人,月日均值增长了45%
接下来绘制前49周的日均值(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦~)

import json
import pygal
import math
from itertools import groupby

filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_date = json.load(f)
#创建五个列表
dates=[]
months=[]
weeks=[]
weekdays=[]
close=[]
#每一天的信息
for btc_dict in btc_date:
	dates.append(btc_dict['date'])
	months.append(int(btc_dict['month']))
	weeks.append(int(btc_dict['week']))
	weekdays.append(btc_dict['weekday'])
	close.append(int(float(btc_dict['close'])))

def draw_line(x_date,y_date,title,y_legend):
	xy_map=[]
	for x,y in groupby(sorted(zip(x_date,y_date)),key=lambda _: _[0]):
		y_list=[v for _ ,v in y]
		""" 与该行代码相等
		y_list=[]
			for _,v in y:
   			 	y_list.append(v)"""
		xy_map.append([x,sum(y_list)/len(y_list)])
	x_unique,y_mean =[*zip(*xy_map)]
	line_chart=pygal.Line()
	line_chart.title = title
	line_chart.x_labels = x_unique
	line_chart.add(y_legend,y_mean)
	line_chart.render_to_file(title+'.svg')
	return line_chart

idx_week = dates.index('2017-12-11')
line_chart_week = draw_line(weeks[1:idx_week ],close[1:idx_week],'收盘价周日均值(¥)','周日均值')
line_chart_week

2017年1月1日是周日,归属为2016年第52周,所以2017年的第一周从2017年1月2日开始,2017年12月10日为第49周周日,因此我们通过index()函数在dates列表中查找2017-12-11的索引位置,确定周数和收盘价的取数范围。运行代码如下图所示:
在这里插入图片描述
最后绘制每周各天的天数(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦~)

import json
import pygal
import math
from itertools import groupby

filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_date = json.load(f)
#创建五个列表
dates=[]
months=[]
weeks=[]
weekdays=[]
close=[]
#每一天的信息
for btc_dict in btc_date:
	dates.append(btc_dict['date'])
	months.append(int(btc_dict['month']))
	weeks.append(int(btc_dict['week']))
	weekdays.append(btc_dict['weekday'])
	close.append(int(float(btc_dict['close'])))

def draw_line(x_date,y_date,title,y_legend):
	xy_map=[]
	for x,y in groupby(sorted(zip(x_date,y_date)),key=lambda _: _[0]):
		y_list=[v for _ ,v in y]
		""" 与该行代码相等
		y_list=[]
			for _,v in y:
   			 	y_list.append(v)"""
		xy_map.append([x,sum(y_list)/len(y_list)])
	x_unique,y_mean =[*zip(*xy_map)]
	line_chart=pygal.Line()
	line_chart.title = title
	line_chart.x_labels = x_unique
	line_chart.add(y_legend,y_mean)
	line_chart.render_to_file(title+'.svg')
	return line_chart

idx_week = dates.index('2017-12-11')
wd = ['Monday','Tuesday','Wednesday','Thuresday','Friday','Saturday','Sunday']
weekdays_int = [wd.index(w)+ 1 for w in weekdays[1:idx_week]]
line_chart_weekday = draw_line(weekdays_int ,close[1:idx_week],'收盘价星期均值折线图(¥)','星期均值')
line_chart_weekday.x_labels = ['周一','周二','周三','周四','周五','周六','周日']
line_chart_weekday.render_to_file('收盘价星期均值折线图(¥).svg')
line_chart_weekday

由于这里的周几是字符串,按周一到周日的顺序排列。另外,原来的周几都是英文单词,这里将他们调整为中文。
首先,我们列出一周7天的英文单词,然后将weekdays的内容替换成1~7的整数(遍历weekdays列表,输出w,然后通过index()函数将wd列表w对应的值的索引求出来,后来+1变成1—7),然后,将图片x轴的标签替换为中文,最终输出下图:
在这里插入图片描述
已经为交易收盘价绘制了五幅图,分别是收盘价变换、收盘价对数变换、收盘价月日均值、收盘价周日均值和收盘价星期均值。每个SVG文件打开之后都是独立的页面。将他们整合在一起进行管理、监督、分析,新的图表也可以加入进来,形成一个数据仪表盘(dashboard)。下面让我们将前面绘制的图整合起来,做一个收盘价数据仪表盘。(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦~)

import json
import pygal
import math
from itertools import groupby

# 将数据加载到一个列表中
filename = 'btc_close_2017.json'
with open(filename) as f:
	btc_data = json.load(f)

# 创建5个列表,分别存储日期和收盘价
dates = []
months = []
weeks = []
weekdays = []
close = []
# 每一天的信息
for btc_dict in btc_data:
	dates.append(btc_dict['date'])
	months.append(int(btc_dict['month']))
	weeks.append(int(btc_dict['week']))
	weekdays.append(btc_dict['weekday'])
	close.append(int(float(btc_dict['close'])))

line_chart = pygal.Line(x_label_rotation=20, show_minor_x_labels=False) 
line_chart.title = '收盘价(¥)'
line_chart.x_labels = dates
N = 20  # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]  
line_chart.add('收盘价', close)
line_chart.render_to_file('收盘价折线图(¥).svg')


line_chart = pygal.Line(x_label_rotation=20, show_minor_x_labels=False)
line_chart.title = '收盘价对数变换(¥)'
line_chart.x_labels = dates
N = 20  # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N]
close_log = [math.log10(_) for _ in close] 
line_chart.add('log收盘价', close_log)
line_chart.render_to_file('收盘价对数变换折线图(¥).svg')
line_chart


def draw_line(x_data, y_data, title, y_legend):
	xy_map = []
	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)] 
	line_chart = pygal.Line()
	line_chart.title = title
	line_chart.x_labels = x_unique
	line_chart.add(y_legend, y_mean)
	line_chart.render_to_file(title + '.svg')
	return line_chart


idx_month = dates.index('2017-12-01')
line_chart_month = draw_line(
	months[:idx_month], close[:idx_month], '收盘价月日均值(¥)', '月日均值')
line_chart_month


idx_week = dates.index('2017-12-11')
line_chart_week = draw_line(
	weeks[1:idx_week], close[1:idx_week], '收盘价周日均值(¥)', '周日均值')
line_chart_week


idx_week = dates.index('2017-12-11')
wd = ['Monday', 'Tuesday', 'Wednesday',
		'Thursday', 'Friday', 'Saturday', 'Sunday']
weekdays_int = [wd.index(w) + 1 for w in weekdays[1:idx_week]]
line_chart_weekday = draw_line(
	weekdays_int, close[1:idx_week], '收盘价星期均值(¥)', '星期均值')
line_chart_weekday.x_labels = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
line_chart_weekday.render_to_file('收盘价星期均值(¥).svg')
line_chart_weekday

with open('收盘价Dashboard.html', 'w', encoding='utf8') as html_file:
	html_file.write(
		'<html><head><title>收盘价Dashboard</title><meta charset="utf-8"></head><body>\n')
	for svg in  [
			'收盘价折线图(¥).svg', '收盘价对数变换折线图(¥).svg', '收盘价月日均值(¥).svg',
			'收盘价周日均值(¥).svg', '收盘价星期均值(¥).svg'
	]:
		html_file.write(                                       
			'    <object type="image/svg+xml" data="{0}" height=500></object>\n'.format(svg))
	html_file.write('</body></html>')

运行程序,得到一个完整的网页(HTML文件)。首先,创建一个网页文件(Dashboard.html),然后将每幅图都添加到页面中。这里设置SVG的默认高度为500像素,由于SVG格式文件是矢量图,所以可以通过放大或缩小网页来调整视觉效果。最终效果如下图所示:
在这里插入图片描述
在这里插入图片描述

以上就是我整理的关于可视化处理json格式文件的方法。(整理不易啊,滑稽脖子不敢动了难受)(哒哒如果有任何不懂,或者是运行得不到正确结果的都可以私信我,记得关注哦)(您的关注,就是对我最大的鼓励!

猜你喜欢

转载自blog.csdn.net/zhu_rui/article/details/105349181
今日推荐