python基础-下载解析JSON文件并使用pygal绘制折线图
下载收盘价数据(内置urlopen)
下面是一个下载收盘价数据的脚本:
from __future__ import (absolute_import, division, print_function, unicode_literals)
# 使用try实现兼容2x和3x
try:
# python 2x版本
from urllib2 import urlopen
# ImportError可以作为判断PY版本的方式
except ImportError:
# python 3x版本
from urllib.request import urlopen
import json
json_url = 'https://raw.githubusercontent.com/muxuezi/btc/master/btc_close_2017.json'
# urlopen执行后 便会向服务器发请求
response = urlopen(json_url)
# 读取请求到的数据
req = response.read()
# 将数据写入文件
with open('btc_close_2017_urllib.json', 'wb') as f:
f.write(req)
# 加载下载的json 将文件内容转换成py能够处理的格式
file_urllib = json.loads(req)
print(file_urllib)
__future__
在 Python 里,__future__
是一个内置模块,它的主要作用是让开发者在旧版本的 Python 中使用未来版本 Python 才会有的新特性。__future__
模块来提供一个过渡机制,使得开发者可以在旧版本中提前体验和使用这些新特性。
__future__常见特性及示例:
print_function
在 Python 2 中,print
是一个语句;而在 Python 3 中,print
变成了一个函数。使用__future__
模块可以在 Python 2 中使用 Python 3 的print
函数语法。
# Python 2 代码示例
from __future__ import print_function
print('Hello, World!')
在上述代码中,通过导入print_function
,在 Python 2 里也能像 Python 3 那样使用print
函数,需要用括号来调用。
division
Python 2 里,整数相除默认进行截断除法;Python 3 中则是真除法。借助__future__
模块可以在 Python 2 中实现 Python 3 的真除法。
# Python 2 代码示例
from __future__ import division
result = 5 / 2
print(result) # 输出 2.5
在导入division
后,5 / 2
的结果就不再是截断后的整数2
,而是真除法的结果2.5
。
absolute_import
Python 2 中默认的导入机制存在相对导入的问题,可能会优先导入当前目录下与标准库同名的模块。使用absolute_import
可以让import
语句默认使用绝对导入。
# Python 2 代码示例
from __future__ import absolute_import
import math # 会优先从标准库中导入 math 模块
unicode_literals
Python 2 中字符串默认是字节串,要创建 Unicode 字符串需加u
前缀;Python 3 中字符串默认就是 Unicode 字符串。在 Python 2 中使用unicode_literals
可以让字符串字面量默认解释为 Unicode 字符串。
# Python 2 代码示例
from __future__ import unicode_literals
s = '你好'
print(type(s)) # 输出 <type 'unicode'>
from__future__import
from__future__import(absolute_import, division, print_function, unicode_literals) 解释如下:
它的作用是从__future__
模块中导入一些特定的功能,以实现 Python 2 和 Python 3 之间的兼容性,或者在 Python 2 中提前使用 Python 3 的某些特性。
1.absolute_import
- Python 2 中的默认行为:在 Python 2 中,当你使用
import
语句导入模块时,如果当前目录下有一个与标准库模块同名的文件,Python 会优先导入当前目录下的文件,而不是标准库中的模块。这种行为被称为相对导入,可能会导致一些意外的问题。 absolute_import
的作用:导入absolute_import
后,import
语句将默认使用绝对导入,即优先从标准库和sys.path
中指定的路径中查找模块。如果需要使用相对导入,需要使用显式的相对导入语法(如from . import module
)。# Python 2 中未导入 absolute_import # 当前目录下有一个名为 math.py 的文件 import math # 会优先导入当前目录下的 math.py 文件 # 导入 absolute_import 后 from __future__ import absolute_import import math # 会导入标准库中的 math 模块
2.division
- Python 2 中的默认行为:在 Python 2 中,整数除法(
/
)会截断结果,只保留整数部分。例如,5 / 2
的结果是2
,而不是2.5
。 division
的作用:导入division
后,/
运算符将执行真除法,即无论操作数是整数还是浮点数,都会返回一个浮点数结果。如果需要执行截断除法,可以使用//
运算符。# Python 2 中未导入 division result = 5 / 2 print(result) # 输出 2 # 导入 division 后 from __future__ import division result = 5 / 2 print(result) # 输出 2.5
print_function
- Python 2 中的默认行为:在 Python 2 中,
print
是一个语句,而不是一个函数。你可以直接使用print
后跟要输出的内容,中间用空格分隔,例如print 'Hello, World!'
。 print_function
的作用:导入print_function
后,print
变成了一个函数,需要使用括号来调用,就像 Python 3 中的用法一样。例如,print('Hello, World!')
。# Python 2 中未导入 print_function print 'Hello, World!' # 可以正常使用 # 导入 print_function 后 from __future__ import print_function print('Hello, World!') # 必须使用括号调用
4.unicode_literals
- Python 2 中的默认行为:在 Python 2 中,字符串字面量默认是字节串(
str
类型),而不是 Unicode 字符串。如果需要创建 Unicode 字符串,需要在字符串前面加上u
前缀,例如u'你好'
。 unicode_literals
的作用:导入unicode_literals
后,所有的字符串字面量都会被解释为 Unicode 字符串,而不需要显式地添加u
前缀。# Python 2 中未导入 unicode_literals s = '你好' # 这是一个字节串 print(type(s)) # 输出 <type 'str'> # 导入 unicode_literals 后 from __future__ import unicode_literals s = '你好' # 这是一个 Unicode 字符串 print(type(s)) # 输出 <type 'unicode'>
如果要实现2与3的兼容脚本,本例中的__future__ 是标准写法。
使用requests下载
requests
是一个第三方库,用于发送 HTTP 请求,它并不是 Python 标准库的一部分,所以需要单独安装。
使用pip安装:
pip install requests
先看一个错误的示例:
import requests
json_url = 'https://raw.githubusercontent.com/muxuezi/btc/master/btc_close_2017.json'
req = requests.get(json_url)
# 将数据写入文件
with open('btc_close_2017_request.json', 'wb') as f:
f.write(req.text)
file_requests = res.json()
requests通过get向服务器发送请求,并将响应结果存在req中,req.text可以直接读取文件数据(格式是字符串)。
req.json() 可以将文件数据转换成py列表file_requests。
但是使用上面代码的这个例子,会报错:
Traceback (most recent call last):
File "D:\python-work\py-bigdata\json_download_requests.py", line 9, in <module>
f.write(req.text)
TypeError: a bytes-like object is required, not 'str'
这个错误TypeError: a bytes-like object is required, not 'str'
是因为你以二进制写入模式('wb'
)打开文件,而req.text
返回的是一个字符串(str
类型),在二进制写入模式下,文件对象的write
方法需要的是字节类型(bytes
类型)的数据。
所以要解决这个问题有两种方法,分别是使用'wb'二进制打开,然后也写入二进制;再是使用文本模式打开,再写入文本。
使用二进制模式写入
使用 req.content 代替 req.text,req.content
返回的是响应内容的二进制形式(bytes
类型),适合以二进制模式写入文件。
import requests
json_url = 'https://raw.githubusercontent.com/muxuezi/btc/master/btc_close_2017.json'
req = requests.get(json_url)
# 将数据写入文件
with open('btc_close_2017_request.json', 'wb') as f:
f.write(req.content)
file_requests = req.json()
print(file_requests)
以文本模式打开文件
如果你想继续使用req.text
,可以将文件以文本模式('w'
)打开,同时指定合适的编码(通常是'utf-8'
)。
import requests
json_url = 'https://raw.githubusercontent.com/muxuezi/btc/master/btc_close_2017.json'
req = requests.get(json_url)
# 将数据写入文件
with open('btc_close_2017_request.json', 'w', encoding='utf-8') as f:
f.write(req.text)
file_requests = req.json()
print(file_requests)
建议使用第一种方法,因为它能避免一些潜在的编码问题,并且对于大多数网络请求响应内容的保存来说是更安全和通用的做法。
最终打印出来的列表如下所示:
[
{'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'}
]
从文件中读取并解析JSON
解析JSON文件为列表
我们下载文件到本地后,就可以加载文件并解析了:
import json
# 将数据加载到一个列表中
filename = 'btc_close_2017_request.json'
with open(filename) as f:
btc_data = json.load(f)
# 打印每一天的信息 btc_dict存储字典中每个键值对
for btc_dict in btc_data:
date = btc_dict['date']
month = btc_dict['month']
week = btc_dict['week']
weekday = btc_dict['weekday']
close = btc_dict['close']
print("{}月 {} 周 {}, {}, 闭市价 {} RMB" . format(date, month, week, weekday, close))
json.load(f):将文件对象中的JSON数据解码为列表
format:是一个强大的字符串方法,用于格式化字符串。它能把变量的值插入到字符串的特定位置,进而生成格式化的输出。
可以使用大括号{}
当作占位符,然后按照顺序在format()
方法中传入参数。比如,使用使用位置参数写法:
name = "Alice"
age = 25
print("My name is {} and I am {} years old.".format(name, age))
关键字参数:你能够在大括号里指定关键字,然后在format()
方法中使用关键字参数。
print("My name is {name} and I am {age} years old.".format(name="Bob", age=30))
索引参数:可以在大括号中指定索引,索引从 0 开始。{charlie}对应的就是20,{0}对应的 20
print("{1} is {0} years old.".format(20, "Charlie")) // Charlie is 20 years old.
结合字典使用:当有字典数据时,可以利用**
解包字典,然后通过键来引用值。
person = {'name': 'David', 'age': 35}
print("My name is {name} and I am {age} years old.".format(**person)) // My name is David and I am 35 years old.
自 Python 3.6 起,还引入了 f - 字符串(f - strings),在字符串前加f
或F
,然后在字符串里使用{}
包裹变量名,Python 会自动把变量的值插入到对应的位置。format的简单写法:
name = "Eve"
age = 40
print(f"My name is {name} and I am {age} years old.")
# 与下面等价
print("My name is {name} and I am {age} years old." . format(name=name, age=age))
print("My name is {} and I am {} years old." . format(name, age))
另外format还可以:
- 格式化数字,例如指定小数位数。
pi = 3.1415926
print("The value of pi is {:.2f}".format(pi))
- 填充和对齐,用
:
来指定填充字符、对齐方式和宽度。
# 左对齐
print("{:<10}".format("left"))
# 右对齐
print("{:>10}".format("right"))
# 居中对齐
print("{:^10}".format("center"))
- 千位分隔符:在格式化数字时,可以使用逗号作为千位分隔符。
number = 1234567
print("{:,}".format(number))
将字符串转换为整数
为了使用pygal将数据生成图表,需要对一些字段的值转换为整数:
month = int(btc_dict['month'])
week = int(btc_dict['week'])
close = int(btc_dict['close']) // 这里报错了
修改后发现报错了:
Traceback (most recent call last):
File "D:\python-work\py-bigdata\btc_close_2017.py", line 25, in <module>
close = int(btc_dict['close'])
^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: '6928.6492'
原因在于:通常原始数据格式经常不统一,这里原因是py不能直接将包含小数点的字符串‘6928.6942’转换为整数,所以需要先将字符串转换为浮点数(float),再将浮点数转换为整数。
close = int( float(btc_dict['close']) )
这里先用float将字符串转换为小鼠,再用int去掉小数(截取取整),返回整数部分。
使用pygal绘制折线图
import json
import pygal
filename = 'btc_close_2017_request.json'
with open(filename) as f:
btc_data = json.load(f)
dates, months, weeks, weekdays, closes = [], [], [], [], []
for btc_dict in btc_data:
date = btc_dict['date']
month = int(btc_dict['month'])
week = int(btc_dict['week'])
weekday = btc_dict['weekday']
close = int(float(btc_dict['close']))
dates.append(date)
months.append(month)
weeks.append(week)
weekdays.append(weekday)
closes.append(close)
# pygal.Line 创建pygal折线图 并设置配置项
# x_label_rotation = 20让X轴上的日期标签顺时针旋转20度
# show_minor_x_labels=False 告诉图形不用显示所有x轴标签
line_chart = pygal.Line(x_label_rotation = 20, show_minor_x_labels=False)
line_chart.title = '收盘价'
line_chart.x_labels = dates
# X轴每个20天显示一次
N = 20
# x_labels_major属性:
# dates[::20]让x轴坐标从0开始切片直到dates数组末尾,步长为20(每隔20天显示一次) import json
import pygal
# 将数据加载到一个列表中
filename = 'btc_close_2017_request.json'
with open(filename) as f:
btc_data = json.load(f)
dates, months, weeks, weekdays, closes = [], [], [], [], []
# 打印每一天的信息 btc_dict存储字典中每个键值对
for btc_dict in btc_data:
date = btc_dict['date']
month = int(btc_dict['month'])
week = int(btc_dict['week'])
weekday = btc_dict['weekday']
close = int(float(btc_dict['close']))
dates.append(date)
months.append(month)
weeks.append(week)
weekdays.append(weekday)
closes.append(close)
# pygal.Line 创建pygal折线图 并设置配置项
# x_label_rotation = 20让X轴上的日期标签顺时针旋转20度
# show_minor_x_labels=False 告诉图形不用显示所有x轴标签
line_chart = pygal.Line(x_label_rotation = 20, show_minor_x_labels=False)
line_chart.title = '收盘价'
line_chart.x_labels = dates
# X轴每个20天显示一次
N = 20
# x_labels_major属性:让x轴坐标从0开始切片直到dates数组末尾,切片步长为20(每隔20天显示一次),避免x轴太拥挤
line_chart.x_labels_major = dates[::N]
line_chart.add('收盘价', closes)
line_chart.render_to_file('收盘价折线图.svg')
line_chart.x_labels_major = dates[::N]
line_chart.add('收盘价', closes) // 添加数据
line_chart.render_to_file('收盘价折线图.svg')
line_chart.x_labels_major:是设置主标签,用于设置折线图中 x 轴上主标签的显示。在某些情况下,x 轴上的标签可能会很多,全部显示可能会让图表显得杂乱,此时你可以通过设置 x_labels_major 来指定只显示一部分重要的标签。
比如:
# 创建一个折线图对象
line_chart = pygal.Line()
# 设置 x 轴标签
line_chart.x_labels = map(str, range(2000, 2025))
# 设置主标签
line_chart.x_labels_major = ['2000', '2010', '2020']
line_chart.x_labels_major = ['2000', '2010', '2020']
指定了只显示 2000、2010 和 2020 这三个主标签。
时间序列特征
要验证周期性假设,就要将非线性的趋势消除,对数变换时常用的处理方法。这里使用PY标准库中的数学模块math来解决。这里用以10为底的对数函数math.log10计算收盘价,日期仍然不变,这种方式称为半对数变换。
import math
# 跳过相同代码
close_log = [math.log10(_) for _ in closes]
line_chart.add('log收盘价', close_log)
line_chart.render_to_file('收盘价对数变换折线图.svg')
close_log = [math.log10(_) for _ incloses]:
- 这是一个列表推导式。列表推导式是一种简洁的语法,用于从现有的可迭代对象(如列表、元组等)创建新的列表。
- 这里的下划线 _ 是一个临时变量名,在 Python 中,下划线常被用作一个 “一次性” 的变量名,表明该变量在代码后续部分不会再被使用。它的作用是遍历 closes 中的每个元素。 这里的_是遍历的closes列表中的每一项,同时将当前遍历的项_ 传入math.log10( 参数,这里传入的参数就是 临时变量_ ) 中
- math.log10(_) 计算该临时变量元素以 10 为底的对数, 最终将所有计算得到的对数值存储在一个新的列表 close_log 中。
- 关于math.log10()的运算,如果 closes = [10, 100, 1000] ,那么 close_log 将是 [1.0, 2.0, 3.0] ,因为 math.log10(10) 等于 1.0 ,math.log10(100) 等于 2.0 ,math.log10(1000) 等于 3.0 。
- import math :这是导入 Python 的标准库 math ,该库提供了许多数学函数,例如常见的三角函数、对数函数等。
完整的代码及注释
完整代码中,使用pygal绘制svg的矢量图表,并最终将所有图表放到了一个仪表盘中。其中包含了很多关于列表操作的库、列表推导式等相关知识点,建议仔细看。
下面代码,可以配合 这篇文章 《PY基础操作-操作列表和迭代器》进行阅读
import json
import pygal
import math
from itertools import groupby, tee
def draw_line(x_data, y_data, title, y_legend):
# 创建一个空列表,用于存储分组后计算得到的 x 值和对应的 y 均值
xy_map = []
zipedXy = zip(x_data, y_data);
# print(list(zipedXy))
# [(1, 6928), (1, 7070), (1, 7175),... (11, 64890), (11, 65583)]
# 对得到的元组进行排序-升序 先按照第一位进行排序 再按照第二位排
sortedList = sorted(zipedXy)
# print(list(sortedList))
# [(1, 5383), (1, 5566), (1, 5648),... (2, 8206), (3, 6437),.. (9, 28208),.. (11, 65458), (11, 65583)]
# 使用 zip 函数将 x_data 和 y_data 打包成元组对,再对这些元组对进行排序,
# 最后使用 groupby 函数根据 x 值进行分组
# for x,y in groupby( sorted( zip(x_data, y_data) ), key=lambda _:_[0] ):
for x,y in groupby( sortedList, key=lambda _:_[0] ):
# x就是lambda匿名函数执行结果,返回 每个元组中的第一个值
# print('依据分组的x', x);
# y就是根据返回的值(迭代器),进行分组的结果
# 这里直接list(y) 会将迭代器转换成列表,那么迭代器就会被耗尽 后续就无法使用它了。
# 如果想打印 y 的副本,同时又不影响后续操作,可借助 itertools.tee 函数创建迭代器的副本。
# tee 函数返回的是一个包含多个迭代器的元组,而非迭代器的副本内容。要打印副本内容,
# 需要对 tee 返回的迭代器进行解包,然后将其中一个迭代器转换为列表来打印。
# y_copy, y_original = tee(y) 把 tee 返回的元组解包成两个迭代器,y_copy 用于打印,y_original 用于后续操作。
# 创建迭代器的副本
y_copy, y_original = tee(y)
# print('分组的结果y', list(y_copy))
"""
( 结果均为部分示例,实际是1~11 )
依据分组的x 1
分组的结果y [(1, 5383), (1, 5566), ...(1, 7175), (1, 7835)]
依据分组的x 3
分组的结果y [(3, 6437), (3, 6623), ... (3, 8832), (3, 8900)]
依据分组的x 8
分组的结果y [(8, 18305), (8, 18376), ...(8, 30656), (8, 31391)]
依据分组的x 11
分组的结果y [(11, 38904), (11, 42085), ...(11, 65458), (11, 65583)]
"""
# 从每个分组的结果y(迭代器) 进行解包, _对应 [0],v对应[1],以(11, 65583)为例,_对应11,v对应65583
y_list = [v for _, v in y_original]
"""
print(y_list)
[5383, 5566, ...7175, 7835] // 1
[6437, 6623, ... 8832, 8900] // 3
[18305, 18376, ... 30656, 31391] // 8
[38904, 42085, ... 65458, 65583] // 11
"""
xy_map.append([x, sum(y_list) / len(y_list)])
"""
print(list(xy_map))
[[1, 6285.870967741936],.. [3, 7789.032258064516],... [8, 26092.645161290322], ..., [11, 51436.166666666664]]
"""
"""
x_unique, y_mean = [*zip(*xy_map)]
首先来看 zip(*xy_map) 这部分,zip 函数的作用是将多个可迭代对象的对应元素打包成元组。
而 * 作为解包运算符,*xy_map 会把 xy_map 这个列表里的元素解包。
例如 xy_map = [[1, 6285.87], [2, 7789.03], ...],
*xy_map 就相当于把列表里的子列表依次取出,即 [1, 6285.87], [2, 7789.03], ...。
接着 zip(*xy_map) 会把这些子列表对应位置的元素组合成元组,最终返回一个由元组构成的迭代器,
这里第一个元组包含所有的 x 值,第二个元组包含所有的 y 均值。
后 [*zip(*xy_map)] 中的 * 又对 zip(*xy_map) 返回的迭代器进行解包,把这些元组放到一个列表里,
最终得到一个包含两个元组的列表,分别对应 x 唯一值和 y 均值。
下面是以拆解的步骤实现的
"""
# *是实现解包的操作, 将*xy_map 中的子列表依次取出,zip再将这些子列表对应位置的元素组合成元组,
# 即0索引跟0索引拼成组,1索引跟1索引拼成组,最终返回由元组构成的迭代器
# 第一个元组包含所有的x值,第二个元组包含所有的y值
xymap_unzipped = zip(*xy_map)
"""
不解包 结果保存在一个迭代器中
print(list(xymap_unzipped))
[(1, .., 3, ..., 8, ... 11), (6285.870967741936, .., 7789.032258064516, ... 26092.645161290322, ... 51436.166666666664)]
x_unzipped, y_unzippen = zip(*xy_map) 解包 结果分别存储
# (1, .., 3, ..., 8, ... 11)
# (6285.870967741936, .., 7789.032258064516, ... 26092.645161290322, ... 51436.166666666664)
"""
# 又对这个迭代器进行解包,拆成两项, 将这些元组放到一个列表里,最终得到一个包含两个元组的列表
x_unique, y_mean = [*xymap_unzipped]
"""
[*xymap_unzipped] 形成的列表
[(1, .. 3, .. 8, .. 11), (6285.870967741936,.., 7789.032258064516,..., 26092.645161290322, ..., 51436.166666666664)]
因为在py中,当有一个可迭代对象,并知晓该可迭代对象元素数量时候,
就可以用解包赋值将可迭代对象中的元素分别赋值给不同变量
所以使用两个变量分别接收 对列表解包的两个元组
"""
"""
最终解包得到的两个元组
print(x_unique, y_mean)
(1, ..., 3, ..., 8, ..., 11) (6285.870967741936, .., 7789.032258064516,..., 26092.645161290322, ..., 51436.166666666664)
"""
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
filename = 'btc_close_2017_request.json'
with open(filename) as f:
btc_data = json.load(f)
dates, months, weeks, weekdays, closes = [], [], [], [], []
# 打印每一天的信息 btc_dict存储字典中每个键值对
for btc_dict in btc_data:
date = btc_dict['date']
month = int(btc_dict['month'])
week = int(btc_dict['week'])
weekday = btc_dict['weekday']
# 原始数据格式经常不统一,这里原因是py不能直接将包含小数点的字符串‘6928.6942’转换为整数
# 所以需要先将字符串转换为浮点数(float),再将浮点数转换为整数
close = int(float(btc_dict['close']))
# print("{}月 {} 周 {}, {}, 闭市价 {} RMB" . format(date, month, week, weekday, close))
dates.append(date)
months.append(month)
weeks.append(week)
weekdays.append(weekday)
closes.append(close)
# 从日期中找到2017-12-01这一天的索引 得到334 即334对应的是2017-12-01
idx_month = dates.index('2017-12-01')
line_chart_month = draw_line(
# 按照索引 对months进行切片 [start:stop:step] 截取从0到idx_month -1
# (索引0~333,对应的截止日期是2017-11-31) 之间的所有数据
months[:idx_month],
closes[:idx_month],
'收盘价日均值',
'月日均值'
)
# line_chart_month
idx_week = dates.index('2017-12-11')
# print( weekdays[1:idx_week] )
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', ...]
wd = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
# 找到weekdays中的 星期几英文,并找出在wd数组中的索引 再+1
weekdays_int = [ wd.index(w) + 1 for w in weekdays[1:idx_week] ]
line_chart_week = draw_line(
weekdays_int,
closes[1: idx_week],
'收盘价星期均值',
'星期均值'
)
line_chart_week.x_labels = ['周一','周二','周三','周四','周五','周六','周日']
line_chart_week.render_to_file('收盘价星期均值.svg')
# 绘制数据仪表盘 将所有图表都放一起
with open('收盘价仪表盘.html', 'w', encoding='utf8') as html_file:
html_file.write('<html<head><title>收盘价仪表盘</title><meta charset=utf-8></head><body>\n')
svgs_arr = [
'收盘价折线图.svg',
'收盘价对数变换折线图.svg',
'收盘价日均值.svg',
'收盘价周日均值.svg',
'收盘价星期均值.svg'
]
# 因为svg是矢量图 可以缩放并且不失真
for svg in svgs_arr:
html_file.write('<object type="image/svg+xml" data="{0}" height=500></object>\n'.format(svg))
html_file.write('</body></html>')
网上有很多免费的JSON格式数据:比如:
open knowledge https://okfn.org/en/
还有很多第三方数据分析的库,除了matplotlib,还有:
科学计算工具包 Numpy https://numpy.org/
scipy https://scipy.org/
快速数据分析工具 pandas https://pandas.pydata.org/
机器学习工具 scikit-learn https://scikit-learn.org/
深度学习 Keras https://keras.io/
比如这个案例可以用pandas读取JSON文件数据,并进行格式转换和数据聚合,时间序列分析,并结合scikit-learn对收盘价进行回归分析与预测。