《python编程从入门到实践》的第16章的16.2.6 收盘价均值小节运行报错,书中并没有像以往内容一样对用到的函数有说明,而且完全按照书中代码敲上去却还是出现报错:object of type ‘int’ has no len(),对于初学者来说真的是一脸蒙圈。
# 将数据加载到一个列表中
filename = 'btc_close_2017.json'
with open(filename) as f:
btc_data = json.load(f)
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'])))
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]): # 1
y_list = [v for _, v in y]
xy_map.append([x, sum(y_list) / len(y_list)]) # 2
x_unique, y_mean = [*zip(*xy_map)] # 3
line_chart = pygal.Line()
line_chart.title = title
line_chart.x_labels = x_unique # 4
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
首先,传入实参x_data为1~11月的月份数,打印到屏幕上可见:
y_data为对应的收盘价格。
#1中使用zip()函数将x_data和y_data打包成元组列表,即[(1,6928), (1,7070) … 省略 … (11,65583)],在python 3 中zip()返回的是一个支持遍历的对象,如果此时打印该返回值,会出现<zip object at 0x1007096c8>错误。
接着使用sorted()函数进行排序,返回一个排序后的元组列表,即[(1, 5383), (1,5566) … 省略 … (1,6928), (1,7070) … 省略… (11,65583)]。使用 groupby()来进行分组,key=lambda _: _[0]代表按照元组列表中的第一个元素进行分类(如果是[1]则是按照第二个),可被分为11组,x是分类的key值,x为1~11,y是对应的元组。
1 [(1,5383), (1,5566) … 省略 … (1,7835)]
2 [(2,6793), (2,6811) … 省略 … (2,8206)]
…
y_list = [v for _,v in y]
将元组中的收盘价格的值取出来,再计算其均值,sum(y_list) / len(y_list)是每月对应的均值。
#2 将月份数以及对应的收盘值月均值储存到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]]
#3 *zip相当于解压,zip(*xy_map)将原列表解压为[(1,2,3,4,5,6,7,8,9,10,11),(6285.870967741936, 7315.714285714285, 7789.032258064516, 8390.466666666667, 12963.935483870968, 18092.166666666668, 17146.16129032258, 26092.645161290322, 26865.633333333335, 35460.67741935484, 51436.166666666664) ]。最后[*zip(*xy_map)]使其成功赋值给x_unique,和y_mean。至此,已经将数据分类成功,x_unique的值为(1,2,3,4,5,6,7,8,9,10,11),y_mean的值为(6285.870967741936, 7315.714285714285, 7789.032258064516, 8390.466666666667, 12963.935483870968, 18092.166666666668, 17146.16129032258, 26092.645161290322, 26865.633333333335, 35460.67741935484, 51436.166666666664)。
#4 x_unique的值数据类型是int, line_chart.x_labels需要的类型是str,因此会出现报错: object of type ‘int’ has no len()。只需要修改#2处的代码,在此处将x转换成str类型即可,代码如下:
xy_map.append([str(x), sum(y_list) / len(y_list)]) # 2