CSV格式存储:逗号分隔的一系列值。
下载天气数据:https://www.wunderground.com/history
import csv
from matplotlib import pyplot as plt
from datetime import datetime
# 从文件中获取信息
filename = 'sitka_weather_07-2014.csv' # 一个包含天气数据的csv文件
with open(filename) as f:
reader = csv.reader(f) # 创建一个与文件相关的阅读器对象
header_row = next(reader) # 返回文件中的下一行。第一行:文件头
# 打印文件头
# print(header_row)
for index, column_header in enumerate(header_row): # 获取每个元素的索引及其值
print(index, column_header)
# 获取文件中的日期(0)和最高温(1)和最低温(3)
highs = []
dates = []
lows = []
for row in reader:
try:
date_format = "%Y-%m-%d" # 格式控制
date = datetime.strptime(row[0], date_format)
high = int(row[1]) # 字符->整形。matolptlib能读取的类型
low = int(row[3])
except ValueError: # 避免数据缺失,读取‘ ’
print(date, 'missing!')
else:
dates.append(date)
highs.append(high)
lows.append(low)
# 根据数据绘制图形
fig = plt.figure(dpi=128, figsize=(10, 6))
plt.plot(dates, highs, c='red')
plt.plot(dates, lows, c='green')
plt.fill_between(dates, highs, lows, facecolor='green', alpha=0.1) # 图表区域着色,alpha值(0-1)表示透明度
plt.title("Daliy temperatures", fontsize=24)
plt.xlabel("Days", fontsize=18)
fig.autofmt_xdate() # 绘制斜的日期标签,避免重叠
plt.ylabel("F", fontsize=18)
plt.tick_params(axis='both', which='major', labelsize=14)
plt.show()
from __future__ import (absolute_import, division, print_function, unicode_literals)
from urllib.request import urlopen # python3
import json
# 向GitHub服务器发送请求
json_url = "https://raw.githubusercontent.com/muxuezi/btc/master/btc_close_2017.json"
response = urlopen(json_url)
# 读取数据
req = response.read()
# 将数据写入文件
with open('btc_close_2017_urllib.json', 'wb') as f:
f.write(req)
# 加载json格式
file_urllib = json.loads(req.decode('utf8')) # 转换成Python能处理的格式
print(file_urllib)
报错了两次:urllib.error.URLError:
[11001] 第六行单引号改成双引号 参考
[11004] 电脑配置的DNS不能使用了,修改DNS地址为114.114.114.114参考
3. 使用标准库模块requests
import requests
# 向GitHub服务器发送请求
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') as f:
f.write(req.text) # text属性可以直接读取文件数据,返回字符串格式
file_requests = req.json() # 转换文件的数据为Python列表
import json
import pygal
import math
# 加载数据到列表
filename = 'btc_close_2017_request.json'
with open(filename) as f:
btc_data = json.load(f) # 一个列表,每个元素都是一个包含五个键的字典
# 创建5个列表。存储信息
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'])) # 包含小数的字符串不能直接转换为数值
# print("{} is month {} week {}, {}, the close price is {} RMB".format(date, month, week, weekday, close))
dates.append(date)
months.append(month)
weeks.append(week)
weekdays.append(weekday)
closes.append(close)
# 绘制收盘价对数变换折线图
line_chart = pygal.Line(x_label_rotation=20, show_minor_x_labels=False) # 倾斜角度,不完全显示x轴标签
line_chart.title = '收盘价对数变换折线'
line_chart.x_labels = dates
N = 20 # x轴坐标每隔20天显示一次
line_chart.x_labels_major = dates[::N] # 切片操作。[开头:结束:步长]
closes_log = [math.log10(x) for x in closes] # 做对数变换,消除非线性的趋势
line_chart.add('log收盘价', closes_log)
line_chart.render_to_file('收盘价对数变换折线图.svg') # 文件保存
import json
import pygal
from itertools import groupby # 分组操作函数
# 加载数据到列表
filename = 'btc_close_2017_request.json'
with open(filename) as f:
btc_data = json.load(f) # 一个列表,每个元素都是一个包含五个键的字典
# 创建5个列表。存储信息
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'])) # 包含小数的字符串不能直接转换为数值
# print("{} is month {} week {}, {}, the close price is {} RMB".format(date, month, week, weekday, close))
dates.append(date)
months.append(month)
weeks.append(week)
weekdays.append(weekday)
closes.append(close)
# 绘制收盘价均值表
def draw_line(x_data, y_data, title, y_legend):
# 计算收盘价均值
xy_map = [] # 存放均值
# 将x、y轴数据合并、排序,再用函数grouphy分组
for x, y in groupby(sorted(zip(x_data, y_data)), key=lambda _: _[0]): # 2
y_list = [v for _, v in y]
xy_map.append([x, sum(y_list) / len(y_list)]) # 3
x_unique, y_mean = [*zip(*xy_map)] # 将合并的x、y轴数据分离
# 制作折线图
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], closes[:idx_month], '收盘价月日均值', '月日均值')
line_chart_month
有一句代码真是难懂:for x, y in groupby(sorted(zip(x_data, y_data)), key=lambda _: _[0])
理解:x_date,y_date分别是一个列表,将这个列表打包成一个元素,然后根据x_date列表的第一个元素将这个包分组。返回的x为这个包的键,y为这个包的值。
zip()函数,接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
groupby函数,按照键值(key)或者分组变量将数据分组。
python学习:zip函数
python3中的groupby函数用法
数据仪表盘(dashboard)就是把生成的SVG文件整合到一个页面。
SVG是矢量图,文件可以任意缩放不失真。
with open('收盘价Dashboard.html', 'w', encoding='utf8') as html_file:
html_file.write(
'收盘价Dashboard \n')
for svg in ['收盘价折线图.svg', '收盘价对数变换折线图.svg', '收盘价月日均值.svg']:
html_file.write(
' \n'.format(svg)) # 1
html_file.write('')