在学习《Python编程从入门到实践》16.2.6收盘价均值这块时,代码不是很清晰,里面有lambda法则等,可能作者不想涉及太多高级内容所以没有详细写,自己把自己的理解过程记录如下。
本文主要参考(19条消息) Python编程:从入门到实践 json练习详解~~_pythonxiaohei的博客-优快云博客
from itertools import groupby
import pygal
import json
def draw_mean(month_data, price_data, title, y_legend):
xy_map = []
zip_data = zip(month_data, price_data)
zip_data = sorted(zip_data)
for x, y in groupby(zip_data, key=lambda value: value[0]):
y_list = [value for index, value in y]
y_mean = sum(y_list) / len(y_list)
xy_map.append([x, y_mean])
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
file_name = 'btc_close_2017.json'
dates, months, weeks, weekdays, closes = [], [], [], [], []
with open(file_name) as f:
btc_data = json.load(f)
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'])
closes.append(int(float(btc_dict['close'])))
idx_month = dates.index('2017-12-01')
idx_week = dates.index('2017-12-11')
line_chart_month_mean = draw_mean(months[:idx_month], closes[:idx_month], '收盘价月平均值', '月平均值')
line_chart_week_mean = draw_mean(weeks[1:idx_month], closes[1:idx_month], '收盘价周平均值', '周平均值')
wd = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
# 这搞错了 wd_label = [wd.index(x)+1 for x in wd]
wd_label = [wd.index(x)+1 for x in weekdays[1:idx_week]]
line_chart_weekday_mean = draw_mean(wd_label, closes[1:idx_week], '收盘价星期平均值', '星期平均值')
line_chart_weekday_mean.x_labels = ['周一', '周二', '周三', '周四', '周五', '周六', '周天']
line_chart_weekday_mean.render_to_file('收盘价星期平均值.svg')
此处主要有三个点:zip()函数的运用,groupby()的运用以及lambda法则
1. zip为将后续参数打包成元组的列表,即例如(1,1000),(2,2000)..... 如此的话,就将每个月的日期与价格打包起来了。注意month_data和price_data是按顺序依次打包的,如果有一个短,那就按照这个短的截断。 因而这个就形成了(month,price)的一个列表。
后续的sorted即将该列表按照month的顺序进行了排序。
此时的数据结构为[(1,1000),(1,1500).....(2,2000),(2,25000)......(12,1000)]
2.groupby函数为将数据进行组的形式输出 上文中zip_data已按月份排起来了,如果此时将月份作文一个flag,相同flag的都进行输出,则就是该函数的作用。
其次其参数key即我们应该用何种方式打包,因为我们想用这个flag为标志进行输出,所以后面的lambda法则就是取出标志flag,具体用法下面写
这样我们可以理解成 a,b = groupby(data, key = flag),即其输出两个值:flag与flag有关的所有data,如此a即接受了flag,b接收了flag相关的所有数据形成的list
因而后续代码就对其进行了相关平均值计算
3. lambda法则 其表达式为 lambda argumen_list:expression
即将argument_list进行expression的处理从而输出与argument_list相同数据结构的output
书上是 key=lambda _:_[0] 即输入名为'_'的列表,取该列表的第一个元素、
顺便写一下自己遇到的小BUG:
1.在绘制周平均值时,对数据处理应为
line_chart_week_mean = draw_mean(weeks[1:idx_month], closes[1:idx_month], '收盘价周平均值', '周平均值')
因为看原数据,第一组为第52周,而我们截止到11月底只有48周,所以我们从1开始取,而不是0
2.在绘制日平均值,对数据处理为
wd = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
# 这搞错了 wd_label = [wd.index(x)+1 for x in wd]
wd_label = [wd.index(x)+1 for x in weekdays[1:idx_week]]
因为后面这个wd_label即weekday_label是输入到line中作为x数据的,其与后面的price是数量上对应的,而我自己code时以为其至少将文字序列转化为数字序列,所以写成了一个如上的错误,最后跑完发现不对,检查后发现这个地方列表解析应该是对weekdays列表,其数量与price对应,进行一个for的解析转化
自己的第一篇文章,纪念纪念哈!