From dda8ddcaa4abbc313dee94aa1d30021ef974efe7 Mon Sep 17 00:00:00 2001 From: victorgau Date: Sat, 25 Mar 2017 03:45:14 +0800 Subject: [PATCH] upload handouts --- ...01. Python \347\260\241\344\273\213.ipynb" | 479 ++++++++++ ...345\217\212\344\275\277\347\224\250.ipynb" | 624 ++++++++++++ ...347\232\204\350\256\212\346\225\270.ipynb" | 392 ++++++++ ...346\226\231\345\236\213\346\205\213.ipynb" | 892 ++++++++++++++++++ ...345\231\250\345\236\213\345\210\245.ipynb" | 472 +++++++++ ...351\201\213\347\256\227\345\255\220.ipynb" | 403 ++++++++ ...347\250\213\346\216\247\345\210\266.ipynb" | 377 ++++++++ ...347\232\204\345\207\275\345\274\217.ipynb" | 441 +++++++++ ...210\220\345\274\217 (Comprehension).ipynb" | 258 +++++ ...\232\204\346\252\224\346\241\210 IO.ipynb" | 387 ++++++++ ...346\226\231\346\223\267\345\217\226.ipynb" | 253 +++++ ...345\244\226\350\231\225\347\220\206.ipynb" | 230 +++++ ...345\274\217\350\250\255\350\250\210.ipynb" | 511 ++++++++++ .../01. Numpy \347\260\241\344\273\213.ipynb" | 752 +++++++++++++++ ...MatPlotLib \347\260\241\344\273\213.ipynb" | 631 +++++++++++++ ...03. Pandas \347\260\241\344\273\213.ipynb" | 668 +++++++++++++ .../data/MI_5MINS_HIST10603.csv | 21 + .../images/artists_figure.png | Bin 0 -> 28982 bytes .../images/artists_tree.png | Bin 0 -> 7310 bytes 02_numpy_matplotlib_pandas/images/od1.png | Bin 0 -> 31985 bytes .../images/three_layers.png | Bin 0 -> 55314 bytes ...345\200\274\344\272\244\345\217\211.ipynb" | 84 +- ...350\243\275\345\234\226\345\275\242.ipynb" | 1 + 23 files changed, 7859 insertions(+), 17 deletions(-) create mode 100644 "01_basics/01. Python \347\260\241\344\273\213.ipynb" create mode 100644 "01_basics/02. Python \345\256\211\350\243\235\345\217\212\344\275\277\347\224\250.ipynb" create mode 100644 "01_basics/03. Python \347\232\204\350\256\212\346\225\270.ipynb" create mode 100644 "01_basics/04. Python \347\232\204\350\263\207\346\226\231\345\236\213\346\205\213.ipynb" create mode 100644 "01_basics/05. Python \347\232\204\345\256\271\345\231\250\345\236\213\345\210\245.ipynb" create mode 100644 "01_basics/06. Python \347\232\204\351\201\213\347\256\227\345\255\220.ipynb" create mode 100644 "01_basics/07. Python \347\232\204\346\265\201\347\250\213\346\216\247\345\210\266.ipynb" create mode 100644 "01_basics/08. Python \347\232\204\345\207\275\345\274\217.ipynb" create mode 100644 "01_basics/09. Python \347\224\237\346\210\220\345\274\217 (Comprehension).ipynb" create mode 100644 "01_basics/10. Python \347\232\204\346\252\224\346\241\210 IO.ipynb" create mode 100644 "01_basics/11. Python \347\232\204\347\266\262\350\267\257\350\263\207\346\226\231\346\223\267\345\217\226.ipynb" create mode 100644 "01_basics/12. Python \347\232\204\344\276\213\345\244\226\350\231\225\347\220\206.ipynb" create mode 100644 "01_basics/13. Python \347\232\204\347\211\251\344\273\266\345\260\216\345\220\221\347\250\213\345\274\217\350\250\255\350\250\210.ipynb" create mode 100644 "02_numpy_matplotlib_pandas/01. Numpy \347\260\241\344\273\213.ipynb" create mode 100644 "02_numpy_matplotlib_pandas/02. MatPlotLib \347\260\241\344\273\213.ipynb" create mode 100644 "02_numpy_matplotlib_pandas/03. Pandas \347\260\241\344\273\213.ipynb" create mode 100644 02_numpy_matplotlib_pandas/data/MI_5MINS_HIST10603.csv create mode 100644 02_numpy_matplotlib_pandas/images/artists_figure.png create mode 100644 02_numpy_matplotlib_pandas/images/artists_tree.png create mode 100644 02_numpy_matplotlib_pandas/images/od1.png create mode 100644 02_numpy_matplotlib_pandas/images/three_layers.png diff --git "a/01_basics/01. Python \347\260\241\344\273\213.ipynb" "b/01_basics/01. Python \347\260\241\344\273\213.ipynb" new file mode 100644 index 0000000..cfb0502 --- /dev/null +++ "b/01_basics/01. Python \347\260\241\344\273\213.ipynb" @@ -0,0 +1,479 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 簡介" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python 之父\n", + "### Guido Van Rossum (荷蘭, 1956~)\n", + "\n", + "[![Guido Van Rossum (荷蘭, 1956~)](../images/Guido_van_Rossum_OSCON_2006_cropped.png)](https://en.wikipedia.org/wiki/Guido_van_Rossum)\n", + "\n", + "* 1989 年 Xmas 時,為了打發時間,Guido 開始寫 Python。\n", + "* 1991 釋出 Python。\n", + "* 取名 Python 的原因是 Guido 喜歡看 \"Monty Python's Flying Circus\"。\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "293af2dd-d2e0-4f2e-a448-2cbf1641e7d5" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Why Python?\n", + "\n", + "* 自由軟體:完全免費、參與者眾\n", + "* 擴充性強:模組豐富、應用性強\n", + "* 易學好用:語法簡潔、易學易懂\n", + "* 跨平台:Windows / Linux / Mac / ...\n", + "* 同好者眾:支援性強、問題快解\n", + "\n", + "[More:Python 發展歷史與特點](http://www.ziqiangxuetang.com/python/python-intro.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 從下面的笑話,可以稍微看出 Python 的特點!\n", + "\n", + "![](../images/python-vs-java.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python is a glue language!!!\n", + "\n", + "* 使用者通常不需要自己實作程式所有的功能,而是需要協調及整合模組跟套件的運作!!!\n", + "\n", + "|| C/C++ | Python |\n", + "|:-:|:-:|:-:|\n", + "|開發速度|慢|快|\n", + "|偵錯速度|慢|快|\n", + "|佈署速度|慢|快|\n", + "|執行速度|非常快|快|\n", + "\n", + "* 使用 Python 可以在最短的時間做出產品雛形。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 新創公司喜歡 Python!\n", + "\n", + "[![](../images/AL_jobs.png)](https://www.codementor.io/learn-programming/beginner-programming-language-job-salary-community)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 學校喜歡教 Python (Top US Universities Teach Python)\n", + "\n", + "[![](../images/Top39-700.4.png)](http://cacm.acm.org/blogs/blog-cacm/176450-python-is-now-the-most-popular-introductory-teaching-language-at-top-u-s-universities/fulltext)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 初學者喜歡學 Python (PYPL, PopularitY of Programming Language Index)\n", + "\n", + "[![](../images/PYPL_2017_03.png)](http://pypl.github.io/PYPL.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "81f50645-13d2-43a5-a557-902be09c9968" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 電子電機工程師喜歡 Python (2016 IEEE Programming Languages Ranking)\n", + "[![](../images/2016 IEEE Top 10 Programming Languages.png)](http://spectrum.ieee.org/computing/software/the-2016-top-programming-languages)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "[![](../images/IoT_languages.png)](http://www.developer-tech.com/news/2016/apr/20/research-iot-developer-survey-reveals-popular-technologies/)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 資料科學家喜歡 Python (Top 10 Tools for Analytics/Data Science)\n", + "\n", + "[![](../images/top10-analytics-data-science-software-2016.jpg)](http://www.kdnuggets.com/2016/06/r-python-top-analytics-data-mining-data-science-software.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 社群喜歡 Python (TIOBE Programming Community Index)\n", + "\n", + "[![](../images/Tiobe_2017_02.png)](http://www.tiobe.com/tiobe-index/)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 後端喜歡 Python (Python/Django Market Share)\n", + "\n", + "[![](../images/silicon_valley.png)](https://www.quora.com/How-is-the-market-for-programmers-in-Python-Django)\n", + "\n", + "[![](../images/berlin.png)](https://www.quora.com/How-is-the-market-for-programmers-in-Python-Django)\n", + "\n", + "[![](../images/barcelona.png)](https://www.quora.com/How-is-the-market-for-programmers-in-Python-Django)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "[![](../images/backend.png)](https://en.wikipedia.org/wiki/Programming_languages_used_in_most_popular_websites)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Fintech 喜歡 Python\n", + "[![](../images/fintech-finance-1.png)](https://blog.hackerrank.com/emerging-languages-still-overshadowed-by-incumbents-java-python-in-coding-interviews/)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "25ac7855-2c20-47bb-b4ab-6a7fbba20e2d" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 2015 Github Statistics\n", + "[![](../images/Python vs R in Github.png)](http://githut.info/?utm_content=buffer781de&utm_medium=social&utm_source=facebook.com&utm_campaign=buffer)\n", + "\n", + "[Python vs. R (Datacamp)](https://www.datacamp.com/community/tutorials/r-or-python-for-data-analysis)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "6ddd881a-45b7-47cb-8a82-8c8280270623" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## stackoverflow\n", + "[![](../images/2016 stackoverflow Languages Ranking.png)](http://stackoverflow.com/research/developer-survey-2016#technology-most-popular-technologies)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 天瓏書局中文暢銷書排行榜\n", + "\n", + "|月份|前五名 Python 書籍有幾本?|前十名 Python 書籍有幾本?|\n", + "|:----:|:----------------------:|:----------------------:|\n", + "|[2016/09](https://www.tenlong.com.tw/zh_tw/bestselling?date=2016-09-30)|2|3|\n", + "|[2016/10](https://www.tenlong.com.tw/zh_tw/bestselling?date=2016-10-30)|3|5|\n", + "|[2016/11](https://www.tenlong.com.tw/zh_tw/bestselling?date=2016-11-30)|4|5|\n", + "|[2016/12](https://www.tenlong.com.tw/zh_tw/bestselling?date=2016-12-28)|4|6|\n", + "|[2017/01](https://www.tenlong.com.tw/zh_tw/bestselling?date=2017-01-28)|3|6|\n", + "|[2017/02](https://www.tenlong.com.tw/zh_tw/bestselling?date=2017-02-28)|4|6|" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python -> 工程師最佳第二程式語言" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## So... Python 2 or 3 ?..." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 注意:\n", + "* Python 3 主要針對了 Python 的 Unicode 的部分做了修正,解決了很多處理字元編碼的問題,但也破壞了向後相容性。\n", + "* Python 2.7 是 Python 2 的最後一個版本,預計只支援到 2020 年。\n", + "* Python 2.7 版只會對臭蟲跟安全問題做修正,不會再增加新功能。\n", + "* 常用的套件,大部分都已經遷移到 Python 3 上。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "[![](../images/py3readiness.png)](http://py3readiness.org/)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 建議安裝 Python 3.x!!!\n", + "\n", + "### (本課程使用 Python 3.5)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/02. Python \345\256\211\350\243\235\345\217\212\344\275\277\347\224\250.ipynb" "b/01_basics/02. Python \345\256\211\350\243\235\345\217\212\344\275\277\347\224\250.ipynb" new file mode 100644 index 0000000..843c195 --- /dev/null +++ "b/01_basics/02. Python \345\256\211\350\243\235\345\217\212\344\275\277\347\224\250.ipynb" @@ -0,0 +1,624 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 安裝及使用" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "3fa64452-39b2-4e24-983d-07a5bf82b02e" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python 環境建置:Anaconda (推薦)\n", + "\n", + "* 版本:2.x vs. 3.x\n", + "\n", + "[![](images/Anaconda.png)](https://www.continuum.io/downloads)\n", + "\n", + "[More](http://www.ziqiangxuetang.com/python/python-install.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 使用 conda 安裝套件\n", + "\n", + "* 檢查 conda 的版本\n", + "```\n", + "c:\\> conda -V\n", + "```\n", + "\n", + "* 更新 conda\n", + "```\n", + "c:\\> conda update conda\n", + "```\n", + "\n", + "* 安裝 package\n", + "```\n", + "c:\\> conda install -n yourenvname [package]\n", + "# 注意:如果沒有加 \"-n yourenvname\",則套件會被安裝到 root env\n", + "```\n", + "\n", + "* 移除 package\n", + "```\n", + "c:\\> conda uninstall -n yourenvname [package]\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 使用 conda 建立 Virtual Environment\n", + "\n", + "\n", + "* 建立 virtual environment\n", + "```\n", + "c:\\> conda create -n yourenvname python=x.x anaconda\n", + "```\n", + "\n", + "* 列出所有 virtual environment\n", + "```\n", + "c:\\> conda info -e\n", + "```\n", + "\n", + "* 啟動 virtual environment\n", + "```\n", + "c:\\> source activate yourenvname\n", + "```\n", + "\n", + "* 停止 virtual environment\n", + "```\n", + "c:\\> source deactivate\n", + "```\n", + "\n", + "* 刪除 virtual environment\n", + "```\n", + "c:\\> conda remove -n yourenvname --all\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Hello World\n", + "\n", + "* 打開 notepad\n", + "* 鍵入 \"print(\"Hello World!\")\"\n", + "* 存成 hello.py 檔!\n", + "* 在命令列使用 python hello.py 執行!\n", + "```\n", + "c:\\> python hello.py\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Python 的程式架構" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "![](images/Python_Syntax.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 重點:\n", + "\n", + "* Python 使用空白字元來定義程式結構\n", + " - 每一行最前面的空白字元的數目是有意義的\n", + " - 同一個區塊的縮排需要一樣\n", + "* 使用 import 來載入套件或模組\n", + "* \"#\" 開頭的為註解\n", + "* 引號(單引號或雙引號)標注起來的為字串" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 怎麼尋找 Python 套件?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "94a40ef6-d5f5-451d-ba73-d11f8d4b2719" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## PyPI (Python Packages Index)\n", + "[![](images/PyPI.png)](https://pypi.python.org/pypi)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 如何安裝套件?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## [使用 pip](https://pip.pypa.io/en/stable/)\n", + "\n", + "* 安裝套件\n", + "```\n", + "c:\\> pip install \n", + "```\n", + "\n", + "* 更新套件\n", + "```\n", + "c:\\> pip install --upgrade \n", + "```\n", + "\n", + "* 移除套件\n", + "```\n", + "c:\\> pip uninstall \n", + "```\n", + "\n", + "* 搜尋套件\n", + "```\n", + "c:\\> pip search \n", + "```\n", + "\n", + "* 列出已安裝套件\n", + "```\n", + "c:\\> pip list\n", + "```\n", + "\n", + "* 列出已安裝套件 (requirement format)\n", + "```\n", + "c:\\> pip freeze\n", + "```\n", + "\n", + "* 將已安裝之套件及版本輸出成文字檔\n", + "```\n", + "c:\\ pip freeze > requirements.txt\n", + "```\n", + "\n", + "* 從 requirements.txt 安裝對應套件\n", + "```\n", + "c:\\ pip install -r requirements.txt\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python 的IDE\n", + "\n", + "* [Atom](https://atom.io/)\n", + "* [PyCharm Community Edition](https://www.jetbrains.com/pycharm/download/)\n", + "* [Sublime Text](https://www.sublimetext.com/)\n", + "* [Visual Studio Code](https://code.visualstudio.com/)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "72048d63-6776-41b6-874e-5ef962c3246a" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python IDE: Spyder (Anaconda 內建)\n", + "![](images/SpyderIDE.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "28a11fcd-516d-4007-ae51-4304d199cfbc" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Python IDE: jupyter notebook (Anaconda 內建)\n", + "* jupyter 由來:[julia](http://julialang.org/) + [Python](https://www.python.org/) + [R](https://www.r-project.org/)\n", + "* 互動式、即見式、展演式\n", + "[![](images/jupyter.png)](http://jupyter.org/)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "e9d95b93-a13a-4adc-9aad-51e724a8e75b" + }, + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## jupyter notebook 基礎常識\n", + "\n", + "* 啟動 jupyter notebook\n", + " - 程式集:搜尋 jupyter notebook => 左鍵點擊 jupyter notebook\n", + " - 終端機 (命令提示字元):輸入 jupyter notebook\n", + "\n", + "* [27 Jupyter Notebook tips, tricks and shortcuts](https://www.dataquest.io/blog/jupyter-notebook-tips-tricks-shortcuts/) ([中譯版](http://www.liuchengxu.org/pelican-blog/jupyter-notebook-tips.html))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 常用的熱鍵或指令\n", + "* 執行區塊:\n", + " - Shfit + Enter 執行該 cell 且跳下一個 cell\n", + " - Ctrl + Enter 執行該 cell (但停在該 cell)\n", + "* 自動填滿:Tab 鍵\n", + "* 提示引數:Shift + Tab\n", + "* 線上諮詢:\n", + " - ?FunctionName()\n", + " - help FunctionName\n", + "* 註解:\n", + " - 單行註解 #\n", + " - 多行註解 ''' '''\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 魔術命令 (Magic Commands) 清單\n", + "%lsmagic" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 的模組及套件" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 什麼是模組?\n", + "\n", + "* 每個 .py 的檔案就是一個模組\n", + "* 模組可以被直接執行,也可以被載入其他模組內執行\n", + "* 每個模組有一個特殊屬性: \"\\_\\_name\\_\\_\"\n", + " - 如果模組被直接執行,\"\\_\\_name\\_\\_\"屬性的值為\"\\_\\_main\\_\\_\"。\n", + " - 如果被載入其他模組,\"\\_\\_name\\_\\_\"屬性的值為自己的模組名稱。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 什麼是套件?\n", + "\n", + "* 套件為用來管理模組的目錄架構。\n", + "* 每個套件目錄底下,必須有一個名為\"\\_\\_init\\_\\_.py\"的檔案。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 套件範例:\n", + "\n", + "![](images/package.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 怎麼載入模組及套件?\n", + "\n", + "* import\n", + "* import... as...\n", + "* from... import..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# Python 的模組搜尋路徑\n", + "\n", + "import sys\n", + "\n", + "sys.path" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 如果要使用的模組所在的目錄,不在搜尋的路徑上,可以使用下面方式加入\n", + "\n", + "# 1.\n", + "# sys.path.append(r\"c:\\path\\to\\the\\module\")\n", + "\n", + "# 2.\n", + "# 也可以設定 PYTHONPATH 參數,讓 Python 去搜尋特定路徑\n", + "\n", + "# 3.\n", + "# 設定一個 .pth 檔,將 .pth 檔放在 package 的存放路徑上,.pth 檔裡面填入模組的路徑" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "import site\n", + "\n", + "site.getsitepackages()" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/03. Python \347\232\204\350\256\212\346\225\270.ipynb" "b/01_basics/03. Python \347\232\204\350\256\212\346\225\270.ipynb" new file mode 100644 index 0000000..78a3519 --- /dev/null +++ "b/01_basics/03. Python \347\232\204\350\256\212\346\225\270.ipynb" @@ -0,0 +1,392 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 的變數" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 變數的命名規則\n", + "\n", + "* 變數名稱最好以英文字母或底線做開頭 (數字不能做開頭)\n", + " - \\_variable, variable, variable\\_ \n", + "* 除開頭字元外,其他字元使用數字、底線、或英文字母\n", + " - _var123, var_123\n", + "* 變數會區分大小寫\n", + "* 避開 keywords\n", + "* 避開 [built-in objects](https://docs.python.org/3/library/builtins.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "字串 = \"Hello World!\"\n", + "\n", + "print(字串)\n", + "\n", + "# 咦... 可以用中文變數耶!!!\n", + "\n", + "# 但是請不要這樣用,因為在使用很多套件時,這樣的變數名稱可能會造成問題。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "import string\n", + "\n", + "# help(string)\n", + "\n", + "# ?string\n", + "\n", + "string.ascii_letters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# Keywords\n", + "\n", + "import keyword\n", + "\n", + "print(keyword.kwlist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# https://docs.python.org/3/reference/executionmodel.html\n", + "\n", + "# built-in objects\n", + "\n", + "# Python 2.7.x\n", + "#import __builtin__\n", + "#\n", + "#dir(__builtin__)\n", + "\n", + "# Python 3.5\n", + "\n", + "import builtins\n", + "\n", + "print(dir(builtins))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 兩個好用的函數:\n", + "\n", + "* type()\n", + "* dir()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 使用 type() 列出變數型別\n", + "\n", + "a = 1\n", + "\n", + "type(a)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "b = '123'\n", + "\n", + "type(b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 使用 dir() 列出 local scope 裡面有那些變數或模組等\n", + "dir()\n", + "\n", + "# 關於 magic methods\n", + "# http://minhhh.github.io/posts/a-guide-to-pythons-magic-methods" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 使用 dir(module) 列出模組可以使用的屬性及方法等\n", + "\n", + "dir(sys)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 使用 dir() 列出物件的方法及屬性\n", + "\n", + "print(dir(b))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "c = [1, 2, 3]\n", + "\n", + "type(c)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "print(dir(c))" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/04. Python \347\232\204\350\263\207\346\226\231\345\236\213\346\205\213.ipynb" "b/01_basics/04. Python \347\232\204\350\263\207\346\226\231\345\236\213\346\205\213.ipynb" new file mode 100644 index 0000000..5c1a205 --- /dev/null +++ "b/01_basics/04. Python \347\232\204\350\263\207\346\226\231\345\236\213\346\205\213.ipynb" @@ -0,0 +1,892 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 的資料型態" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 資料型態\n", + "* 數值 number\n", + " - 整數 integer (int)\n", + " - 浮點數 float\n", + " - 複數 (complex)\n", + "* 字串 string (str)\n", + "* 布林 boolean (bool)\n", + "* 日期時間 datetime\n", + "* None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 整數 int\n", + "A = 3\n", + "type(A)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "B = 2\n", + "C = A + B\n", + "type(C)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 2進位 (0b), 8進位 (0o), 16進位 (0x) 整數\n", + "A = 0b101\n", + "type(A)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "A" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "A = 0xFF\n", + "A" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 型別轉換\n", + "\n", + "# 字串轉整數\n", + "A='10'\n", + "type(A)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "B=int(A)\n", + "type(B)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "B" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 無前綴時,將字串轉乘 8 進位整數\n", + "int('12', 8)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 有前綴時,將字串轉乘 8 進位整數\n", + "int('0o12', 0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 浮點數轉整數\n", + "int(3.6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 整數轉成不同進位的字串\n", + "oct(10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "hex(10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 浮點數 float\n", + "A = 1.23\n", + "type(A)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 浮點數另一種表示法\n", + "B = 1E-3\n", + "B" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "C = 2\n", + "type(C)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "D = B + C\n", + "type(D)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 字串 str\n", + "\n", + "# 字串宣告\n", + "Name = 'Victor'\n", + "type(Name)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "ID = '001'\n", + "\n", + "## 字串串聯 (相加)\n", + "NameID = Name + ID\n", + "NameID" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "# 跳脫字元?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "## 字串分割\n", + "sentence = 'It is raining cats and dogs'\n", + "words = sentence.split(' ') # 注意:此處是 ' ' 而非 ''\n", + "print(words)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 格式化輸出\n", + "\n", + "## 傳統作法 I\n", + "print('Name=' + Name + ': A=' + str(A) + '; B=' + str(B))\n", + "\n", + "## 傳統作法 II\n", + "print('Name=%s: A=%d; B=%d' % (Name, A, B))\n", + "print('Name=%s: A=%d; B=%f' % (Name, A, B))\n", + "print('Name=%s: A=%d; B=%3.5f' % (Name, A, B))\n", + "\n", + "''' \n", + "%d is the format code for an integer.\n", + "%f is the format code for a float.\n", + "%s prints the str() of an object\n", + "%r prints the repr() of an object (\n", + "'''\n", + "# http://stackoverflow.com/questions/15215242/python-2-7-d-s-and-float" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "## 建議作法\n", + "print('Name={0}: A={1}; B={2}'.format(Name, A, B))\n", + "print('Name={}: A={}; B={}'.format(Name, A, B))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 什麼是 Unicode?\n", + "\n", + "* [Wikipedia - Unicode](https://en.wikipedia.org/wiki/Unicode)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "### 什麼是 Encode()?\n", + "\n", + "將字串轉換成特定格式(如UTF-8)的 bytes,以便於儲存或網路傳輸。 " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "### 什麼是 Decode()?\n", + "\n", + "將特定格式的 bytes,轉換回字串以便於顯示。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "a = \"中文\"\n", + "b = a.encode('utf-8')\n", + "b" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "type(b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "b.decode('utf-8')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 從字元找對應的 codepoint\n", + "ord('中')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 從 codepoint 找回字元\n", + "chr(20013)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "hex(ord('中'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 邏輯 bool: True: 1; False: 0\n", + "\n", + "A = 3\n", + "B = 3\n", + "\n", + "A == B\n", + "type(A == B)\n", + "A != B\n", + "\n", + "A is B\n", + "A is not B\n", + "\n", + "res = (A == B)\n", + "res\n", + "res == 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# datetime\n", + "#\n", + "# package: datetime\n", + "# http://www.wklken.me/posts/2015/03/03/python-base-datetime.html\n", + "\n", + "# 取得當下的日期與時間\n", + "import datetime" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "now = datetime.datetime.now()\n", + "now" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "type(now) # datetime.datetime" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "datetime.datetime.now().date()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "type(datetime.datetime.now().date()) # datetime.date" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "datetime.datetime.now().time()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "type(datetime.datetime.now().time()) # datetime.time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "datetime.date.today()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "type(datetime.date.today()) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 1. 字串 -> 日期\n", + "# 2. 日期 -> 字串\n", + "\n", + "# https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior\n", + "\n", + "# strptime\n", + "s = '2017-03-11'\n", + "datetime.datetime.strptime(s, '%Y-%m-%d')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# datetime 2 string: .strftime(Format)\n", + "date = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n", + "date" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "date = datetime.datetime.now().strftime(\"%Y%m%d\")\n", + "date" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/05. Python \347\232\204\345\256\271\345\231\250\345\236\213\345\210\245.ipynb" "b/01_basics/05. Python \347\232\204\345\256\271\345\231\250\345\236\213\345\210\245.ipynb" new file mode 100644 index 0000000..5172d1a --- /dev/null +++ "b/01_basics/05. Python \347\232\204\345\256\271\345\231\250\345\236\213\345\210\245.ipynb" @@ -0,0 +1,472 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 的容器類別" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 容器類別 (資料結構)\n", + "* [列表 list](http://www.runoob.com/python/python-lists.html)\n", + "* [元組 tuple](http://www.runoob.com/python/python-tuples.html)\n", + "* [字典 dict](http://www.runoob.com/python/python-dictionary.html)\n", + "* [集合 set](http://www.iplaypython.com/jichu/set.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 列表 list:[]\n", + "\n", + "## 宣告方式\n", + "list1 = []\n", + "list1 = list()\n", + "type(list1)\n", + "\n", + "list1 = ['B', 'A', 'C'] \n", + "list1\n", + "\n", + "# indexing 索引指標\n", + "list1[0] \n", + "list1[-1]\n", + "\n", + "# slicing\n", + "list1[1:]\n", + "\n", + "# len():計算 list 長度\n", + "len(list1) \n", + "\n", + "list2 = [80, 70]\n", + "\n", + "# list 串聯\n", + "list1 + list2\n", + "\n", + "# list 複製\n", + "list1 * 3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "a = [1, 2, 3]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "a * 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "b = np.array([1, 2, 3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "b" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "b * 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "## in 隸屬 (包含) operatior\n", + "element = 'C'\n", + "element in list1\n", + "\n", + "element = 'D'\n", + "element in list1\n", + "\n", + "## 排序:sorted()\n", + "sorted(list1)\n", + "sorted(list1, reverse=True)\n", + "\n", + "## 排序:.sort() # 注意:會蓋掉原始序列\n", + "list3 = list1.copy() \n", + "print(list3)\n", + "\n", + "list3.sort()\n", + "print(list3)\n", + "\n", + "list3.sort(reverse=True)\n", + "print(list3)\n", + "\n", + "## 顛倒 list\n", + "list3.reverse()\n", + "print(list3)\n", + "\n", + "## 移除特定 element\n", + "list3.remove('B')\n", + "print(list3)\n", + "\n", + "## 刪除 list\n", + "del list3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# tuple 元組:()\n", + "\n", + "## tuple vs. list: \n", + "# 1. tuple 生成後不可修改;list 生成後可以修改 (區別:記憶體能否動態配置)\n", + "# 2. tuple 的處理效能會優於 list,但 list 的彈性會優於 tuple\n", + "\n", + "## 宣告方式\n", + "tup1 = ()\n", + "tup1 = tuple()\n", + "type(tup1)\n", + "\n", + "tup1 = ('physics', 'chemistry', 1997, 2000)\n", + "tup1\n", + "\n", + "# 型別轉換\n", + "tuple(list1) # list 2 tuple\n", + "list(tup1) # tuple 2 list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# dict 字典:{key : value}\n", + "\n", + "## 宣告 dict\n", + "dict1 = {}\n", + "type(dict1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dir(dict)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dict1 = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}\n", + "dict1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dict1.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dict1.values()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dict1.items()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dict1['Alice']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# set 集合\n", + "\n", + "# 宣告 set\n", + "set1 = set()\n", + "type(set1)\n", + "\n", + "a = set('abc')\n", + "a.add('wxyz')\n", + "a\n", + "\n", + "a = set('abc')\n", + "a.update('wxyz')\n", + "a\n", + "\n", + "a = set('abc')\n", + "b = set('cde')\n", + "a & b # 交集\n", + "a | b # 聯集\n", + "a - b # 差集" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/06. Python \347\232\204\351\201\213\347\256\227\345\255\220.ipynb" "b/01_basics/06. Python \347\232\204\351\201\213\347\256\227\345\255\220.ipynb" new file mode 100644 index 0000000..6310d75 --- /dev/null +++ "b/01_basics/06. Python \347\232\204\351\201\213\347\256\227\345\255\220.ipynb" @@ -0,0 +1,403 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 的運算子" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 重點:\n", + "\n", + "* 算術運算子\n", + "* 比較運算子\n", + "* 指定運算子\n", + "* 邏輯運算子\n", + "* 位元運算子\n", + "* 成員運算子 (in, not in)\n", + "* 相等運算子 (Identity Operator) (is, is not)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 算術運算子\n", + "\n", + "|運算子|說明|\n", + "|:-:|:-:|\n", + "|+|加法|\n", + "|-|減法|\n", + "|\\*|乘法|\n", + "|/|除法|\n", + "|//|整數除法|\n", + "|**|次方|\n", + "|%|求餘數|" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 比較運算子\n", + "\n", + "|運算子|說明|\n", + "|:-:|:-:|\n", + "|==|等於|\n", + "|!=|不等於|\n", + "|>|大於|\n", + "|<|小於|\n", + "|>=|大於等於|\n", + "|<=|小於等於|" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 指定運算子\n", + "\n", + "|運算子|範例|同義式|\n", + "|:-:|:-:|::|\n", + "|=|a = b||\n", + "|+=|a += b|a = a + b|\n", + "|-=|a -= b|a = a - b|\n", + "|\\*=|a \\*= b|a = a \\* b|\n", + "|/=|a /= b|a = a / b|\n", + "|%=|a %= b|a = a % b|\n", + "|**=|a **= b|a = a ** b|\n", + "|//=|a //= b|a = a // b|" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 邏輯運算子 (Logical Operators)\n", + "\n", + "|運算子|說明|\n", + "|:-:|:-:|\n", + "|and|且|\n", + "|or|或|\n", + "|not|非|" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "a = True\n", + "b = False\n", + "c = True\n", + "\n", + "a and b" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "a and c" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "a or c" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "not (a and b)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 成員運算子 (Membership Operators)\n", + "\n", + "|運算子|說明|\n", + "|:-:|:-:|\n", + "|in|在容器類別中|\n", + "|not in|不在容器類別中|" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "a = [1, 2, 3]\n", + "\n", + "1 in a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "4 in a" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 位元運算子 (Bitwise Operators)\n", + "\n", + "|運算子|說明|\n", + "|:-:|:-:|\n", + "|&|邏輯 and|\n", + "|||邏輯 or|\n", + "|^|邏輯 xor|\n", + "|~|邏輯 not|\n", + "|>>|位元右移|\n", + "|<<|位元左移|" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 相等預算子 (Identity Operators)\n", + "\n", + "會比較兩變數的記憶體位置是否相等。\n", + "\n", + "|運算子|說明|\n", + "|:-:|:-:|\n", + "|is|物件相等|\n", + "|is not|物件不相等|" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/07. Python \347\232\204\346\265\201\347\250\213\346\216\247\345\210\266.ipynb" "b/01_basics/07. Python \347\232\204\346\265\201\347\250\213\346\216\247\345\210\266.ipynb" new file mode 100644 index 0000000..ac4c6e9 --- /dev/null +++ "b/01_basics/07. Python \347\232\204\346\265\201\347\250\213\346\216\247\345\210\266.ipynb" @@ -0,0 +1,377 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 流程控制" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 重點:\n", + "\n", + "* if 語句\n", + " - if\n", + " - if-else\n", + " - if-elif-else\n", + "* 迴圈\n", + " - for loop\n", + " - while loop\n", + " - continue, break,..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 條件判斷 if\n", + "name = \"Victor\"\n", + "\n", + "if name == \"Victor\":\n", + " print(\"Hi!\", name)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 條件判斷 if-else\n", + "\n", + "A = 3\n", + "B = 2\n", + "\n", + "if A == B:\n", + " print('A = B')\n", + "else:\n", + " print('A != B')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 條件判斷 if-elif-else\n", + "\n", + "A = 3\n", + "B = 2\n", + "\n", + "if A > B:\n", + " print('A > B')\n", + "elif A < B:\n", + " print('A < B')\n", + "else:\n", + " print('A = B')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# for 迴圈\n", + "\n", + "A = range(10)\n", + "\n", + "for i in A:\n", + " print('{} \\n'.format(i))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "help(range)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# for 迴圈\n", + "\n", + "A = range(1,10, 2)\n", + "\n", + "for i, item in enumerate(A): # enumerate: iterator\n", + " print('{}: {} \\n'.format(i, item))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# while 迴圈\n", + "\n", + "count = 0\n", + "while (count < 8):\n", + " print(count)\n", + " count += 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# while 迴圈\n", + "\n", + "count = 0\n", + "while (count < 8):\n", + " count += 1\n", + " if count % 2 == 0:\n", + " continue\n", + " print(count)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# while 迴圈\n", + "\n", + "count = 0\n", + "while (count < 8):\n", + " count += 1\n", + " if count % 2 == 0:\n", + " break\n", + " print(count)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# while 迴圈\n", + "\n", + "count = 0\n", + "while (count < 10):\n", + " if count % 3 == 0:\n", + " print(str(count))\n", + " count += 1" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/08. Python \347\232\204\345\207\275\345\274\217.ipynb" "b/01_basics/08. Python \347\232\204\345\207\275\345\274\217.ipynb" new file mode 100644 index 0000000..5955c3a --- /dev/null +++ "b/01_basics/08. Python \347\232\204\345\207\275\345\274\217.ipynb" @@ -0,0 +1,441 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 函式" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 函式 (Functions)\n", + "\n", + "* 使用 def 定義函式\n", + "* pass\n", + "* lambda function (匿名函式)\n", + "* 位置引數 (positional arguments)\n", + "* 關鍵字引數 (keyword arguments)\n", + "* 預設引數 (default arguments)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 函式定義\n", + "def f():\n", + " print(\"Hello!\")\n", + "\n", + "# 函式呼叫\n", + "f()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 空函式\n", + "def f():\n", + " pass\n", + "\n", + "f()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# def function\n", + "def f(x): \n", + " return x**2\n", + "\n", + "def f(x): return x**2\n", + "\n", + "# lambda function\n", + "g = lambda x: x**2\n", + "\n", + "f(3)\n", + "g(3)\n", + "\n", + "MySum = lambda x, y: x + y\n", + "MySum(3,2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "## 字串分割\n", + "sentence = 'It is raining cats and dogs'\n", + "words = sentence.split(' ') # 注意:此處是 ' ' 而非 ''\n", + "type(words)\n", + "print(words)\n", + "\n", + "lengths = map(lambda word: len(word), words)\n", + "print(lengths)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# function\n", + "\n", + "def MyMean(data):\n", + " total = 0\n", + " for num in data: # 避免使用回圈是提高計算效率的關鍵之一\n", + " total = total + num\n", + " return total / len(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "data = [1, 2, 5, 8, 11]\n", + "MyMean(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# Positional Parameters\n", + "def f(a, b, c):\n", + " return {'a':a, 'b':b, 'c':c}\n", + "\n", + "f(1, 2, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# Keyword Parameters\n", + "def f(a, b, c):\n", + " return {'a':a, 'b':b, 'c':c}\n", + "\n", + "f(b=1, c=2, a=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "f(1, c=2, b=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# * 跟 ** 的使用\n", + "def f(*args):\n", + " print(args)\n", + "\n", + "f(1, 2, 3, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "def f(**kwargs):\n", + " print(kwargs)\n", + " \n", + "f(a=1, b=2, c=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "def f(*args, **kwargs):\n", + " print(\"args:\", args)\n", + " print(\"kwargs:\", kwargs)\n", + " \n", + "f(1, 2, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# unpacking\n", + "\n", + "arg_dict = {'a':1, 'b':2, 'c':3}\n", + "\n", + "f(**arg_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# default arguments?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# decorator?" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/09. Python \347\224\237\346\210\220\345\274\217 (Comprehension).ipynb" "b/01_basics/09. Python \347\224\237\346\210\220\345\274\217 (Comprehension).ipynb" new file mode 100644 index 0000000..60ceef9 --- /dev/null +++ "b/01_basics/09. Python \347\224\237\346\210\220\345\274\217 (Comprehension).ipynb" @@ -0,0 +1,258 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 生成式 (Comprehension)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 重點:\n", + "\n", + "* list comprehension\n", + "* dict comprehension\n", + "* set comprehension\n", + "* generator comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# list comprehension\n", + "a = [1, 2, 3]\n", + "b = [e**2 for e in a]\n", + "b" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# dict comprehension\n", + "word = \"letters\"\n", + "letter_counts = {letter: word.count(letter) for letter in word}\n", + "letter_counts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# set comprehension\n", + "a_set = {number for number in range(1, 6) if number % 3 == 1}\n", + "a_set" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# generator comprehension\n", + "a = [1, 2, 3]\n", + "b = (e**2 for e in a)\n", + "b" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "for c in b:\n", + " print(c)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/10. Python \347\232\204\346\252\224\346\241\210 IO.ipynb" "b/01_basics/10. Python \347\232\204\346\252\224\346\241\210 IO.ipynb" new file mode 100644 index 0000000..c33b7ee --- /dev/null +++ "b/01_basics/10. Python \347\232\204\346\252\224\346\241\210 IO.ipynb" @@ -0,0 +1,387 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 的檔案IO" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 常見的儲存方式\n", + "* 文字檔:txt (tab 分隔 / space 分隔)、csv (逗點分隔)\n", + "* EXCEL 檔:xls / xlsx\n", + "* 網路檔:html / xml / json\n", + "* 資料庫:SQLite / PostgreSQL / MySQL..." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 一般文字檔" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 寫入檔案\n", + "file = open('test.txt','w')\n", + "file.write('this is a test!')\n", + "file.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### mode 字串\n", + "|字元|說明|\n", + "|:-:|:-|\n", + "|r|讀取模式|\n", + "|w|寫入模式|\n", + "|x|檔案不存在時才寫入|\n", + "|a|附加模式|\n", + "|b|二進位模式|\n", + "|t|文字模式|\n", + "|+|更新模式|" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 讀取檔案:\n", + "file = open('test.txt', 'r')\n", + "# 把所有資料一次全部讀進來\n", + "text = file.read()\n", + "\n", + "print(text)\n", + "# 關閉檔案\n", + "file.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 讀取檔案:\n", + "# 如果沒有第二個參數,表示預設的模式是 'r'\n", + "file = open('test.txt')\n", + "\n", + "# 一次全部讀進來,但是分行\n", + "text = file.readlines()\n", + "\n", + "print(text)\n", + "\n", + "# 關閉檔案\n", + "file.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 讀取檔案:\n", + "file = open('test.txt')\n", + "\n", + "# 將資料一行一行的讀進來處理\n", + "for line in file:\n", + " print(line)\n", + "\n", + "# 關閉檔案\n", + "file.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 附加資料 (Append)\n", + "file = open('test.txt', 'a')\n", + "file.write('this is a test!')\n", + "file.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 如果不想每一次都要呼叫 close() 來關閉檔案,則可以使用 with … as 語法。\n", + "with open('test.txt') as file:\n", + " text = file.read()\n", + " print(text)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### .csv 檔\n", + "\n", + "### csv 是 Comma Separated Values 的縮寫" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "import csv" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 台灣證券交易所 - 加權指數歷史資料\n", + "# http://www.tse.com.tw/ch/trading/indices/MI_5MINS_HIST/MI_5MINS_HIST.php#\n", + "# 此範例取自 \"Python 3.5 技術手冊, 林信良\"\n", + "with open('MI_5MINS_HIST10603.csv', encoding='Big5') as f:\n", + " for row in csv.reader(f):\n", + " print(row)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "with open('MI_5MINS_HIST10603.csv', encoding='Big5') as rf:\n", + " with open('10603-UTF8.csv', 'w', encoding='UTF-8', newline='') as wf:\n", + " rows = csv.reader(rf)\n", + " csv.writer(wf).writerows(rows)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/11. Python \347\232\204\347\266\262\350\267\257\350\263\207\346\226\231\346\223\267\345\217\226.ipynb" "b/01_basics/11. Python \347\232\204\347\266\262\350\267\257\350\263\207\346\226\231\346\223\267\345\217\226.ipynb" new file mode 100644 index 0000000..0c4b75e --- /dev/null +++ "b/01_basics/11. Python \347\232\204\347\266\262\350\267\257\350\263\207\346\226\231\346\223\267\345\217\226.ipynb" @@ -0,0 +1,253 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 的網路資料擷取" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 重點:\n", + "\n", + "* 怎麼使用 requests 擷取網路資料?\n", + "* 處理 json 資料\n", + "* 處理 html 資料" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "import requests\n", + "import json" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "r=requests.get('http://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindAllTypeJ')\n", + "r.text" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 載入 json 檔案\n", + "doc=json.loads(r.text)\n", + "print(doc[0]['categoryName'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "dict1 = {'a':1, 'b':2, 'c':3}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "doc1 = str(dict1)\n", + "doc1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "doc2 = json.dumps(dict1)\n", + "doc2" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/12. Python \347\232\204\344\276\213\345\244\226\350\231\225\347\220\206.ipynb" "b/01_basics/12. Python \347\232\204\344\276\213\345\244\226\350\231\225\347\220\206.ipynb" new file mode 100644 index 0000000..9156946 --- /dev/null +++ "b/01_basics/12. Python \347\232\204\344\276\213\345\244\226\350\231\225\347\220\206.ipynb" @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "\n", + "# Python 的例外處理" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### 重點:\n", + "\n", + "* try... except\n", + "* try... except... else\n", + "* try... except... else... finally" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "a = 1\n", + "b = 0\n", + "a / b" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 如果知道可能產生的錯誤是甚麼\n", + "\n", + "try:\n", + " a / b\n", + "except ZeroDivisionError:\n", + " print(\"哇!除數是零!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "try:\n", + " a / b\n", + "except:\n", + " print(sys.exc_info())" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/01_basics/13. Python \347\232\204\347\211\251\344\273\266\345\260\216\345\220\221\347\250\213\345\274\217\350\250\255\350\250\210.ipynb" "b/01_basics/13. Python \347\232\204\347\211\251\344\273\266\345\260\216\345\220\221\347\250\213\345\274\217\350\250\255\350\250\210.ipynb" new file mode 100644 index 0000000..e56cce6 --- /dev/null +++ "b/01_basics/13. Python \347\232\204\347\211\251\344\273\266\345\260\216\345\220\221\347\250\213\345\274\217\350\250\255\350\250\210.ipynb" @@ -0,0 +1,511 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "nbpresent": { + "id": "904e7041-5347-4036-bfff-4b5af4763913" + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Python 程式設計教學\n", + "\n", + "## Victor Gau\n", + "\n", + "### [victorgau@gmail.com](\"mailto:victorgau@gmail.com?subject=[Question]QF20170311\")\n", + "\n", + "### 2017-03-11\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# 物件導向程式設計\n", + "## (Object-Orientation Programming, OOP)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 注意:\n", + "\n", + "* 解決問題並不一定需要使用物件導向設計。\n", + "* 雖然在 Python 中,萬物皆為物件!但Python之父 Guido van Rossum 曾經說過,自己並非物件導向的信徒。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 物件導向設計的三大核心觀念:\n", + "\n", + "* 封裝 (Encapulation)\n", + "* 繼承 (Inheritance)\n", + "* 多型 (Polymorphism)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## 重點:\n", + "\n", + "* 怎麼定義類別?\n", + "* 生成物件 (Instantiation)\n", + "* \\_\\_new\\_\\_, \\_\\_init\\_\\_, \\_\\_del\\_\\_\n", + "* 類別屬性\n", + "* 類別方法\n", + "* 靜態方法\n", + "* 物件屬性\n", + "* 物件方法\n", + "* 繼承\n", + "* 多型" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 定義類別\n", + "class Human:\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 生成物件\n", + "human1 = Human()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 定義物件屬性\n", + "human1.name = \"Victor\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "human2 = Human()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "human2.name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# __new__(): 要生成物件時被呼叫,初學者通常不會實作這個方法。\n", + "# __init__(): 要初始化物件時被呼叫\n", + "# __del()__: 要刪除物件時被呼叫\n", + "\n", + "class Human:\n", + " # 類別屬性\n", + " count = 0\n", + " \n", + " def __init__(self):\n", + " Human.count += 1\n", + " \n", + " def __del__(self):\n", + " Human.count -= 1\n", + "\n", + "human1 = Human()\n", + "Human.count" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "human2 = Human()\n", + "Human.count" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "del human1\n", + "Human.count" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "del human2\n", + "Human.count" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 增加兩個方法,描述物件的行為\n", + "\n", + "class Human:\n", + " # 類別屬性\n", + " count = 0\n", + " \n", + " def __init__(self, name):\n", + " self.name = name\n", + " Human.count += 1\n", + " \n", + " def __del__(self):\n", + " Human.count -= 1\n", + " \n", + " def sleep(self):\n", + " print(self.name, \"sleeps!\")\n", + " \n", + " def attack(self):\n", + " print(self.name, \"attacks with bare hands.\") \n", + "\n", + "human1 = Human(\"John\")\n", + "human1.sleep()\n", + "human1.attack()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "# 繼承\n", + "class Knight(Human):\n", + " pass\n", + "\n", + "# 父類別的方法被繼承下來了\n", + "knight1 = Knight('Jack')\n", + "knight1.sleep()\n", + "knight1.attack()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "# 多型\n", + "class Knight(Human):\n", + " def attack(self):\n", + " print(self.name, \"attacks with a sword.\")\n", + "\n", + "class Wizard(Human):\n", + " def attack(self):\n", + " print(self.name, \"attacks with a spell.\")\n", + "\n", + "human1 = Knight(\"David\")\n", + "human2 = Wizard(\"Tom\")\n", + "\n", + "group1 = [human1, human2]\n", + "\n", + "for man in group1:\n", + " man.attack()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "class Human:\n", + " # 類別屬性\n", + " count = 0\n", + " \n", + " def __init__(self, name):\n", + " self.name = name\n", + " Human.count += 1\n", + " \n", + " def __del__(self):\n", + " Human.count -= 1\n", + " \n", + " def sleep(self):\n", + " print(self.name, \"sleeps!\")\n", + " \n", + " def attack(self):\n", + " print(self.name, \"attacks with bare hands.\")\n", + " \n", + " @staticmethod\n", + " def fight(man1, man2):\n", + " print(man1.name, \"fights\", man2.name)\n", + " \n", + " @classmethod\n", + " def default(clz):\n", + " return clz('John Doe')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "human3 = Human.default()\n", + "human3.name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "Human.fight(human1, human2)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "livereveal": { + "scroll": true + }, + "nbpresent": { + "slides": {}, + "themes": { + "default": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "theme": { + "56b38c57-4ffe-478a-9f92-8ca64a17c67c": { + "id": "56b38c57-4ffe-478a-9f92-8ca64a17c67c", + "palette": { + "19cc588f-0593-49c9-9f4b-e4d7cc113b1c": { + "id": "19cc588f-0593-49c9-9f4b-e4d7cc113b1c", + "rgb": [ + 252, + 252, + 252 + ] + }, + "31af15d2-7e15-44c5-ab5e-e04b16a89eff": { + "id": "31af15d2-7e15-44c5-ab5e-e04b16a89eff", + "rgb": [ + 68, + 68, + 68 + ] + }, + "50f92c45-a630-455b-aec3-788680ec7410": { + "id": "50f92c45-a630-455b-aec3-788680ec7410", + "rgb": [ + 155, + 177, + 192 + ] + }, + "c5cc3653-2ee1-402a-aba2-7caae1da4f6c": { + "id": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "rgb": [ + 43, + 126, + 184 + ] + }, + "efa7f048-9acb-414c-8b04-a26811511a21": { + "id": "efa7f048-9acb-414c-8b04-a26811511a21", + "rgb": [ + 25.118061674008803, + 73.60176211453744, + 107.4819383259912 + ] + } + }, + "rules": { + "blockquote": { + "color": "50f92c45-a630-455b-aec3-788680ec7410" + }, + "code": { + "font-family": "Anonymous Pro" + }, + "h1": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 8 + }, + "h2": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 6 + }, + "h3": { + "color": "50f92c45-a630-455b-aec3-788680ec7410", + "font-family": "Lato", + "font-size": 5.5 + }, + "h4": { + "color": "c5cc3653-2ee1-402a-aba2-7caae1da4f6c", + "font-family": "Lato", + "font-size": 5 + }, + "h5": { + "font-family": "Lato" + }, + "h6": { + "font-family": "Lato" + }, + "h7": { + "font-family": "Lato" + }, + "pre": { + "font-family": "Anonymous Pro", + "font-size": 4 + } + }, + "text-base": { + "font-family": "Merriweather", + "font-size": 4 + } + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git "a/02_numpy_matplotlib_pandas/01. Numpy \347\260\241\344\273\213.ipynb" "b/02_numpy_matplotlib_pandas/01. Numpy \347\260\241\344\273\213.ipynb" new file mode 100644 index 0000000..0ec86ad --- /dev/null +++ "b/02_numpy_matplotlib_pandas/01. Numpy \347\260\241\344\273\213.ipynb" @@ -0,0 +1,752 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Numpy 簡介" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Numpy 是 Numerical Python 的簡稱,是 Python 用來作科學運算的基礎套件。\n", + "\n", + "#### 這一份筆記主要說明以下重點:\n", + "\n", + "* 為何需要 Numpy?\n", + "* Numpy 比 pure python 提供了那些不一樣的東西?\n", + "* 怎麼使用 Numpy 的 ndarray?\n", + "* 投資理財相關領域中常用的 Numpy 的函式有哪些?\n", + "\n", + "#### 參考資料:\n", + "\n", + "* [Numpy 官網](http://www.numpy.org/)\n", + "* [Numpy 教學](https://docs.scipy.org/doc/numpy-dev/user/quickstart.html)\n", + "* [Python Numpy Array Tutorial](https://www.datacamp.com/community/tutorials/python-numpy-tutoria)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 為什麼需要 Numpy?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 關於向量運算:\n", + "\n", + "在工程、科學及金融領域,需要用到很多向量運算。簡單說明如下:\n", + "\n", + "假設有兩個向量 (Vectors) A 跟 B,\n", + "\n", + "$A = \\left(\n", + " \\begin{array}{c}\n", + " a_1 \\\\\n", + " a_2 \\\\\n", + " a_3\n", + " \\end{array}\n", + " \\right)\n", + "$\n", + "\n", + "$B = \\left(\n", + " \\begin{array}{c}\n", + " b_1 \\\\\n", + " b_2 \\\\\n", + " b_3\n", + " \\end{array}\n", + " \\right)\n", + "$\n", + "\n", + "向量加法運算如下:\n", + "\n", + "$A + B = \\left(\n", + " \\begin{array}{c}\n", + " a_1 + b_1 \\\\\n", + " a_2 + b_2 \\\\\n", + " a_3 + b_3\n", + " \\end{array}\n", + " \\right)\n", + "$\n", + "\n", + "向量的純量積算法如下:\n", + "\n", + "$c \\cdot A = \n", + " \\left(\n", + " \\begin{array}{c}\n", + " ca_1 \\\\\n", + " ca_2 \\\\\n", + " ca_3\n", + " \\end{array}\n", + " \\right)\n", + "$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. python 的 list 沒有辦法直接作向量運算。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "A = [1, 2, 3]\n", + "B = [4, 5, 6]\n", + "A + B" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "A * 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. 替代性的方法運算速度緩慢" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "C = []\n", + "for i, j in zip(A, B):\n", + " C.append(i + j)\n", + "C" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "D = []\n", + "for i in A:\n", + " D.append(i * 2)\n", + "D" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. Numpy 提供簡易即迅速的方式執行上面那些向量運算" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "A1 = np.array(A)\n", + "B1 = np.array(B)\n", + "A1 + B1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "A1 * 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Numpy 提供了什麼不一樣的東西?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Numpy 中主要提供了一個叫做多維陣列 ndarray, or Multi-dimensional Array 的資料結構,透過它可以直接作向量運算。\n", + "#### ndarray 有兩個重要的屬性 dtype 及 shape,dtype 為 ndarry 裡面的資料的型態,而 shape 則為資料的形狀。\n", + "#### 底下會用例子加以說明。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Numpy 中的兩大概念:\n", + "\n", + "* 資料結構\n", + " - ndarray\n", + " - dtype\n", + " - shape\n", + "\n", + "\n", + "* 通用函式\n", + " - ufunc\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 如何創建 ndarray?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 最簡單的方法就是使用 Numpy 的 array 函式。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "X = [1, 2, 3]\n", + "Y = np.array(X)\n", + "Y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "Z = np.array([4, 5, 6])\n", + "Z" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "Z.dtype" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "Z.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 其他的創建方式\n", + "\n", + "|函式|說明|\n", + "|:-|:-|\n", + "|array|將輸入的資料轉換成 ndarray。|\n", + "|arange|range 的 ndarray 版。|\n", + "|ones, ones_like|創建一個全部是1的ndarray。|\n", + "|zeros, zeros_like|創建一個全部是0的ndarray。|\n", + "|empty, empty_like|創建一個未填入資料的ndarray。|\n", + "|eye, identity|創建一個單位矩陣。|" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "I = np.eye(4)\n", + "I" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "I.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G = np.arange(25)\n", + "G" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "F = G.reshape(5, 5)\n", + "F" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G.shape = 5, 5\n", + "G" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ndarray 的 indexing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[1, 1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[1][1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ndarray 的 slicing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[0, :]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[:, 0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[:][0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[1:3, 1:3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ndarray 的 boolean indexing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G > 10" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "G[G > 10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.where(G > 10, G, 0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.all(G > -1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.all(G < 25)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.all(G > 0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.any(G > 0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 什麼是 ufunc?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* universal function 的縮寫\n", + "* 用來對 ndarray 裡面的每個元素作操作的函式。\n", + "* ufunc 可以被看作是一般 python 函式的向量化版本。\n", + "* Numpy 的 ufunc 都是衍生自 numpy.ufunc 類別。\n", + "* 很多內建的 ufunc 底層都是使用 C 實作的,所以速度很快。\n", + "\n", + "詳細內容請參考:[ufuncs](https://docs.scipy.org/doc/numpy/reference/ufuncs.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "isinstance(np.sin, np.ufunc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "isinstance(np.arange, np.ufunc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import math\n", + "math.pi" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "K = np.arange(0, 2, 0.1)\n", + "K = K * math.pi\n", + "K" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.sin(K)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt\n", + "plt.plot(np.sin(K))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### numpy 有哪些 ufuncs?\n", + "\n", + "想知道 numpy 有哪些 ufunc ,可以參考官網上面的連結:[Available ufuncs](https://docs.scipy.org/doc/numpy/reference/ufuncs.html#available-ufuncs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 金融投資相關領域中常用的 numpy 函式有哪些?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* [Numpy 的函式列表](https://docs.scipy.org/doc/numpy/reference/routines.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 統計相關函式\n", + "\n", + "參考:[Statistics](https://docs.scipy.org/doc/numpy-1.12.0/reference/routines.statistics.html)\n", + "\n", + "|函式|說明|\n", + "|:-|:-|\n", + "|sum|總和|\n", + "|mean|平均|\n", + "|std|標準差|\n", + "|var|變異數|\n", + "|min, max|最小值、最大值|\n", + "|argmin, argmax|最小值的索引、最大值的索引|\n", + "|cumsum|和的累計值|\n", + "|cumprod|積的累計值|" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 亂數相關函式\n", + "\n", + "參考:[Random Sampling (numpy.random)](https://docs.scipy.org/doc/numpy/reference/routines.random.html)\n", + "\n", + "|函式|說明|\n", + "|:-|:-|\n", + "|[seed](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.seed.html#numpy.random.seed)|設定亂數的種子|\n", + "|[permutation](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.permutation.html)|隨機排列|\n", + "|[shuffle](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.shuffle.html)|沿著 axis 0 的隨機排列|\n", + "|[rand](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.rand.html#numpy.random.rand)|返回指定形狀的亂數,亂數值為[0,1]間的均勻分布|\n", + "|[randn](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randn.html#numpy.random.randn)|返回指定形狀的亂數,亂數值為mean為0,variance為1的高斯分布|\n", + "|[randint](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randint.html#numpy.random.randint)|使用離散均勻分布,返回指定形狀的整數亂數|\n", + "|[normal](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.normal.html#numpy.random.normal)|返回指定形狀的亂數,亂數值為自訂的mean跟variance的高斯分布|\n", + "|[uniform](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.uniform.html#numpy.random.uniform)|使用均勻分布,返回指定形狀的亂數|" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "np.random.seed(10)\n", + "np.random.rand(5)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [conda root]", + "language": "python", + "name": "conda-root-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git "a/02_numpy_matplotlib_pandas/02. MatPlotLib \347\260\241\344\273\213.ipynb" "b/02_numpy_matplotlib_pandas/02. MatPlotLib \347\260\241\344\273\213.ipynb" new file mode 100644 index 0000000..bcca85c --- /dev/null +++ "b/02_numpy_matplotlib_pandas/02. MatPlotLib \347\260\241\344\273\213.ipynb" @@ -0,0 +1,631 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "# MatPlotLib 簡介" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### MatPlotLib 是 Matrix Plotting Libray 的縮寫。它是 Python 最主要的 2D 繪圖套件,是用 Python 來畫圖的首選套件。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 這一份筆記主要說明以下重點:\n", + "\n", + "* MatPlotLib 的架構\n", + "* 怎麼使用 MatPlotLib 畫圖?\n", + "* 針對一維資料作圖\n", + "* 針對二維資料作圖\n", + "* 控制線型、顏色\n", + "* 控制圖形參數(標題、X軸、Y軸標題等)\n", + "* 圖形上的文字標註\n", + "* 圖面上的中文顯示\n", + "* 子圖 (Subplot)\n", + "* 畫其他的圖表 (散步圖、餅圖、直方圖等)\n", + "* 金融圖形 (K線圖等等)\n", + "\n", + "參考資料:\n", + "\n", + "* [Github of Python for Finance](https://github.com/yhilpisch/py4fi)\n", + "* [Github of Python for Data Analysis](https://github.com/wesm/pydata-book)\n", + "* [Wiki - MatPlotLib](https://en.wikipedia.org/wiki/Matplotlib)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## MatPlotLib 的架構\n", + "\n", + "MatPlotLib 的架構分成三層:Scripting Layer, Artist Layer, 跟 Backend Layer。\n", + "\n", + "Backend Layer 負責將圖形實際繪製出來。屬於比較低階的操作,一般使用者較少直接接觸。\n", + "\n", + "Artist Layer 負責告訴 Backend Layer 要畫那些東西,是用來組成繪圖物件 (lines, rectangles, text, 等等) 的地方,Artist 物件主要分成 Primitives 跟 Containers 兩種。Primitives 為需要被畫出來的圖形 (lines, rectangles 等),而 Containers (如 axes 等) 則是用來放置圖形物件的地方。\n", + "\n", + "Scripting Layer 提供了更簡單的操作介面,讓使用者可以更容易地去控制 Artist Layer。初學者大致上只會用到 Scripting Layer。\n", + "\n", + "參考資料:\n", + "\n", + "* [MatPlotLib](http://www.aosabook.org/en/matplotlib.html)\n", + "* [Artist Tutorial](http://matplotlib.org/users/artists.html)\n", + "* [Plotting commands summary](http://matplotlib.org/api/pyplot_summary.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[](http://www.aosabook.org/en/matplotlib.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[](http://www.aosabook.org/en/matplotlib.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 怎麼使用 MatPlotLib 畫圖?\n", + "\n", + "在 Jupyter Notebook 裡面使用 MatPlotLib 畫圖可以加上底下的魔術命令,讓產生的圖形嵌入 HTML 頁面中。\n", + "\n", + "```\n", + "%matplotlib inline\n", + "```\n", + "\n", + "我們主要使用的是 matplotlib.pyplot 這個模組來做 scripting 的動作。\n", + "\n", + "慣例上,我們會用以下的方式載入模組。\n", + "\n", + "```\n", + "import matplotlib.pyplot as plt\n", + "```\n", + "\n", + "接著,使用 plt.plot() 函式即可作圖。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "# 載入 pyplot 時,通常使用如下慣例\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# 載入 numpy 時,通常使用如下慣例\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "plt.plot?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 針對一維資料作圖" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.arange(10)\n", + "plt.plot(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "如果是寫成獨立的程式 (.py 檔),則需用下面程式來顯示圖形。\n", + "\n", + "```\n", + "plt.show()\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 針對二維資料作圖" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.random.rand(10, 2)\n", + "plt.plot(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.random.rand(10, 2)\n", + "plt.plot(x)\n", + "\n", + "# 畫點\n", + "i=3\n", + "plt.plot(i, x[i, 0], '^')\n", + "\n", + "# 畫線 plt.plot([x1, x2], [y1, y2])\n", + "j=7\n", + "plt.plot([i, j], [x[i, 0], x[j, 0]], 'k-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 控制線型、顏色\n", + "\n", + "參考資料:[matplotlib.pyplot.plot](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.arange(10)\n", + "plt.plot(x, 'r')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.arange(10)\n", + "plt.plot(x, 'ro')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.arange(10)\n", + "plt.plot(x, 'ro-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 控制圖形參數(標題、X軸、Y軸標題等)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.arange(10)\n", + "plt.plot(x, 'ro-')\n", + "plt.title('Demo')\n", + "plt.xlabel('X Axis')\n", + "xplt.ylabel('Y Axis')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.random.rand(10)\n", + "plt.plot(x)\n", + "plt.grid(True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.random.rand(10)\n", + "plt.plot(x, label='line 01')\n", + "plt.legend(loc=0)\n", + "# location code 請參考:http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.legend" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.random.rand(10)\n", + "plt.plot(x)\n", + "plt.xlim(-1, 10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 圖形上的文字標註\n", + "\n", + "參考:[Text Introduction](http://matplotlib.org/users/text_intro.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = np.random.rand(10)\n", + "plt.plot(x)\n", + "i = 5\n", + "plt.text(i, x[i], str(x[i]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 圖面上的中文顯示" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from matplotlib.font_manager import FontProperties\n", + "font = FontProperties(fname=r\"c:\\windows\\fonts\\simsun.ttc\", size=14)\n", + "\n", + "x = np.arange(10)\n", + "plt.plot(x)\n", + "plt.title('中文測試', fontproperties=font)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 子圖 (Subplot)\n", + "\n", + "參考資料:[Subplot Demo](http://matplotlib.org/examples/pylab_examples/subplots_demo.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.subplot(211)\n", + "x = np.arange(10)\n", + "plt.plot(x)\n", + "plt.subplot(212)\n", + "y = np.random.rand(10)\n", + "plt.plot(y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.subplot(121)\n", + "x = np.arange(10)\n", + "plt.plot(x)\n", + "plt.subplot(122)\n", + "y = np.random.rand(10)\n", + "plt.plot(y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.subplot(221)\n", + "x1 = np.random.rand(10)\n", + "plt.plot(x1, 'ro')\n", + "plt.subplot(222)\n", + "x2 = np.random.rand(10)\n", + "plt.plot(x2, 'b^')\n", + "plt.subplot(223)\n", + "x3 = np.random.rand(10)\n", + "plt.plot(x3, 'gx')\n", + "plt.subplot(224)\n", + "x4 = np.random.rand(10)\n", + "plt.plot(x4, 'k*')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 畫其他的圖表 (散布圖、餅圖、直方圖等)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 請參考:http://matplotlib.org/examples/shapes_and_collections/scatter_demo.html\n", + "N = 50\n", + "x = np.random.rand(N)\n", + "y = np.random.rand(N)\n", + "colors = np.random.rand(N)\n", + "area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radii\n", + "\n", + "plt.scatter(x, y, s=area, c=colors, alpha=0.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 請參考:http://matplotlib.org/examples/pie_and_polar_charts/pie_demo_features.html\n", + "# Pie chart, where the slices will be ordered and plotted counter-clockwise:\n", + "labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'\n", + "sizes = [15, 30, 45, 10]\n", + "explode = (0, 0.1, 0, 0) # only \"explode\" the 2nd slice (i.e. 'Hogs')\n", + "\n", + "fig1, ax1 = plt.subplots()\n", + "ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',\n", + " shadow=True, startangle=90)\n", + "ax1.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# bar chart - 1\n", + "N = 10\n", + "y = np.random.randint(1, 10, size=N)\n", + "x = range(N)\n", + "width = 0.5\n", + "plt.bar(x, y, width, color=\"blue\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# bar chart - 2\n", + "N = 10\n", + "y = np.random.randint(1, 10, size=N)\n", + "x = np.arange(N)\n", + "width = 0.5\n", + "plt.bar(x - 0.25, y, width, color=\"blue\")\n", + "plt.xlim(-1, 10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# histogram\n", + "x = np.random.randn(1000)\n", + "n_bins = 10\n", + "\n", + "plt.hist(x, n_bins, color='g', rwidth=0.8)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 金融圖形 (K線圖等等)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.finance as mpf\n", + "\n", + "start = (2014, 5, 1)\n", + "end = (2014, 6, 30)\n", + "\n", + "quotes = mpf.quotes_historical_yahoo_ohlc('YHOO', start, end)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(8, 5))\n", + "fig.subplots_adjust(bottom=0.2)\n", + "mpf.candlestick_ohlc(ax, quotes, width=0.6, colorup='g', colordown='r')\n", + "plt.grid(True)\n", + "ax.xaxis_date() # dates on the x axis\n", + "ax.autoscale_view()\n", + "plt.setp(plt.gca().get_xticklabels(), rotation=30)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(8, 5))\n", + "mpf.plot_day_summary_ohlc(ax, quotes, colorup='g', colordown='r')\n", + "plt.grid(True)\n", + "ax.xaxis_date()\n", + "plt.title('Yahoo Inc.')\n", + "plt.ylabel('Prices')\n", + "plt.setp(plt.gca().get_xticklabels(), rotation=30)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "quotes = np.array(quotes)\n", + "fig, (ax1, ax2) = plt.subplots(2, sharex=True, figsize=(8, 6))\n", + "mpf.candlestick_ohlc(ax1, quotes, width=0.6, colorup='g', colordown='r')\n", + "ax1.set_title('Yahoo Inc.')\n", + "ax1.set_ylabel('Prices')\n", + "ax1.grid(True)\n", + "ax1.xaxis_date()\n", + "plt.bar(quotes[:, 0] - 0.25, quotes[:, 5], width=0.5)\n", + "ax2.set_ylabel('volume')\n", + "ax2.grid(True)\n", + "ax2.autoscale_view()\n", + "plt.setp(plt.gca().get_xticklabels(), rotation=30)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [conda root]", + "language": "python", + "name": "conda-root-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git "a/02_numpy_matplotlib_pandas/03. Pandas \347\260\241\344\273\213.ipynb" "b/02_numpy_matplotlib_pandas/03. Pandas \347\260\241\344\273\213.ipynb" new file mode 100644 index 0000000..9ed6177 --- /dev/null +++ "b/02_numpy_matplotlib_pandas/03. Pandas \347\260\241\344\273\213.ipynb" @@ -0,0 +1,668 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "# Pandas 簡介" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pandas 是 Python 裡面被用來作資料分析及整理最常用的套件。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 這一份筆記主要說明以下重點:\n", + "\n", + "* 資料結構及其基本操作\n", + " - Series\n", + " - DataFrame\n", + "* 網路資料存取\n", + "* 資料視覺化\n", + "* 資料分組及聚合\n", + "\n", + "參考資料:\n", + "\n", + "* [Python Data Analysis Library](http://pandas.pydata.org/)\n", + "* [Pandas Cookbook](http://pandas.pydata.org/pandas-docs/version/0.18.0/cookbook.html)\n", + "* [Pandas 入門介紹](https://github.com/Wei1234c/Introduction_to_Pandas)\n", + "* [Financial Time Series](https://github.com/yhilpisch/py4fi/blob/master/ipython3/06_Financial_Time_Series.ipynb)\n", + "* [Pandas API references](http://pandas.pydata.org/pandas-docs/stable/api.html#api-dataframe-stats)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "pd.__version__" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pandas 的資料結構" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Series" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s = pd.Series([1, 2, 3, 4, 5])\n", + "s" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Series 跟 ndarray 有什麼不同呢?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s.values" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s.index" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### index 可以在創建 Series 時指定" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "s = pd.Series(range(5), index=list('abcde'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### index 也可以在創建完 Series 後指定" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s.index = list('fghij')\n", + "s" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 什麼是 reindex?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s.reindex(list('hijabcd'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### DataFrame" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "data = np.random.randn(10, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df = pd.DataFrame(data)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.columns = ['No1', 'No2', 'No3', 'No4']\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.index = pd.date_range('2016-01-01', periods=10)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.ix['2016-01-06']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.drop(datetime(2016, 1, 3), inplace=True)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.index=range(9)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.ix[1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.drop(4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 使用 Pandas 作資料存取\n", + "\n", + "### 這一部分包括底下幾個重點:\n", + "\n", + "* read_csv() 的使用\n", + "* read_html() 的使用\n", + "* 如何抓取股市資訊?\n", + "\n", + "底下練習一下將 [台灣證券交易所 - 加權股價指數歷史資料](http://www.tse.com.tw/ch/trading/indices/MI_5MINS_HIST/MI_5MINS_HIST.php#) 的資料轉成 DataFrame。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 使用 read_csv() 讀取資料\n", + "\n", + "參考連結:[pandas.read_csv](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "df = pd.read_csv(\"data/MI_5MINS_HIST10603.csv\", encoding=\"Big5\", header=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.drop(df.index[len(df.index)-1], inplace=True)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 使用 read_html() 讀取資料\n", + "\n", + "參考連結:[pandas.read_html](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_html.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import requests\n", + "from bs4 import BeautifulSoup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "r = requests.get(\"http://www.tse.com.tw/ch/trading/indices/MI_5MINS_HIST/MI_5MINS_HIST.php\")\n", + "r.encoding = 'Big5'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "soup = BeautifulSoup(r.text, \"lxml\")\n", + "tables = soup.select(\"table.board_trad\")\n", + "tables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "type(tables[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "df_list = pd.read_html(str(tables[0]), header=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df_list[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 使用 Pandas 讀取股價資訊\n", + "\n", + "參考資料:[pandas-datareadre 說明文件](https://pandas-datareader.readthedocs.io/en/latest/)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import pandas_datareader.data as web\n", + "from datetime import datetime" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df = web.DataReader(\"TSLA\", 'yahoo', datetime(2016,1,1))\n", + "df['Close'].plot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 資料視覺化\n", + "\n", + "Series 跟 DataFrame 都附帶有一個產生各類圖表的 plot(),預設的情況下,它會產生線形圖。\n", + "\n", + "參考資料:[Pandas Plotting](http://pandas.pydata.org/pandas-docs/stable/visualization.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s = pd.Series(np.random.randn(10), index=np.arange(10))\n", + "s.plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s.plot(kind=\"bar\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD'))\n", + "df.plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df.plot(kind='bar')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 資料分組與聚合" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "data = np.random.randn(10, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df = pd.DataFrame(data, columns=['No1', 'No2', 'No3', 'No4'])\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df['Category'] = np.NaN\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "clist = ['C1'] * 3 + ['C2'] * 5 + ['C3'] * 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df['Category'] = np.random.permutation(clist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "groups = df.groupby('Category')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "groups" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "groups.mean()" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [conda root]", + "language": "python", + "name": "conda-root-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/02_numpy_matplotlib_pandas/data/MI_5MINS_HIST10603.csv b/02_numpy_matplotlib_pandas/data/MI_5MINS_HIST10603.csv new file mode 100644 index 0000000..6123f19 --- /dev/null +++ b/02_numpy_matplotlib_pandas/data/MI_5MINS_HIST10603.csv @@ -0,0 +1,21 @@ +"106 ~03 oq[vѻƾv" +"","}L","̰","̧C","L" +" 106/03/01"," 9,751.12"," 9,758.78"," 9,674.78"," 9,674.78" +" 106/03/02"," 9,727.60"," 9,774.60"," 9,646.34"," 9,691.80" +" 106/03/03"," 9,672.26"," 9,679.82"," 9,633.88"," 9,648.21" +" 106/03/06"," 9,647.00"," 9,688.50"," 9,647.00"," 9,682.63" +" 106/03/07"," 9,690.26"," 9,738.07"," 9,690.20"," 9,738.07" +" 106/03/08"," 9,744.26"," 9,773.49"," 9,712.50"," 9,753.45" +" 106/03/09"," 9,740.05"," 9,743.78"," 9,650.32"," 9,658.61" +" 106/03/10"," 9,653.79"," 9,656.65"," 9,562.75"," 9,627.89" +" 106/03/13"," 9,656.56"," 9,697.34"," 9,656.56"," 9,697.34" +" 106/03/14"," 9,720.53"," 9,767.66"," 9,720.53"," 9,744.21" +" 106/03/15"," 9,741.29"," 9,749.01"," 9,714.58"," 9,740.31" +" 106/03/16"," 9,768.85"," 9,842.17"," 9,768.85"," 9,837.83" +" 106/03/17"," 9,845.59"," 9,908.69"," 9,835.51"," 9,908.69" +" 106/03/20"," 9,905.81"," 9,916.18"," 9,869.35"," 9,912.97" +" 106/03/21"," 9,923.18"," 9,976.61"," 9,918.39"," 9,972.49" +" 106/03/22"," 9,911.96"," 9,922.66"," 9,843.07"," 9,922.66" +" 106/03/23"," 9,921.97"," 9,945.24"," 9,897.45"," 9,930.74" +" 106/03/24"," 9,914.12"," 9,932.68"," 9,892.31"," 9,902.98" +"" \ No newline at end of file diff --git a/02_numpy_matplotlib_pandas/images/artists_figure.png b/02_numpy_matplotlib_pandas/images/artists_figure.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a2c1cdc77674e260f34230054665ece4250c00 GIT binary patch literal 28982 zcmaI8by$@_*Ec$wMnJk7>FyAuk(5$oqr@g`X^;}wgmej#Qi2EyQlbJ98<3DT=#)^p zJI`#N^F8PNuIs(dA6)Ex-!p6dR?M2U)(k`%8)}nXV7dSRAk)>+GzEY_6#%?)A{_Wc z*q#yt0K>%x8XCsB8X6qNZq9cfJiY^fcV@EBJ!6{H!PPZ!DREMTznu5JS-AD;5STE8 zWwHiG5Yw7q=<)C=Dex(81S5DN6Y(?+7{sY*Xz*xhX%Jb*EiS!YeO^n0{sA7VxB5mO zmDPW#t*vDT&-JUmenq|@;Sg0$|809ucXyjSH_;kgU@%7Gd)(i7tx4kLb?=~Td6|d< z0P1!b7l_$ z%c_T8sK{^wbRx~{A|Aj2I!sx2XNiG2(6M$%3)yzAHM&t^0%CjgodBp2{m;Gg`^-2HK>{%N3lrbbJNBS4dY zU3+ftli%9B1-@rZKYw0&Z+X6v{~&G+U=Zj({S2T{DVN8#;t3nzAVUxG@qY0;E%oG6 z9^Ca3TX2wX8JzX1V@YwCJuJNG_B!=c%s)mb{rCK)J~cH-e5L2XJmP1B!|-`i54HV7 zR^Ysybqo!;Gf2S4G`Gyu2R^b>cqRR)&_=4Mvx)9L1}#n$&Bmh#uzd5YU%+2DzX@67NW^U|=jV+Or=W)#DQL2`1$Xk*CZKgg$clCy*gX930goLa?@)CuSO}^g1kN#gcD(7ISO#3*R zkOQEJ#!u<#_E<0-bm)&qHpn>&Rex5r&U~Y|78$TLM7KTgy>MxlJ`5L7ph+_^gv}fX z$y}m`x%j>)(myENxM>3GX>#VEi_a+tNry?tQ1lLJqAa0Y{Lf}xs0=l5Eko%R&`t~C zoYjQ!(+V*yG~LZgPoL4^sp$|YHb)a(N{nF13%<`u5Fua}B7cc3LWL?ulVeloLM7Qq z$Q;)*9RbtGOf^vsM;$rI2+~VN&xsuf4r7G#8T8Z+ja_fBnQ4<5ll&syRhP@9T;P>v z?a|!sr>eT}Ui;;DCl4b3(75~$3tR*Y%)Dq_+lOh0yU%KD5lHzq%oCIXQsU+_8N1bC zum_mi|CF!GQ~qszTg~JYGd4RZ&pH*ljv=2eICxOU*chjR;oI;z;S0**xN6MFK*>TB z5K7d1SDo%vnz2T;!NMgaE(6L2sz^;l9*#-QeWM+|tJI&V$SL9}`zXIew0s@Z7L}c?eXG<(GvFr-?ir{$YCV6MHTX~1rBn?;>ib^51Dsr+T3#HMY=8s z(HFB6Qx-En;$Nm4d^-4W@X6qplItZx4o;OgBcUr=alGqXsR_*A{O9QB#2!C>{Nr)h z4+yJI z^?%_X8Io#G7LKdU-)4N^2%L3J~ZXo+h*BjiDvv}k!CS17s@-&J-J?L32Gi` z{?RQA!b4I`%2d7Q?_Shi`pEU3V^yU7_EF}JK4WD} zkU@2~Z8}@JkAD+`;75`#=*en=Gfbrw~Yy1jNw-?E~;p=HFQH=ov7E~qwOEMxsqZ?}R; zt4CeL?7g9*T`Y#_ugsUBs*=N8(PFk->s;mBv+Ek>mu}|YnyulDf0O^mspm;g->uGD z9`7aJhmWp|ei~K$c>ANuV$nkA;*ABR@ACtm-zN&k@{cu)Y~o)H70Km`6|?5ROty7#x$I-d-O(Z5AH32@dP%O= z-#sW_B>w3tB_Neykvt;g&bV#7&9wcQPLJ+8-7X!wu#7NcN~%bs1*3)I=cUTFlGPIT zlJ((@VehdQqcNj;V^@a{jk{?)$F2U&xx7m~C04UT|;w`?Bn#^Q-mhoZ6`;jhum$=lth`z!Yty zdJQw<`*K%nxe&(__XCc$EdOJjG4W~>2m6(_Vzo@Qs@yjy^>XKpk!iCG=J!#b7-lF; z*(8lV=dr))3(E*+yO>2RMJz<>$LvI9&7jO`OXbRM$NNLLQr=CpQ}CVi()B9;oy`Sj z2`7n<65YtDVRu(y*CtoTO{GnV%^_-TsvlHg)Miv4sM_Ti9R)|F`&{gPadYZ2C*Ddr zOr%b7F5rK&axGm)=9-AU)#%EH8i80v5#`lEx_Ob2+mmm`-sFr%ITtvuj_`hT9QqWw zN;f9t#i6MFWM}2YNP3OCV2kMNj_6itn$>5oM=PS^_2uneMt*O+?_T}0T>r#xxl+E8 z!6JU2ab2;2eTx0#x#6cLd*4@b6kaLFxy!gkyPK2ulaHThZ|5WiruqE#@!Hzm61qr5 z-p0-%ATA_t)nS!peQ=b}_3BT{uNH-H`l#S2f@sgEcy>;9T?I+&8OtBOH})2q@{0?e z7sPi8cl9PmC*MmARHXA=33%qCHS4-LThpFuq?zSy`oMg|lE=pEX`;8}?%d0VIZHv; z2?~3EMf{o@JSmDTV^vvoJvw4MmAcm(mDN+Gv240@cL{fST?Q#vCHqe1W;V5asvlc# zVP>Eg=RtFaR$=s&YXsL~Q|CmJZT{3}{)~}!evs`P`Iymp*O}GH{qgbxIj6>_cY2aX zFTRbdEIu*cE_+^f$J+kM8!yo(JWqN&wLKcwh?jgOmxqowj%t^^jxvv&cExSD_r(fRhldgXxFJoEfeeZ^jD5W-$*j zH(s{A;<}vtxAi-7V zoT+WL6vY2wckVgvG4i*2Y8Rlqp>?3Y8r-Yimv=m~FjQS8H072Onrav*cc5Ip^5x{o zoo&GfALqh<#P8)8s@RCnrgdvFg%H4`9OVA~4RRhKhEEaR>xcw}0DtCFYX%%N4!CHU zOJrD1dyA50Q&Tk8?mnU|-U<^!{38^9hG>zui)dL+R##8jkGxRWTp*s*`ATCtCfGPV z;tRu<1IKSH0?v#kBY(H}Xf=}OZ(JSNE7pH#*YcKA*>~-(gF1O4s|NcDHD1?$Qei*Xd_9Ay?`r@em zWhz11yG(1$l=SJeW^DeVZxr{O#*ruCp#|6YLlU_&g;VpAAJ&d=_5|wR@a?`i=9o98 z?6f{*^3nbFRg7rJ1eYJG&*RU=WN8V>@xwiHhtxkT-$bq$?-`j{YXpon1qEwAyB^-a zVlC`zezMZBnz)vqsxOw3CFU$Yh;;pZFi*{ze8nt;FT7aWFm|x+ZI;66S@+)$(Vir` zIn2tk0SbLSYO{Hdu6Gw)NfpX?c{}V@&gY&_Wgg|$^Nm+mZ!G;-l3jIO+5N&cnL3(t z#n^TB$8>*B@2hvW89(E$GmOvIAOE(Va#=jRM*f)Xf>NfB#~to<*AD8e!qCF_oB@?S z@874Uo;2+K(w{sn-Rd53?a(e4ZD$F}=q}L9(60wf9C-eDx&Aqu=Xt?&K}JE%x^7pV zP^`+GGy{MMBD~RrTRBb89N+)^Q4!9qNCA|Hw|J1Aw|1Rj?bjcjzAsPW)bGU4EzBqW zJ_}EMCZ?@wxe>KNU}8{W*qqwQIUw@knxSsMjS6Fn+XaTP?$=_Da^Ga!Y}m^yZL}^7 zs`_o1U-9t`Z^0Xzo*|20NYUGh!!L##D$QMVTuR(CT%WsIt>2thE_Z6Z{=KV9vE}b; z=fRDM2{Iu^yp%Ii5j z+1)f-!zHcEHi zZ7D5Ut@?DnZz~x5U3HxP>w}D^*HS7oPv1z6QMJo~-SwX#`q4cnBBSrw93xkK%tfEX zSXwQhb$UD8U#dtW}Cmj|Z_6^va&~=dXM046GG+H12IbB^f-SY}r@1EZ; zeyqY3@JZ@p`pa~4=m)AnWSXkf9r%4Qk-JUTbQjEy>>h=0& z3T{cooT@B&6!RB3ZKA(-OEt!?Dee2vA0Fbz;NymVB1w&|idLq0No(_*+XTPh#p_rH zONWrTnfafzl{DmntY*ruO!IxOu6AeqTpD2Fla8*ctorGh=i$FwvOC1E!5sYicK*w@ zze6eM4lkV~qNVrC#XsDrn)!TWd*zPQ{V|kRhw_ANNPc=!jMR6ZwmTgko8Dutcv>Zd zzb~v!&6WFeWnF5;uT!jbiVH1-dV2Z{bA`E1w$t&1%|oa$B4&60g2 zi!bm0YRbqP-TL|QUPkYe!HH6K=L3&87wfs;Bdzc^{rY~Q<}&-A3_h8R%9I^=tu&0f ztXj~&x?O+I-??}9O+zZ~9P_P^s+YSOLZ9ESt<;SLte^Ui5ZaO#v-=0E96M~JZ*M3gys^yA2!IKBZU-IauPC~m5shOGvD|OczBz zeH1#|8joA|c>P#|s0xGMY)eR^acQSTAF0Y8A#E30ed&3J;T+MAh@DIJ9aNpq1oKkv zb7VxZX)gB%?9g_8)s(>PX4Y@JXnSoKcZH-ket8yg@Z^LWhA!R+$`vBr(Am)2q3fDj zd19{Y70L1%RF`U!Ds{|tNrc}C{}whA&M&bmS+?l1Xz!4mC$&jMz#6EJzXCCF5Sk&#ngI!bAg=vaxDq*dMXHs2pd4yX7bCM}%#kJ@k_<-B|5tfrIj zg{2GGcR zGJpTekXb`-MRr_6h};uWp2?BRnOo)4o5}aYv@3|izl|=I?6*b>OnIiTm(|($ALakK z$CE@1aB_(aDK08b6J>@oi(k|ylFJK4a-4PWauX^j_eHYeYjFs^2))aZJ2B%dW2q~PT`hUb%^Q-}RkBvb&@z3?d~wX+-Jo($ZfZTYN>XRSJG=K)H84>11&5EYKJ>s3&yQ`hcD?1#@=WTV97dP>{#Mf;$;4z!2}t^5)Pom&UYWN{YDH-IYR+r! zf8}z0v-y%bgX%A1lrH7BWC0_&?biy9BQKRdi8vg8&N}=;^Tg}!(dubKnedqWy%|;O z$5C>3zG$S9!1ee6C|!Q^CC& zujXC#K=qjSinsNK(~SMBVyknDiik1Cec^+v3lZf>L|i{aGX&p=ec}$#vitH{COP&p zm#5|Bt8He3nugle7HYRlEOiYmEVb0l)Es-5E_o7?1@>sZKOL31Twj}X-wJ(vn^}Q23hrDd#m44dKOhE zlG?MUj8Qi7uHM=eU!MzU*Xye!|1~ROS%3T5?EMY;frWud6>1ahB9+l1f2RfYU#$iD zT0QSXhQ?&8#60G#udlGI#4Yexm92R(A1EUw=AJUwyRT#~xU}NVhi6@)G(u*7x)Sg6 zO=47jO;KY1vXk3Z?BB6Zj169EAN>9>P3{LWoE^9{od2BfBW(OCS|r*ndh_YW^P|JD zGoFe9_o;!#9IF(oQly%Bv$<1gsl~+S%O@H;+QaegDk*`rCy(trrAX2Z(63z_MF3Fc zPXVDOyxY-A;4Q_pHX^CUwAJBEo)}#Z7NSl)*KmO991efqiSu9fbHd1yA38oS06PGH z*hR;}9RRi#><^+YHFXpK4xp>4cEdY!Wn#>2Os7)Sq$hOK^T@g}(?%n7R>`I0?l#Vh zX=+Ky$Lzb~RK%S$@5gnF&kwi%_R&LvKy!C$k`Vg=+{P2e{!*td$NnO^hQXdla7ZIa z;4gIl|L@CyU1c~3rPNiabpE@xbTu9i&3N*+FGr<59sxka@}1&QqXC@h%UD|89ul|e zFWp7B#G&y4I58@4+BNuwGfjbgcR#h1jo$*SaH0?ZQ|IehOejeQ#;~l@OcFdijoNUg zS+V2ZxR+Y9UN9)cO^?CHNMWDwx>X6$e$(Z%OMy?W{2Sv^#AUXmO&NzkQxYQqNSHcv z`^C$wrN{00aol_1oDDpmT@K>Q2x3u)~&zMc!as~#N8%VsyQ7)X7eWuJ!pTx{|7qPLH=#ypOD zQovRAfX{A_zpMa<4ggZIfcjcD?v!$LMU{_ZOd#nUtRBScL>2W!Qc0wRQ8Z+GrsR=N zlnPHj??XF*)NYq&R&UyIxIY!ry$_U;&(8TWw*4G2_4q6sYb%z)fLU`hxC27y zlD(Z=W8H<>rms)4=;2eeZFK?#(Vc$BH}Tg*rla3s*=SS-;P(&h>DyJc7T>d%5ymQU zEA5rFMKjI}Np@)f>92CExfqO!Ugg!B@M>^W#18$gu+G2w0Ev~FTcYKNRu%8T(m>DN zK%AQOdEh_i|GsQXie~U_r3WjV}Ez+ZgBhqEAe-NzsG|UV2AjeXOZ%s~DMo38DQ4%eemG31Z|3620raN&GSN zAKCNr0DKqctAausZgl8_e7u`Z#1ZhIKde<2mu^3+pBH3IA}a-p9IzxOg-b zkiu#Z#ZVf9i!#JMjOn>R1s1WIP!-(!1-1?cj-g1_l>!HRsbfj|!a|IRHRsHwD#V*yJZOFd6^5>HnBW<& z2{l{XTw{DN`t>bd)OhCQ${`LE z<3RS>pF$ZECdZ1N_#;)f8kE6C{<;Dc1Rinc_+Ea_`H|Aw00aGF{qfblb!XdiZMwRj zLb44p%r-4T`)*%8a>TFAvpTYmg>ag7d@1~?L{EkD>*t>s*5ewuz=tdEeG=Q9ov0KR z2{b+Nwozd(KfgpWxk#(%{QAKBOH=;XA@_q5%M1LQEuRDMJzg9P$S6b3@~BUgu7QLC z2h^*rFE8&bu96>jUST^OXKafhZsf5!JA78fhRfeQgb{mwzY5x36%agFFH$_t=mCbDMcx(Cj#tGyC4w zm31A@&A3lft&6kTYk{+`!pVz|TAwzQm369wteq#aZEeQ>Ryiv;If*x2|H?ka?Hnf4 zVvkqreMr8;E%qLP)ot_PfxB%JYtc*~a>>w0Gv~DNxa`N5wE8dYT=7nQtd1u>PRD_< zm}*NUqJERmz-!Rwb7SP4aXwzJs`-4d8S0CsCx0`qc#llbt3_{v0&P&oKOudls{u({ zAA6^p6)BsVHEG{kkEZ)wS$)^5)?a&DNot?jcW_kRJ8($V(fZ!Z29!!wQ{~d~4Hfyp zfO{3z`&!InfrTHZstSI@7Mp{K`r~VgvE=_q4yVhq5&U7I-a1|FlP$A8^d*S7o@jyV z&wSH$iI!r}rL3s1_3-m;tkXQ&xHOtw>w1jV4X_S%{~;~Bdx2=e#yV} zxvx@qES$cv0RcndeB_B+Mm(7?;K)19p*i*NR>yEoP1)PC@0T~sTrpBs*3DxT$51?a z|2Onj<56W0K2WN*W{mQRI(=l3?|1N{XCvY5((HA9L$mP@-t&q$3->>z=HB03>VgZW z-0^R`fNR_I^io!#;|4S5>~MfbcI>`#!$-?dGvR1+3`J+dOFsvRbDoco?hEt9zu68d ztbevQgFpT(JsI#DU3q%FMs&6_`*>H5=qvq)1Dc_Id<&?UGuNZ`vSpS2mGje(e7}8u z-&5<=%6YrL*9QEW=e!eXKA(GCsyf6G4fH?JfhxNbb~*)ZJV}Igz1Tq0k?aRQPb?31 zcaYY~OVlh>#bwW`` zNC%8tllMa+PFk)D?3PvvCwrD295{_Tt}RUXuO15CxyHvnMYTNHr)_=mFw>jh?&%Tk zBH3vGl38qslI;bIZzp}bUIGsp^|($r%=%hCKkd8);+3n$jS_!4*`#RLe9LDJHqQ<^ z8$=&`I=?dNgtWDp4<0HOgGPz9_GvmG$9NoJ6@+)TU21er;A`%tu>=UDo|uZCXVq z8vzFSL%M`>X<%q*DDdp$@aHi@_3Nc$nYyQJ;l2d8sxCEC7K>-!dHn8EFC|teIikPI z_>Hye5nK*nM$SIi`w}a6cD;yC0)U~9mb%+5+zD;fe#n;h^(4r;jZGhx!&i_L9t==z?Vy@p8@nA9>HH%NM`n*t@6A58y7~{h+U7T*!Vk zef|C}u`P z2O{6&pl7ZgzS_tfkG}{E6+L!M-zIw66|pbmxIqH|kXxRWN;KyV$@0GwS!&-#UN248bzD^?>s;*1vnVGv)-E z0(5=MZ0-6ufqK=;AO^16Wtq3%E{x4M33edZ2gP+!W zNeIOX4vFm}WOwY3?;o>0%qYYw@cv(@i{K8vBHw6kipNv2)r?acvt#oKF2uX@zX1tv zFjooKxSHpCc7+IsPBHe3y6q}%RAwn#s4q>v3J-tpf009t?RUR|DMg$6!siFsLA8HT!9@BL}N2rvu(@bh<*5Qdn# zG)z9Fd~*aZr-^g9FOcF1U)XMLiU@t_*T4i5rB;^9xQOWHIu~)eia$Iy&>0E-KY9@c zA9{ue0h%*SG)oH!=d>y<%b!gC;!z&9Nvqy6IuXPTw(3XRKmrgApqZbQ+sg`FLL8JFJA;3-_P8t zN*~p;d^r2~H>AE%ae^4BO0Zk|7R_&T`+dF^p4VW#H8r4U^f)aRta*upF zMC+m`l@g{UhC?SVyDP{`MgpcM&svKK2;Dasq=joK%F#h@&7VJjnXnvtv{5Lmw_CV4 z5F`xAzO*@E_@KPd`lCXkhO(>-S#%qoFiK}>fFG95sJmmye4{f1Qe@Hc@Tt<$0P>7a`ytd}Hljr&;lf)xYjb!_OQT9%ReWwngUOhM_Q(?`V8e_>NW1cCsdahAqIl z;%b34SvzwrE|B8CU8bj1RLQeEziM84r<$@HEm3_WObA6y8+_$!RwidvHxjG;%GM+q zDo3@xQxnpo@}qZsGFUw7XG-qnvF2{2qeG8FN0H^591n%2P}>ZInUR|clMB{7D#g5&312-!L(i>%lA40XHAlEow8Ro!Nfa$OOnz5Ti z{n=tqU7a76fOZxBQhYEM2j6aVUOqnlwHSjBD@9d~$!h<*Sj#IG?!Su*xY@)bY))yK zg2w+^VBLc?eAu?+PZ~@AN*#PTNd4L8hM9CIltD47b}1PnY-<9mqtIMy*V!^QklQwB zwiQJHP9PpNGelmCqL_r5bXl3sg>Xr=ee(qoBn#cGAuF%o_n3|` zlt~mCf9JLJW*i?bj2yRhj3eRoQTxI$M^SD(!1duao(Kd>BkSaim6zr_?`I3ud^Sj< zr8OioA3nl_LY}z0QKw2*0NNyULS?iuz-*SYdN7d-zL43C%D2=Z0w4+YZ5Yr{0GBv? zemAK9HzhVEQSkf5cWB(Xqo(p96G_-)y02Y7bHRuKaKv#AW`xP>4C`WWPz+cs!;AOp zD;2a{aOnCYc7>w);hq_Fy)42AgLBKc4DQ8@^yG>0X#5-Zw8JWeA+X0Tn;ZfV`=i0K zYD4To(yiwzwy7rvI=!tS0Q6%by9fq^2<&i4igfDp*!1DrQTZkG1B){m;@Y8lcNY52 zd{QM_56VHeY!0{U+eNFWob~IFYcYf zF#L|G$olPF8n}p_y*018hh0IPs=F8T;AY>U3i0q#)>t3XhW@&QLh!)S8lb4Go@B() z<#}4IT0aj#tAIOD?3Kq#t^vi@>7b$m{Z|XFCgobIS>VvQMD7YTZ#~8X1TvQOzCM^>CfJO^ z_$<-lR)pe%Dvu+8~La@z)?lU;x zz675*a^FX4uyDg915FOm_)>`g+zA1}W@go=U1jTPJq%7mL!Fl*%$b8=nX@4VT?=q9AxL0r4S;|B zBc)0R2)rUfiYqRgZzQh6FA*@yKC`t8_reAXRj4t89)pX_+*YuEt`6U{ms}jfvjJd1 z3lr><-uC;FE$q2tZCfUG{qoACV;rCgoy(w;<)Y%ZFEE^Bq4CrDeuGUoYLvPhb(Pme zevWhN=pyWuL3^fUVeN_SUZXCjXiwu|qfP&FG`_n}TJ3uq*j=Q^ffd0QY*0a4!{IQ( zRd;xi0pJ1S2SyhwP%asQ<-peXt=^V`aH;5iJKs|M959TQ-e$r7H2njP-<>}9u{d{B!Gbe%g={-i82}ia$#tf zlrqsU%M%BniWAi&Y%ps4(t#9!WFlljiUku>LKqwcqs|*tTbOL9JxmYPFu|Dy-}_@! z;i!+q$b_6lrdx^d@E}(nK|&>|qGA6(INmqXgd8g&uC_T+tB6(@w_wapPcM2!F91*7 zFHn_p&`L>pa5LfpRURC=*LPCF8u0GGKOlfsP%`N1&vJoGWFV9z0Vb}5WXOaFL6RuW zr$Mm=#iHRusj2_D7olMZnJhylm{8JJ5iof+hU;V`Et8We5;75`Do1(WwI|ZigQJ4+ zgmqfGNhOGTU;+3Hjc+eS3$>eoZJL`YJ=W~RKF&bnWBU z9;6Hn!kHe#NoWg+?NOAYNZ(lMXrSTzeAw$+ z(9MRQ;vuE@T{4EObvrmg6BCR;_CxB?4)5@%ZF;x zF{n#Oz5$(*8Bds~$ABbK_XhywNl+;9Wp$@u8CY9iLaAB4vCuI}gFLQ49w7qscR6lD zS}@e%-HCgq+wl{2o}nIa#iyE;zCMC=Ixk91lNXs5r2`4W^P-4e2NKxXo`X;$S}*d# zY?Pv$gXM#eK}RVM0FU7pX(^Fz-44jW4~Oon-NR=OhzB7}m@>Pj-?hE#CJRrd;3$f1 zK?B22a8xP;+sQ%_0gu~UAUqmgvuXW0_}m=w>cArz*BOJeVH;dknhH+Ea>LVy_0d0y zzmW}Kjd&bJ6O>xuo9oj-2@vEyoY?y7f>Kfq0;IugFe_a@D0S{J00*2XHI6@K)2tQD z0G&>Z>`#iM8RmEhrH_T~WS>w6$3sUnL4JhfvA7o6B=I+%S3#OEEaTZ;#owc7fMcLW z{nONgvhbW>Tqw^~`6*DIb3*nn(^|ls5VLT(!&I#XrZVX5lsi6WEuL1JvbB26nu2+tLOKb)x8IiJ&| z{`Q|)52&kk4hR6YA-`jL0lze<6-p3_mU-v3Y+lMm+LcL6!x;$izQW?Iwzdx9PoT9u z!-EPqeT;JLt`wfUMZ$4$EDL~cRm==2*)l&huW^EiApm!0snkD>i!wY-FHX5rbMT0w zu%7Ar9Px|Y)6>;w_@JYQ4j+duKKsj$t8JHkue-yIh-UwI-?>Z#V3a-;>iaw*5apb+ zk+r7zRmAmJ7sy0d05Hdka)ntaMK}j6pOx^0dp{J^gnxwV8dU3Gf}fP=gWZmKco4;l zid~x6OL|{q+?}LqRtc4pL{To^ciWEDt{3kibq@k`=wX-MSHTu6+AERbX_JfGCHoON^z zASY@BNogfqi!jL`h5(WYIe6c)0`x0lq)TKv1(Cif90PZ{C^VQKrLl1Va`-Il%Da2@iL@CgkR5 zz*bZUl3sBHj)KlMoS+7$*63`&PuiGZD`5fbR9MpIPai?G|K~0M%UvHthh{ER0z7_E zmYP6(BZ5q0;Pz*4;IFDIc?Ezbxb=%)QeXqOP%B(ZU;%0gi^U>x7v2ltMK#e; zvnHhd4>WVUBk=E@VDtgoiGQF-!DxJEi>q)Znh3&eO~et${S7Im;R$>9&=4A^{|^M) z3F`47@|2_4p*IN;H%a(No)zWNp7h4~g+`Z${Se;^R&6JQ5uV`%&7 zW&KJxMjSzM*7^gcJ3#Xis_AwLB@B~C06Gtw^@Roia70y}mi3l&nnw-Jgzb-m@CPsu0~{(?hV-oz<6!f% z)?eNBfO(|=2T+8f@z3oIaff-2a6x}G)MFjb8q{bIy0vc2oY(;F=>Jjg%DkXD0I(yI z_JWZV#i#fV=5Tzdpb^q(zz4_NhxIB@rZ_@iO=fp>5PN?E#eqZj;loYf@&ay-K$;gN z!Rk(rA$C)NjWJ@RL5~tv>`iEOjO`~21h}t@u@mJLMgM&K9)gU901WJaxjft*Rbd|j zl&9`M&B5H1x&rH);1ZPc1rH8-IgSxjCO_m+h>5Pg&`G;PA}0~0lY%!nM_hRhzAi}lU5A}q2wV~mt-qg zA;bJ!r`G`AI5O)d02!3!X%QAAxomuJcoEFzfuS4BHqf$o!jc~@VxbWeA-kJ1V2NVL z45>$=wQl|4M-ybSLFxzyA*~FIx@^H2Ojr-1;v7H=98gzTfI~e;6rr%u;2*8i7iU3dhr@U`Y5X<2)$&u6taP7Ll zCgjW04>_%5o=Rhk4W=1jCCg3y>E3J0qC)0#aqPE}oSv z?HOpB55)r>CJ*Rj?XHi-V6o!^5rs{lD!E(Aj>l%eTHYWm9oM$#3ze7lLh)UO9LlGx z_`5L5%M}>Vm+zf?QX63ag04ph^!QACQWRCl5xlvTuUf!LYT-c zu)ww7$*_2b1Q}kN>>!JJPf1N`i+B1&{vQhFs+1sTM}mjJT{S^kHw}ky9p*h?uz}T*x>O(F{!@hq zzCPc|(~;EmB>o+iKNXe2hb#FPGW+#G7)IrCD5yvm7dNh|!9E|~;|Uy9ueN*5dTixS z*U5Ug;jY%7rjU`ANGSZn<&*4-XUjKC(4ejs$9WO39SA5!P8TouRRiPXysr_7geAw$U3V;2 zY{{C&;hrMSr6IS=O^&oNdf+osIP`rB1NU2ZH%VOd!HR^M{vj?M5Xa*a0Xi6Eyc>xs zD4#=y=<6_<0uP3-=f9Xk=+`r4T;Bvz?s~YO%?=d4n?o#*)Ecd~WWKP#N4XhV0r8a7 zmi#zenG=}%u6CH(OSE7$Xnd*S+mm0i6EN$A_=rhg)&SBayB>=a9&PeUZFRK|c*0Y% zo9Xa>HlTn1VwM%UQ^N8fhPa2SoFN(-xZ2eh7yT`{2N~}4Fz}_H&xbu7{zob30ts9U ze`Xut2&&Xr*o`q;uhg8Cbu`%FUF)hO!q_S_K~EulXf>2dS$II<8z`peeCS~%sZ4!s zi>xHvS;5wu$gmFArBC-FJjGf0IW2B|R&%E1`VDt*d*3v{*$tpVk{ChEyj2;aN9~Io zB7Pr?9npT_;5E2!tMazUltiyj1T4^@RIpco7S3LT6%!#M#I!$}lo9D;@}#6-SWakJ zpr^7fGdDKcno{RKjl*U)b=$B&${_}AW+!q~bmns#!75k7?!r4wM0yoCD0yalzLmir zwWZfa5$Dz!8eS-qK!PYU8vIU{Om(^1Zsht61Cr<;9oJxM5Y1SUXcbRa>>b=efEd_LgZ z#Ngpz3_p1w7|esiWWK6NhGZg^+s_g`3w&Ikf5U@rj)Oo6&&rm>OI7X)-Rh(+|1=fh zbT~KOg9FIq2N0NkW!Vxm%zV zZuDhWC243^cO8X=P}-oQ@@ZO>6MH`@ZGyeaU~nhd2RHg4(~xkQrBDMfjP^3@Y!1a) zRh*|-6>H+*&|OQH1M*n)N-Dev)k`j!@9i~uUJ6@}dCcxaFr5>?!7La)mK8C&=>K%J zCBzq|Kqv;o0FcnvYPgeGWk_Fa8jdGpu*tiI_xlE{1u^=HQ{(kLwyLVK0fxxy9N_imv*eYA=?ke8KO&Om;KB(%@hF%{r4zhK3Qu`i<$W%y z3K%8;@sQnbt+$I@6O5D5S|o2szy&uhJdm9<_-V48#GDveb$1Em3K!}EfITlkZ_2ac z0C8GG^in1RHlc;h-20ux?%<(IB_7;=B5?+{I=jdhJVOB{z%U91SNkZmr?mb9B)$R< zHrQIeP(i&lag{f_sCvaP9hToIDyY@ZrH|G%uiVRA|h^J@zpa^!y7t@6(n zExq11zDPVkLZ+%xFcPvXoA-^}uctoT%VHzUB{QeQ0k5U?F?x%ff>%zami0|PIzU#`Z022#Li!C2rP;d9?i?57!KnUEb%q4~uC zIa+NZN79v+6Yi^6AM;$UU4jt--0%!M`kKsdYzd>wOO0bawUn1`2aV^)jq~-B+Jvfi zVZV_hDfash4~57RW~AI_;g6?PDWy@{JovcvJ=^NS;~^Jm8=s{*;_D`Wk}jfg`_Z3QnZn5MNuk642mQfBugqKTSZdH zk|j%a@43_eeV^a^zRxp{$9KESx%ZxX&gXp2-G1nuT+^}M?-pj9`AJu$(G@*6)Nmg?dorg`EL_i{5zu>gXOKE3%kEc+?*L$L7{E8!n)p+EJ_zp%@n9@Ke9t-q2bA` zW9R&OKC^Z#ex8b(wJ2MRQ(U>Hw`1$?i4_p2<9`)Epm0ovr{m4zrSYLPiL;9{W7~E0 z-&Ws!eykNHMNc9L4JCtdq_-)I$JLb}PiD6_6d=hJFT?e*K00C@QWo3y;`#O7N?G@(DMek zsnWi{8qS48vu-AB5Xc@oTWVv^bqop4_0`zUK0u!YU@3>3L4m+J@8!J`u7|e(cJF~ zBHsL7zPI*Z#5I=%EvyB+rVql30bm;_43tfn%c8WE5O+xFQCRwG_iOMW>R&^wtZKTN zv;%xzz^e5J+!{Vy`sW%DkytYL*fld^2GCiN2Z(kII!4DPBD)1S%u>G4ZXs&F7#gXU zC9?JvhNPE*xZMG{dO8)0P&?>1#1(H!Go!Xlm^(f`F=SEyQ5@B?piYx%b&lsZSI`a( zyRl$CQAifjYzOwU8+@i*Ft7-Y0uCwzt1H((xP7Rki4~?Tc2O zDob9)YSXkACx_m9^#`{?zzUj6@60D*&0th5zbZnNR?5UG6Tk=EQZ%yLLgLI)=E80d zHwf{n`Pu?jG6=r&ia{ld`4{jT11?+ZOCgf^&^I15Jcee0JFK?>+m(aBe#^>4U|8!uV~hOwFiuhPQx*N zR>Z*{miAyOvMlPg5h4I|0s8mNOKpCo_orwlTQnfL3NSUej$4^a&8 zH{yv2U@Tk9+d$|G;lLePNoPTL`>nsM&-=C~B!&-ZKY`-z`^@ul>Am4<{?jtKUP^w7?F*&eM=-iF9T0; z`7X!^F$W1b-&drkZ!bIZ9kkKmX15T9Wr&O#0bkZ>WX~hNUB|_35>08^CqfkXP)zi8 zZkqGz{odp4HR?_EiP*qv5kt<)3EUAbqAjACLVL#sur$ImF_DWu&G||K57< z+&Ylxsj%8Ka1l{Ve4Idx)gO8wFrP+s#q$9+skcTPu%Lh3Q2ytQy6;&4Wb5GbHAfep zpPCIy=Y`!y_f&q&Yj+u{(4_kgZp3^Wz)9wuEg(O62u=iR?R`Z=Pw;yYF>>CH8{n(_ zd?mi*`e%%82?)9FPL4%q3fA)71ts%)(6vJh$p4jEoWjXl`C{q;{0J|)mIMC1y)E)y z+l_c&WhykrABLgwQzoLlyE@h!m3R!D+mbKFH?8uG72?;;3y#tYKr{|*uki+Dvy*@f zlK{_=-WbM{?gL#Ui_J1)J^~dD&W206fh_aX`S!tTMu|yRP?x_lAs?$)TRjs3=XXvH zUuBrt?z?ROn1a|f^pwMdiD7!=oW#SMW>S(Da|vJ2H}S9ove;*7KT>A=5KZGEyNjcR zQ5sepY5V{;g&h6Nw!+XOvI8ODdjK&5*b`{kuKiFt0M4KxX{$ZGxnN~cwEZ;buMbvO zy5fsXe(Lmu6b3M6?2@g+S)m-`U5GGL#TpW?&AOiO(Q>jxqtR2V;((br5R|@%kMo-pKo30>^&c ztzDTv4p>%vz9|Ubi{( zECEG&yK(tn2xyb zb-yiQ!Mp~Hz`ZZ~>J(iPHt0u_kgxX@DbI2O>I2YD~oToos zdLrbZo70y#A9yvUB8R^-E=}n4BWY&jLpL3KE7nYgb*4ecbpFw#eanDLoXV3^2d`FJ z0f6r~J3m_ltD5=vBWH7Pf!oRm*o^2_2B9>UA2**}-JFY=X+M2>xkkEX)^*;qVaECI!~S#yv$`_4dz}6gJ&r-AMP8s(=rS z92%CG&uff76WHYtVKW(Q`cngSMu#uXw}=a(&WHV+t`Ptm2`BiF>T4&?vR17*sEwOUl*t@%s1}@k}gw)GRO>H4Ts`7GcC zMIwYZIQHu%Nr5PCBS(}yE&d*axFp)z32`yQ3<07m$KkUibgANMTqD}<%-(8V!j1edDUrY^)c3TcuJx0maKN0tgf2PUSRx3PR;hjh@PEo3 zg(Q=Fg$6a`nIXv*k5ckf^bsvlPL8axS>9;>Bu_S}5vv}8c}@{oTg45LG(M!wUWx+!>KVIKV8wSN>8K(NIt*i{=}m7|WBb4Ktu2rCp9Jq9kv$ zf%O@)8qsy!@Ynp*t7RUi4S?}>p>hP=)AV()q36{}7Jx3(&p?;fomt{IU_?uOv!z!r z0i>lUXhNZ(kEZ?`6A1$|TJig|P?}Cq2xa)yiO%R-MAykT$PjLAon%m2)}QRmga!@D z2SBvPO_2yg4KcFD{(Z!(h`hTH%%E`g*f1{o2~pQT{lDVc6&qHLWw3avI1;jYAvHB` zfFnfZ8AnSpYky^{1W-oIlp5sNJs_fAQKbq9lwy{V#AcWvje45AzOid*#d?A$P0hqA zZMok@M&o{an$$WXXbwT)U*~EBe|CvfaMeE~AgMM5qKEJ|2-9ch+utT2)mE_Ow$>^z zU8^rDpGc{xhVTwFC7oiU#^k;B8qtjhMHrp+mx&Thd{npnj>RI|%5;kfu&mCtD+(tw z1%JAz(Bk(R{GByBb6JqKkN&g+8|6IY8;BtmcP2;b@EF5<-XUl z5c&*AOOYlVxZ4Q{oxLGAZ%8ra z9k*8yN5hZB_~6NlLNAYwyv{{**FhCVB<^|$;Xp}`ilDC9LeOY%j>Ux#5_;ub&5bVg zyS-IEWhyUI)f-l(aM}FO@>qC;{PibzuDi{ORA?QiF3n{3CypX|e;q?a`YXo)dZbvd z;_v}mQ@<$KNAe4faQ4T&Veo$b`l|F>%L~nurAQpy2#0PK~$^49gqyVioPc zBP`FDd-}?F!!bLfB)X0wa%QwIcaC!w{PaPK)-H0)DTOmmFIeo6r`!xUjOC6LXgfIFXfbWW0EkCaC+Y3>81Dux5+zAnuzWcltdxua2hOrw|5$m@j^6Z2!9^>h>LB0t(H0&lxT9mhsVtl>Oyl?fu#F zRtjD-BR5JuPMLds;Vx=gg0{3e5mDt-(+p}hTmGTXdCMIp=b)>AP+wTtlGE!z^BLC% z664R^WQ9ohegzWZ`dxy2XvU|AXPHljXr|&X&gPPfjntOgA;)BL7l&kE_Fq1qd^5dFI`%c=T4%HAmr4T;14oMz7wT^$+|9zt`C%b^SP_> z0`mXtEDAbvP>(|J^?ojzxrxp^w+I#TJzViSY8(GedoE% z$U%5XzbNzhbt5;InHh6fjTEoJwT$B`N7B|3vfN5WH{#7MKdyqI#+iL3)NbR|>K_3f zw$ooVuL{A0&j2k}mD{|8rP^z`WvovdrNy%WD3+3=G=)!x9ojkap? zHpMtu2J;mM#`lK-OL>gSix_(<10G zS-o5u6W9?g)lA!dV+|K@AD}}$sxBNJxU#9r5lCaeY0xY;8-1FF$Z9r&gXJ|y^OjdO zY~aI%YEKrCc}Ar#*yD0)&Bgr`ojBxhlUltK`6}ZcGdi&dTwC8(v_|Yp1G))9vx9-& zv@?cm&MC|I)DFpb6@dU8pjV8N)8XIri0io`w0$H#RT~o=NRVA^MI|GP8Vb+`VQpmHin#GSFnU; zIC>YqcX?nKaQE3G_CdQpepHj4agPio!EScMa|BuHhmr71b&dk_pi`Dzy!{o{X4sMs zx$R!%sx}GC z>x4{(pdUdrb|4;cFi*T?Qp^Ch?J;$!C zVgX4DQMiK!>+PSATJd@jj-5Ac6gf^X#|5qbet4+9cFU4hw&)BBGTorxuJ{S34>up0 z!m~p7BG0lO?>SyY%o(BVjbtW8gpimR7EqKmIq9ePj+lWZdEuS;?a^n!!tA45=oh}e zl|#XJfYBp8IGqBoZi+KFKy*BU07-!Tq>hLD)o$*Kd2kR!6mGO-BU3Vp#Q*PX80WKK zOR)#(!aHGcWDkUYn3eCQ#Qu5aa%7<6vxWcbY@~JBB`<wqUYSexQlIRe<4s$E>+ckq;7!9v?$Fo445hP|-X*KbJLXWh7%mT~ zL&<^oKmIC^$tA3CX$I2bfiNF3@q9o=_N7GF(&07*q)k)76KB^)<_cI9l->A(Md%l! zgyR1y^+1BVut+46Bdt9_J~!|Mx(5Aw%&r6EzMZ-j39x$(>3}BC4nurVzp=7Q7<%&r z&l@tSiqQz?ll0&r^!sjU>Bw}%X$}B=Ux=)-{@>*$-H5E>f^RsnMk7lIoLLVIk;M&Z zJgTIG{%Lj_Y4I;Glo1%+V*S4FJ!(@*yns7K+wzDrE5n|R9;2RaOG|O{7J35@dv9TV zGSFHLjb`t_BN74!b{q~R{oCdS19%TZH3xAu&tm+8UjATnA7NA7M-@H(BZxkQ8%=%S z{T3DxdsC$^o=)HsI1mg)G~mUF78;oMVY-ZC%Yt5(DH#`|Mlfc#@0!eWq4$@+5N6m{ zyaESkP}Pb5DbT?ZT8>pLeVcSM`ua>R4e~<}I^BI$L=ZZ~-tW*(gKWraMDtj$)6Pd4 zqHlV1_6Eaz|HQFnu5BH?1B*N6m4fQv^$-#n;RbElM{Nf;@9f4fBAcS2mb2kuVPQKIIIN1l4d*V-js_c; ziXi%o>)rTUTdstVz7AUTD$-(;MVBD@qb=uKq=NH>QW+R$Rn$)ub%mnst2o7zSAIjt ziPugkr;$^9&}t8j2u+VBpLaO}HK>bHeea*9^(ky z>J+gAy>Q@Z!LyVRVQBp^HD-L$W(_f?fB_R%6<|Pg$3H zk9E=FPe^J}MgIMY3ewf{HN9e0%g?Bmo6O?m^!b(2Oml^~dBWDAqV8Aa8pC8NQ{~^! z^K}hX#;Z#EH(wsU6U>&|0ZyrK*At>m=|cWpomD3M;#xfHU(~q)LT0@ChQqi~Bk%Ay zG;{NkvX7rA{(l;gWn4%7az4Z)>`4MAUjpYadw?#3?9KmE_iEoGRwu=bP5;v=o0x$; zhTY+NcRPcA2i@6ObHqQ- zOPQ){A#%yaqVZEF71>CB*@wxScsy zmp`bfdg?2yg@ z7q)CG1#!Psjc7bsR@^i>_h~+CaSr``4ay#A=rgJktaEnEm4VfXugQ$2+rOnUFJA5& z4L-O*6K>J#IJFYYWtxkGvi!*i-Q5vd-K{N-vPGEGyf4hv9Xmp2*AKt$d6E~S6}2|i zyoj999b7C zn|pX&$@K~5Own>lm#%BirrXyQ=`G0HFD^GFN44M9Iif)`CAx;Mx^m9prLj5yC}f&j*q3+b=xsJJ?ay-a+-B4IW^A)=F8SmN(;3 zsPfBk?Azg0g}dct{#K3MigR+Upuys$rbxU9@2a(>dGFdZb-t13&~0U{sM?7??LvVm zdg7upg`L2Si{aGT&lDoOi2u2w%;f&Ww9qbHw~FGs#sPY!qs#QfImU8(WPQqE16D40 zH4u|(j#|YFwmWaHU&FsaqPH)%Yg~1+o_J-!3vWxT^*3`0C7u`58RnXu*xOf4ZncmK zD+xR?zg%fq(XYsp+*J4YsZ|<-a~8reYtkfVZ*LtLJ~d;Kd}l*grmuiSwBejY&6{3@ zzpYb}c4s=voB^dIrkOEL9TP{l?;Kja#dTlzF3RKz=X z;zCM}`BiT?Ph)=H4zt1ce09e2{m*{A`u$z^$L#MyrPt79F-ypF3je$UMj4&CA=M`5@!c)a^DLmt;^3S zD0)$2Mg5}A`+%F?#!dBQPVFhJGEq9B<5xJZ9wWYJ*Se;`_xm>1gCiwdv(7o^EQV-2 z$q;(_;IdM7jljU69iE7I@UHv$^c00N|)7#toU_zHH z{dYA{vAw^rO-Jxi-*eAYlbT~Kc9y$yq|ZLYW?{YNskaZ;)?J@h{Jluvegl$4_KyYt zi-hDauwk!C^*7NVmzl-|8W0qafv{4u%IkcQ^E1Jw$}fm0216J0#cgn+|M>b`p@bAb z>#UURc13BvbOwl$il)*@tU&CbLG^G3k`X=*+fMFJZ>E3!&98c>or{yE46CK5^8 zE@8;_u>@^1Y*8WoCZ{ zMAzI3F(mNw# zFRi~w9QqwLQ+U1S=_!FUe^Qk2FT}QLI4g)bG$8W*0fJ>ktMl)wQ4d7Nm`A;0 zk9LZEe>&m^gTKaYPZ_`bu#|y(JZwE}A+-hD_zfR0I zjR%GNR2xDpE%B$SmNlTRd+R>%loV-v3+vcC+_|u9+I+~&)e<7AxQBMuC7W7TSoymO zq7SedStszm>C+82WUGrw__eh7r$)E^)@P3Id8%JWT>r$bxtA?MYC6$w?|9XjHA=qc=@Z~u~T$l#n8)3m#CHdR7Oec zsR>^5Q-VYp#&?T>=gV=)tI1+eRHx)KH`4jH(5t$C8>ZT1^$h(zHDh-o(=&DU%ClK9 zB&Q4O7%i?074z=;;g(dY*FmCq;pONzu5IeFmn!3wH}92eVS)ncuqtuh`Gt^q@h$|?Kb6W*F4>}iYGP97hKT>L+mLT@1?r=mB3kkl;Qs)tA>uC z?qZRQRg-rwY9IX3cG-)-MoQ7b)*SD9reTv0zJ%FK@Y1hfeK@kAFVY44E*AMKJ|=Ua zb(M)+yFCzS{(0YXyXlclRqKcpV@#4{MLXuIesys3zAB4W=iKn0e35o-N3~H7axbunF1Yq<v+}Z24E8ltC@^qZrOxMM&`huc}=U@gIP;EVk6Q&-EX5f^K_7O}mO0-NIuE z7|tvh!T2A#HtrCdn1CyR92*R`0Gx$YDVWFX6FL9Cho2V-4m-ZQ{_~4ojlbDs?YKV2 Il6K~Q0qZx3`2YX_ literal 0 HcmV?d00001 diff --git a/02_numpy_matplotlib_pandas/images/artists_tree.png b/02_numpy_matplotlib_pandas/images/artists_tree.png new file mode 100644 index 0000000000000000000000000000000000000000..56a23c17839936eb775a94fa1d48371fd0a04974 GIT binary patch literal 7310 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 literal 0 HcmV?d00001 diff --git a/02_numpy_matplotlib_pandas/images/three_layers.png b/02_numpy_matplotlib_pandas/images/three_layers.png new file mode 100644 index 0000000000000000000000000000000000000000..d126810a016c6256a2d84d69d9655a479201fd8f GIT binary patch literal 55314 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 literal 0 HcmV?d00001 diff --git "a/Notebooks/\345\235\207\345\200\274\344\272\244\345\217\211.ipynb" "b/Notebooks/\345\235\207\345\200\274\344\272\244\345\217\211.ipynb" index eadef3a..357374a 100644 --- "a/Notebooks/\345\235\207\345\200\274\344\272\244\345\217\211.ipynb" +++ "b/Notebooks/\345\235\207\345\200\274\344\272\244\345\217\211.ipynb" @@ -15,7 +15,7 @@ }, "outputs": [], "source": [ - "%pylab inline\n", + "%matplotlib inline\n", "\n", "# Pandas v0.16 之前,使用下面這個\n", "# import pandas.io.data as web\n", @@ -39,7 +39,7 @@ "outputs": [], "source": [ "# 讀取從 1970/1/1 之後的股價資訊\n", - "df=web.DataReader(\"FSLR\", 'yahoo', datetime(2012,1,1))" + "df=web.DataReader(\"TSLA\", 'yahoo', datetime(2016,8,1))" ] }, { @@ -51,8 +51,8 @@ "outputs": [], "source": [ "# 計算均線\n", - "df['20d'] = np.round(pd.rolling_mean(df['Close'], window=20), 2)\n", - "df['60d'] = np.round(pd.rolling_mean(df['Close'], window=60), 2)\n", + "df['20d'] = np.round(pd.Series.rolling(df['Close'], window=20).mean(), 2)\n", + "df['60d'] = np.round(pd.Series.rolling(df['Close'], window=60).mean(), 2)\n", "\n", "# 判斷均線向上或向下\n", "df['20d_diff'] = np.round(df['20d'].diff(), 2)\n", @@ -70,6 +70,19 @@ "df[['Close','20d','60d']].plot(grid=True, figsize=(10,8))" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Donchian Channel\n", + "df['20d_high'] = np.round(pd.Series.rolling(df['Close'], window=20).max(), 2)\n", + "df['10d_low'] = np.round(pd.Series.rolling(df['Close'], window=10).min(), 2)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -95,12 +108,49 @@ "outputs": [], "source": [ "# 第一個策略\n", - "#df['signal'] = np.where(df['20d']-df['60d'] > 0, 1.0, 0.0)\n", + "df['positions'] = np.where(df['20d']-df['60d'] > 0, 1.0, 0.0)\n", "\n", + "df['signals'] = df['positions'].diff()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ "# 第二個策略\n", - "df['signal'] = np.where(np.logical_and(df['20d']-df['60d'] > 0, df['20d_diff'] > 0), 1.0, 0.0)\n", + "df['positions'] = np.where(np.logical_and(df['20d']-df['60d'] > 0, df['20d_diff'] > 0), 1.0, 0.0)\n", "\n", - "df['positions'] = df['signal'].diff()" + "df['signals'] = df['positions'].diff()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# 第三個策略\n", + "has_position = False\n", + "df['signals'] = zeros(size(df['Close']))\n", + "for t in range(2, df['signals'].size):\n", + " if df['Close'][t] > df['20d_high'][t-1]:\n", + " if not has_position:\n", + " #df['signals'][t] = 1 # 這樣指定會有警告訊息\n", + " df.loc[df.index[t], 'signals'] = 1.0\n", + " has_position = True\n", + " elif df['Close'][t] < df['10d_low'][t-1]:\n", + " if has_position:\n", + " #df['signals'][t] = -1\n", + " df.loc[df.index[t], 'signals'] = -1.0\n", + " has_position = False\n", + "\n", + "df['positions'] = df['signals'].cumsum()" ] }, { @@ -118,15 +168,15 @@ "# Plot the AAPL closing price overlaid with the moving averages\n", "df['Close'].plot(ax=ax1, color='gray', lw=1., figsize=(10,8))\n", "df[['20d', '60d']].plot(ax=ax1, lw=2., grid=True)\n", + "df[['20d_high', '10d_low']].plot(ax=ax1, lw=2., grid=True)\n", "\n", "# Plot the \"buy\" trades against AAPL\n", - "ax1.plot(df.ix[df.positions == 1.0].index,df['20d'][df.positions == 1.0],'^', markersize=10, color='r')\n", + "#ax1.plot(df.ix[df.signals == 1.0].index,df['20d'][df.signals == 1.0],'^', markersize=10, color='r')\n", + "ax1.plot(df.ix[df.signals == 1.0].index,df['Close'][df.signals == 1.0],'^', markersize=10, color='r')\n", "\n", "# Plot the \"sell\" trades against AAPL\n", - "ax1.plot(df.ix[df.positions == -1.0].index, df['20d'][df.positions == -1.0], 'v', markersize=10, color='k')\n", - "\n", - "# 如果不是在 IPython Notebook 則需要下面這一行來顯示圖形\n", - "#fig.show()" + "#ax1.plot(df.ix[df.signals == -1.0].index, df['20d'][df.signals == -1.0], 'v', markersize=10, color='k')\n", + "ax1.plot(df.ix[df.signals == -1.0].index, df['Close'][df.signals == -1.0], 'v', markersize=10, color='k')" ] }, { @@ -151,13 +201,13 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ "#假設無風險利率為 4%\n", "#假設一年有252個交易日\n", - "excessRet = (dailyRet - 0.04/252)[df['signal']==1]\n", + "excessRet = (dailyRet - 0.04/252)[df['positions']==1.0]\n", "\n", "sharpeRatio = sqrt(252.0)*mean(excessRet)/std(excessRet)" ] @@ -202,11 +252,11 @@ " drawdownduration[t] = 0\n", " else:\n", " # 從日期來計算 MaxDDD 的天數\n", - " # drawdownduration[t] = drawdownduration[t-1] + (cumRet.index[t]-cumRet.index[t-1]).days\n", - " drawdownduration[t] = drawdownduration[t-1] + 1\n", + " drawdownduration[t] = drawdownduration[t-1] + (cumRet.index[t]-cumRet.index[t-1]).days\n", + " #drawdownduration[t] = drawdownduration[t-1] + 1\n", " maxDD = max(drawdown)\n", " maxDDD = max(drawdownduration)\n", - " Series(drawdownduration).plot()\n", + " Series(drawdownduration, index=cumRet.index).plot()\n", " return maxDD, maxDDD" ] }, diff --git "a/Notebooks/\345\246\202\344\275\225\345\276\236\347\266\262\350\267\257\350\256\200\345\217\226\350\202\241\345\203\271\350\263\207\346\226\231\344\270\246\347\271\252\350\243\275\345\234\226\345\275\242.ipynb" "b/Notebooks/\345\246\202\344\275\225\345\276\236\347\266\262\350\267\257\350\256\200\345\217\226\350\202\241\345\203\271\350\263\207\346\226\231\344\270\246\347\271\252\350\243\275\345\234\226\345\275\242.ipynb" index 7cb2772..476e6da 100644 --- "a/Notebooks/\345\246\202\344\275\225\345\276\236\347\266\262\350\267\257\350\256\200\345\217\226\350\202\241\345\203\271\350\263\207\346\226\231\344\270\246\347\271\252\350\243\275\345\234\226\345\275\242.ipynb" +++ "b/Notebooks/\345\246\202\344\275\225\345\276\236\347\266\262\350\267\257\350\256\200\345\217\226\350\202\241\345\203\271\350\263\207\346\226\231\344\270\246\347\271\252\350\243\275\345\234\226\345\275\242.ipynb" @@ -218,6 +218,7 @@ } ], "metadata": { + "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [conda root]", "language": "python",