摘要:本節中將繪制幅圖像收盤折線圖,收盤價對數變換,收盤價月日均值,收盤價周日均值,收盤價星期均值。對數變換是常用的處理方法之一。
《Python編程:從入門到實踐》筆記。1. 前言
本篇是Python數據處理的第二篇,本篇將使用網上下載的數據,對這些數據進行可視化。
本篇將訪問并可視化以兩種常見格式存儲的數據:CSV和JSON:
使用Python的csv模塊來處理以CSV(逗號分隔的值)格式存儲的天氣數據,找出兩個不同地區在一段時間內的最高溫度和最低溫度;
使用json模塊來訪問以JSON格式存儲的交易收盤價數據。
本文數據均可從圖書官網下載( http://www.ituring.com.cn/boo... )。
2. CSV文件格式新建一個項目,將文件death_valley_2014.csv復制到項目根目錄,并新建highs_lows.py文件,改程序讀取加州死亡谷2014年的溫度數據,提取出每天的最高和最低氣溫,并繪制出折線圖:
import csv from datetime import datetime from matplotlib import pyplot as plt filename = "death_valley_2014.csv" with open(filename) as f: reader = csv.reader(f) header_row = next(reader) dates, highs, lows = [], [], [] for row in reader: try: current_date = datetime.strptime(row[0], "%Y-%m-%d") high = int(row[1]) low = int(row[3]) except ValueError: print(current_date, "missing data") else: dates.append(current_date) highs.append(high) lows.append(low) fig = plt.figure(dpi=141, figsize=(10, 6)) # 繪制最高氣溫折線圖 plt.plot(dates, highs, c="red") # 繪制最低氣溫折線圖 plt.plot(dates, lows, c="blue") # 填充兩個折現之間的空間,alpha為透明度,0為全透明,1為不透明 plt.fill_between(dates, highs, lows, facecolor="blue", alpha=0.1) plt.title("Daily high and low temperatures - 2014 Death Valley, CA", fontsize=20) plt.xlabel("", fontsize=16) # 自動排版x軸的日期數據,避免重疊 fig.autofmt_xdate() plt.ylabel("Temperature(F)", fontsize=16) plt.tick_params(axis="both", which="major", labelsize=16) plt.show()
代碼現將文件打開,然后通過csv.reader()函數創建一個CSV文件閱讀器,參數就是剛才打開的文件;通過next()函數讀取文件的一行,并自動將數據轉換為列表;然后通過一個for循環讀取全部數據。for循環中還添加了錯誤檢查,以防文件中數據丟失等問題造成程序終止。我們還通過fill_between()函數將兩個折現之間的區域著色。最后得到的圖像如下:
同時我們還得到了一條信息輸出:
2014-02-16 00:00:00 missing data
即該日的數據丟失了。
3. 制作交易收盤價走勢圖:JSON格式現將將btc_close_2017.json拷貝到項目根目錄下。本節中將繪制5幅圖像:收盤折線圖,收盤價對數變換,收盤價月日均值,收盤價周日均值,收盤價星期均值。均使用Pygal繪制。
3.1 繪制收盤價折線圖import json import pygal # 將數據加載到一個列表中,列表中的元素是字典 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"]))) # x軸坐標上的刻度順時針旋轉20度 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")
最后得到的圖像如下:
3.2 收盤價對數變換從上圖可以看出,收盤價基本呈指數增長,但其中有一些相似的波動(3,6,9月)。盡管這些波動被增長的趨勢掩蓋了,但也許其中有周期性。為了驗證周期性的假設,需要首先將非線性的趨勢消除。對數變換是常用的處理方法之一。我們使用Python標準庫中的math模塊來解決此問題。
-- snip -- import math 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")
得到了如下圖像:
可以看出,3,6,9月都出現了劇烈的波動。下面再看看收盤價的月日均值和周日均值。
3.3 收盤價均值 3.3.1 月日均值在繼續新的代碼之前,需要補充一些知識:對于zip()函數,它將多個列表按照元素的位置組成新的列表,而新列表的元素是元組。如下:
# 代碼 a = [1, 2, 3] b = [4, 5, 6] c = [7, 8, 9, 10] zipped_1 = zip(a,b) zipped_2 = zip(a, b, c) print(zipped_1) print(list(zipped_1)) print(list(zipped_2)) # 結果[(1, 4), (2, 5), (3, 6)] [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
在python2中,zip()直接返回一個列表,但在python3中,zip()返回一個可迭代的zip對象,這里我們將其轉化為列表。也在前面加星號對zip對象進行“解壓”(解包):
# 代碼: print(*zipped_1) # 結果: (1, 4) (2, 5) (3, 6)
星號不止能對zip對象進行解包,還可以對list等類型進行解包。
我們還會用到groupby()函數,但在使用該函數之前,需要對列表進行排序。我們使用sorted()函數進行排序,python3中sorted()函數默認按照元素順序進行比較,比如這里的列表的元素是元組,則sorted()先比較元組中第一個元素的值,再比較第二個元素的值,如下:
# 代碼: test = [(1, 5), (1, 4), (1, 3), (1, 2), (2, 3)] print(sorted(test)) # 結果: [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3)]
接下來通過groupby()函數對這些數據進行分組,通過關鍵字參數key=itemgetter(0)指定根據列表元素(即元組)的第一個值進行分組。也可以將這里的itemgetter()函數替換為lambda表達式,如等價的lambda表達式為lambda x: x[0]。在python3中,groupby()返回一個可迭代的groupby對象,如果將其轉換成list,list中的每個元素的第二個值也是個可迭代對象:
# 代碼: test = [(1, 5), (1, 4), (1, 3), (1, 2), (2, 4), (2, 3), (3, 5)] temp = groupby(sorted(test), key=itemgetter(0)) print(temp) print(list(temp)) for a, b in temp: print(list(b)) # 結果:[(1, ), (2, ), (3, )] [(1, 2), (1, 3), (1, 4), (1, 5)] [(2, 3), (2, 4)] [(3, 5)]
從上面的for循環的結果來看,可以將groupby()返回的對象看做一個字典,該字典的鍵為上面的key的值,該字典的值為還沒分組時列表中的部分元素(可能組成了列表,也可能組成了元組)。
現在言歸正傳,回到主線。
繪制2017年前11個月的日均值,前49周的日均值,以及每周中各天(Monday~Sunday)的日均值。首先我們需要封裝一些代碼:
from itertools import groupby from operator import itemgetter def draw_line(x_data, y_data, title, y_legend): xy_map = [] # 本段見后面解釋 for x, y in groupby(sorted(zip(x_data, y_data)), key=itemgetter(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
本段代碼有些繞。從前面的介紹可以知道,for循環中的變量y相當于一個list,這個list的元素是tuple,tuple的第一個元素是x_data中的值,不再重復需要,所以取第二個值組成list,即第8行代碼。xy_map是個list對象,而它的元素也是list,即它是一個二維數組。注意第10行的操作,*xy_map將list進行解包,zip()函數將解包后的元素再次打包成一個zip對象,如果將其看做list對象,則這個對象含有兩個tuple元素,然后將這個zip對象也解包,最外面再套一層list,得到一個含兩個tuple元素的list,最后再平行賦值。為了更具體的體現這段操作,下面用一些簡單數據進行模擬:
# 代碼: temp = [[1, 2], [3, 4], [5, 6]] x, y = [*zip(*temp)] print(x) print(y) # 結果: (1, 3, 5) (2, 4, 6)
最后,終于到了畫圖階段:
-- 讀取文件內容的代碼和前面一樣 -- idx_month = dates.index("2017-12-01") line_chart_month = draw_line(months[:idx_month], close[:idx_month], "收盤價月日均值(¥)", "月日均值")
得到的結果如下:
3.3.2 周日均值2017年的第一周從2017年1月2日開始,第49周周日是2017年12月10日。
-- 讀取文件內容的代碼和前面一樣 -- idx_week = dates.index("2017-12-11") line_chart_week = draw_line(weeks[1:idx_week], close[1:idx_week], "收盤價周日均值(¥)", "周日均值")
結果如下:
3.3.3 每周中各天的均值如果直接用weekdays這個列表生成圖表,由于該列表存儲的是字符串,排序的時候是按ASCII碼進行排序,最后生成的圖表星期的順序會出錯,所以將其轉換成數字。
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")
最后的結果如下:
3.4 收盤價數據儀表盤最后我們將五張表整合到一個文件中,做成一個儀表盤:
with open("收盤價Dashboard.html", "w", encoding="utf8") as html_file: title = "收盤價Dashboard " html_file.write(title) for svg in [ "收盤價折線圖(¥).svg", "收盤價對數變換折線圖(¥).svg", "收盤價月日均值(¥).svg", "收盤價周日均值(¥).svg", "收盤價星期均值(¥).svg" ]: html_file.write( " ".format(svg)) html_file.write("")
效果如下:
這是將瀏覽器放大后的效果,默認100%的話這五張圖都在同一行,且非常小。
4. 小結本篇中主要內容有:
如何使用網上的數據集;
如何處理CSV和JSON文件,以及如何提取你感興趣的數據;
如何使用matplotlib來處理以往的天氣數據,包括如何使用datetime模塊,以及如何在同一個圖表中繪制多個數據系列;
如何json模塊來訪問JSON格式存儲的交易收盤價數據,并使用Pygal繪制圖形以探索價格變化的周期性,以及如何將Pygal圖形組合成數據儀表盤。
下一篇將從網上采集數據并對其進行可視化。
迎大家關注我的微信公眾號"代碼港" & 個人網站 www.vpointer.net ~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44724.html
摘要:將每一行作為返回,其中是每行中的列名。對于每一行,都會生成一個對象,其中包含和列中的值。它返回一個迭代器,是迭代結果都為的情況。深度解析至此全劇終。 簡單實戰 大家好,我又來了,在經過之前兩篇文章的介紹后相信大家對itertools的一些常見的好用的方法有了一個大致的了解,我自己在學完之后仿照別人的例子進行了真實場景下的模擬練習,今天和大家一起分享,有很多部分還可以優化,希望有更好主意...
摘要:前言本文記錄自己在學習當中遇到的各種大小問題,持續更新。錯誤分析本身是一個網絡引擎框架,的運行依賴于。在打開新建的項目后,報錯顯示。錯誤分析的默認依賴項當中沒有,或者說默認查找的路徑中找不到。 前言 本文記錄自己在學習scrapy當中遇到的各種大小問題,持續更新。 環境簡介: 語言版本 爬蟲框架 IDE 系統 python3.5 scrapy1.4.0 pycharm win1...
摘要:學習利器我的小白安裝之路序易用,但用好卻不易,其中比較頭疼的就是包管理和不同版本的問題,特別是當你使用的時候。另外值得一提的是,并不僅僅管理的工具包,它也能安裝非的包。 Python學習利器——我的小白 Anaconda安裝之路 序 Python易用,但用好卻不易,其中比較頭疼的就是包管理和Python不同版本的問題,特別是當你使用Windows的時候。為了解決這些問題,有不少發行版的...
閱讀 1609·2021-09-23 11:31
閱讀 924·2021-09-23 11:22
閱讀 1347·2021-09-22 15:41
閱讀 4076·2021-09-03 10:28
閱讀 2911·2019-08-30 15:55
閱讀 3545·2019-08-30 15:55
閱讀 1954·2019-08-30 15:44
閱讀 2716·2019-08-30 13:50