跳至主要内容

16 篇文章 含有標籤「Python」

檢視所有標籤

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

· 閱讀時間約 5 分鐘

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

Excel 幾乎是所有職場工作者最常使用的 Office 軟體工具,小至同事間訂便當、飲料,大到進出貨訂單管理,應收應付賬款的財務報表等都有它的身影。在一般工作上,你可能常常需要在不同表單中複製貼上許多的欄位,或是從幾百個列表中挑選幾列依照某些條件來更新試算表內容等。事實上,這些工作很花時間,但實際上卻沒什麼技術含量。你是否曾想過但使用程式語言來加快你的工作效率,減輕瑣碎的重複性無聊工作但又不知道如何開始?

別擔心,這邊我們就要使用 Python 和 Openyxl 這個模組,讓讀者可以輕鬆使用 Python 來處理 Excel 試算表,解決工作上的繁瑣單調工作!

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

Excel 試算表名詞介紹

在正式開始使用 Python 程式來操作 Excel 試算表前我們先來了解 Excel 常見名詞。首先來談一下基本定義,一般而言 Excel 試算表文件稱作活頁簿(workbook),而活頁簿我們會存在 .xlsx 的副檔名檔案中(若是比較舊版的 Excel 有可能會有其他 .xls 等檔名)。在每個活頁簿可以有多個工作表(worksheet),一般就是我們工作填寫資料的區域,多個資料表使用 tab 來進行區隔,正在使用的資料表(active worksheet)稱為使用中工作表。每個工作表中直的是欄(column)從和橫的是列(row)。在指定的欄和列的區域是儲存格(cell),也就是我們輸入資料的地方。一格格儲存格的網格和內含的資料就組成一份工作表。

環境設定

在開始撰寫程式之前,我們先準備好開發環境(根據你的作業系統安裝 Anaconda Python3virtualenv 模組openyxl 模組),關於開發環境設定可以參考:Python Web Flask 實戰開發教學 - 簡介與環境建置,Windows 讀者開發環境可以參考 如何在 Windows 打造 Python 開發環境設定基礎入門教學

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

這邊我們使用 MacOS 環境搭配 jupyter notebook 做範例教學:

# 創建並移動到資料夾
$ mkdir pyexcel-example
$ cd pyexcel-example
$ jupyter notebook

開啟 jupyter notebook 後新增一個 Python3 Notebook

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

首先先安裝 openyxl 套件(在 jupyter 使用 $ !pip install <your-package> 安裝套件):

使用 shift + enter 可以執行指令

!pip install openpyxl

記得要先安裝 openpyxl 模組,若是沒安裝模組則會出現 ModuleNotFoundError: No module named 'openpyxl' 錯誤訊息。

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

讀取 Excel 檔案

  1. 使用 Openpyxl 開啟 Excel 檔案(可以從這邊下載範例 Excel 資料檔案),下載後檔名改為 sample.xlsx,並放到和 jupyter Notebook 同樣位置的資料夾下:

    from openpyxl import load_workbook

    wb = load_workbook('sample.xlsx')
    print(wb.sheetnames)

    執行後可以讀取活頁簿物件(類似讀取檔案)並印出這個範例檔案的工作表名稱:

    ['Sheet1']
  2. 從工作表中取得儲存格(取得 A1 儲存格資料)

    ws['A1'].value
  3. 從工作表中取得欄和列

    列出每一欄的值

    for row in ws.rows:
    for cell in row:
    print(cell.value)

    列出每一列的值

    for column in ws.columns:
    for cell in column:
    print(cell.value)

寫入 Excel 檔案

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

  1. 創建並儲存 Excel 檔案

    from openpyxl import Workbook

    # 創建一個空白活頁簿物件
    wb = Workbook()
  2. 建立工作表

    # 選取正在工作中的表單
    ws = wb.active
  3. 將值寫入儲存格內

    # 指定值給 A1 儲存格
    ws['A1'] = '我是儲存格'

    # 向下新增一列並連續插入值
    ws.append([1, 2, 3])
    ws.append([3, 2, 1])
  4. 儲存檔案

    # 儲存成 create_sample.xlsx 檔案
    wb.save('create_sample.xlsx')

Python 自動化程式設計:如何使用 Python 程式操作 Excel 試算表

總結

以上簡單介紹如何使用 Python 程式操作 Excel 試算表,透過 Python 可以讀取和寫入 Excel 檔案,相信只要能活用就能夠減少一般例行性的繁瑣工作。若需要更多 openpyxl 操作方式可以參考官方文件教學,我們下回見囉!

參考文件

  1. openpyxl - A Python library to read/write Excel 2010 xlsx/xlsm files

(image via matplotlib

如何在 Windows 打造 Python Web 開發環境入門教學 Part2

· 閱讀時間約 1 分鐘

如何在 Windows 打造 Python Web 開發環境

所謂工欲善其事,必先利其器。我們開發程式之前我們最重要的就是要設定好開發環境,接下來我們將帶領讀者體驗如何在 Windows 打造 Python Web 開發環境。

撰寫第一個 Python Django 程式

  1. 創建虛擬開發環境:conda create -n <自定義虛擬環境名稱> python=3.5
  2. 觀看已建立的虛擬環境:conda info -e
  3. 進入虛擬環境:activate <自定義虛擬環境名稱>
  4. 安裝套件:pip install django
  5. 觀看已安裝套件:pip list
  6. 建立第一個 django 專案:django-admin startproject my_first_app
  7. 啟動伺服器:python manage.py runserver
  8. 到瀏覽器觀看成果!http://localhost:8000http://127.0.0.1:8000

其他常用指令

  1. 離開虛擬環境:deactivate
  2. 移除虛擬環境:conda remove <自定義虛擬環境名稱> -n --all
  3. pip uninstall 套件名稱

影片教學

如何在 Windows 打造 Python Web 開發環境入門教學 Part1

· 閱讀時間約 2 分鐘

如何在 Windows 打造 Python Web 開發環境

所謂工欲善其事,必先利其器。我們開發程式之前我們最重要的就是要設定好開發環境,接下來我們將帶領讀者體驗如何在 Windows 打造 Python Web 開發環境。

安裝軟體步驟

  1. 下載安裝 google chrome 瀏覽器
  2. 下載安裝 Visual Studio CodeSublime text 文字編輯器
  3. 下載安裝 cmder terminal 終端機程式 (請下載含 git 的 full 完整版本)
  4. 下載安裝 anaconda for windows (請依你的作業系統位元 32/64 下載對應程式,記得安裝時要勾選加入環境變數)
  5. 在終端機輸入 (若正確顯示版本即為安裝成功):python -V
  6. 輸入 python 可進入互動式對話環境,可以執行 python 程式

撰寫第一個 Python 程式

  1. 打開 Visual Studio Code 或 Sublime text 並建立一個 hello.py 檔案:
print('hello python')
  1. 到 cmder 終端機移動到 hello.py 資料夾下輸入 python hello.py

就可以看到你撰寫的第一個 Python 程式 hello python 啦!

影片教學

如何在 Windows 打造 Python 開發環境設定基礎入門教學

· 閱讀時間約 13 分鐘

如何設定開發環境應該是每個初學程式設計者的痛(即便是老手有時也會覺得苦惱),尤其當你需要在終端機(terminal)輸入指令(command)來操控你的指令時(好吧,若你完全只走圖形化介面,習慣 GUI 操作就另當別論,但若你有志於往程式設計領域發展,建議還是熟悉一下指令碼)。

要在 LinuxMac OS 這種屬於類 Unix 系統(指各種 Unix 的衍生系統,而 Unix 指的是一種電腦作業系統,具有多工、多使用者的特色,是許多作業系統的父親)上打造 Python 開發環境相對容易,但當你使用 Windows 作業系統並希望在終端機下指令操作或開發應用程式時,往往受限於環境而產生許多困難和誤踩地雷。因此,接下來本文將教大家如何在 Windows 打造屬於自己的 Python 開發環境(包含一般 Winodows 安裝和使用虛擬機在 Windows 環境下建立 Linux/Ubuntu 作業系統,開發 Python 程式一般建議使用 Linux/Ubuntu 環境避免環境設定除錯困擾)!

開始建置 Python 開發環境

所謂工欲善其事,必先利其器,在開始之前我們必須先建置相關的開發環境,讓自己從麻瓜(不會寫程式的人)變成擁有程式魔力的魔法師。以下介紹我們在接下來開發 Python Web 應用程式所需要安裝的開發環境工具(強烈建議使用 Virtual Box 虛擬機搭配 Linux/Ubuntu 環境,若你真的很想使用 Windows 環境就繼續往下看吧!)。

  1. Microsoft VSCode 編輯器 Microsoft VSCode 是 Microsoft 推出的編輯器(非整合開發環境 IDE),夾帶著 Microsoft 過去打造 Visual studio 整合開發環境的豐富經驗,相比 Sublime Text 和其他編輯器,VSCode 的優勢在於開源且活躍的開發社群、內建 debugger 框架、原生 Git 整合、套件整合容易等特性。綜合以上幾點,對於初學者來說 VSCode 是一個蠻適合入門的開發環境。它的安裝方式也十分簡易,在官網下載後按照指示安裝完成即可,下載完成後可以打開看看。

    title: 如何在 Windows 打造 Python 開發環境設定

    我們可以點選左邊 icon 欄的第五個(長得像正方形拼圖),安裝 Python 語法和格式檢查的相關套件幫助除錯(搜尋 Python),選擇 Python 並點選 install 安裝:

    title: 如何在 Windows 打造 Python 開發環境設定

    你也可以於檔案(file)-> 開啟(open)打開你在電腦中已經準備好的專案資料夾,同時也可以在資料夾中新增檔案,我們之後的程式也會希望在建立好的專案資料夾中進行開發。這邊我們建立一個 hello.py 的檔案並印出 hello 訊息。

    print('hello python')
  2. 終端機環境(iTterm/內建 terminal) terminal(終端機)是我們下指令的地方,許多時候我們進行程式開發時不會使用 GUI 圖形化介面而是使用下指令方式請電腦做相對應的行為(記得寫程式就是下指令請電腦做事情!)。在 Linux 和 Mac 裡面都有內建的 terminal 的應用程式,以下為 MacOS 的 iTerm2 終端機下指令示意圖(iTerm2 中 $ 為提示字元,不用輸入):

    title: 如何在 Windows 打造 Python 開發環境設定

    使用 Windows 讀者可以使用 Cmder 這個軟體當做終端機環境。

    title: 如何在 Windows 打造 Python 開發環境設定

    比起 Winodws 內建的命令列 CMD,cmder 更貼近 Unix 的命令列指令碼:

    title: 如何在 Windows 打造 Python 開發環境設定

    首先到 Cmder 官網先安裝 Cmder Full 版本(含 git),安裝完成後解壓縮資料夾到桌面,執行裡面的 cmder.exe 檔案即可。

    title: 如何在 Windows 打造 Python 開發環境設定

    Cmder 預設是 λ,如果不習慣可以改成 Mac / Linux 環境下的 $,具體流程請參考這份文件

    title: 如何在 Windows 打造 Python 開發環境設定

    對於有志於從事程式開發相關工作的讀者建議可以多熟悉指令碼的輸入,更多指令碼可以參考鳥哥撰寫的 Linux 基本指令介紹Linux 學習資源

    以下是常用指令
    # 移動到桌面
    cd \Users\XXXX\Desktop
    # 列出資料夾下檔案
    ls
    # 刪除檔案
    rm 檔名
    # 複製檔案
    cp 檔名
  3. Git 版本控制系統/註冊 GitHub 帳戶 Git 是一種分散式版本控制系統,可以讓我們可以更方便地管理我們的程式碼。在網路上有非常多優秀的 Git 教學文件(連猴子都能懂的Git入門指南寫給大家的 Git 教學初心者 Git 上手攻略)。安裝 Git 方式是到官網下載軟體,依照指示安裝(若您使用 Cmder 的完整安裝 Download Full 的版本就不用安裝 git,因為已經幫你安裝好了)。

    title: 如何在 Windows 打造 Python 開發環境設定

    互動式語法學習:

    title: 如何在 Windows 打造 Python 開發環境設定

    在介紹完 git 之後我們來了解一下 GitHub。GitHub 是一個可以存放 git 程式碼專案的平台,透過 GitHub 我們可以接觸到最新的開放原始碼資訊,也可以將我們的程式碼開源出來。

    title: 如何在 Windows 打造 Python 開發環境設定

    從 GitHub 上複製程式碼

    # 複製一份到本地端
    $ git clone https://github.com/happycoderorg/python101.git
    # 移動到資料夾
    $ cd python101

    常見 Git 指令:

    # 初始化專案
    $ git init
    # 查看狀態
    $ git status
    # 檢查差異
    $ git diff
    # 將變更檔案放入暫存區
    $ git add index.py
    # 使用 commit -m 提交變更
    $ git -a -m 'init commit'
    # 查看歷史
    $ git log
    # 放棄已經 commit 的檔案重回暫存區
    $ git reset HEAD index.py
    # 放棄檔案變更
    $ git checkout index.py
  4. Anaconda Python3 版本 Anaconda 是一個 all-in-one 的 Python 開發環境,對於初學者來說是個十分合適的開發環境包。Anaconda 具備了幾項特點:

    • 便於安裝許多流行的科學、數學、工程、資料分析的 Python 模組
    • 免費並支援跨平台:Linux、Windows、Mac
    • 內建 Spyder 編輯器和 Jupyter Notebook 環境
    • 方便建立不同的虛擬開發環境

    安裝流程也十分簡單,進入 Anaconda 首頁,選擇對應作業系統(這邊使用 Windows)和是屬於 64 還是 32 位元: title: 如何在 Windows 打造 Python 開發環境設定

    Windows10 可以在系統看到位元資訊; title: 如何在 Windows 打造 Python 開發環境設定

    Windows7 可以在控制台->系統與安全->系統觀看作業系統位元資訊: title: 如何在 Windows 打造 Python 開發環境設定

    選擇對應 Python 版本下載(這裡選擇 Python3 以上版本),我們使用 Graphical Installer(圖像介面安裝方式),接著在下載完成時按照預設的安裝方式完成安裝; title: 如何在 Windows 打造 Python 開發環境設定

    記得安裝時要注意建議在安裝 anaconda 時勾選把環境變數加入(path environment variable),這樣在使用 cmder 時使用 conda 相關指令才不會出現錯誤,若一開始沒有勾選的話建議解除安裝後再重新安裝 anaconda 勾選加入環境變數。

    title: 如何在 Windows 打造 Python 開發環境設定

    若是完整安裝成功,可以打開 Cmder 終端機輸入,若是顯示 Python 3.6.0 :: Anaconda 4.3.0 (x86_64) 版本號即安裝成功(若沒成功可能要檢查一下是不是環境變數路徑的問題):

    $ python -V
    Python 3.6.0 :: Anaconda 4.3.0 (x86_64)

    接著要建立我們專案虛擬環境,這樣在安裝操作套件時比較不容易被污染到 root 全域的環境(因為你可能會有很多專案,專案使用的套件不盡相同,正式上線時只要把相關套件資訊透過 pip freeze > requirements.txt 存起來,然後在正式上線的伺服器安裝 pip install -r requirements.txt 即可),啟動後會出現(套件名稱)的提示字元:

    顯示目前虛擬環境列表
    conda info -e
    創建虛擬環境
    conda create -n 套件名稱 python=3.6
    進入虛擬環境(若是非 Windows cmder 環境加 source 於開頭) ,成功後提示字元變成:(套件名稱)$
    activate 虛擬環境名稱
    離開虛擬環境(若是非 Windows cmder 環境加 source 於開頭)
    deactivate

建立虛擬環境(virtual environment)

接著我們正式來建立一個 Python 的專案,打開終端機移動到桌面,建立專案資料夾(在輸入指令時可以使用 tab 自動補完指令)

# 移動到桌面
cd \Users\XXXX\Desktop
# 建立資料夾
mkdir python_examples
# 移動到資料夾
cd python_examples

建立獨立虛擬環境,並進入虛擬環境:

# 創立虛擬環境
conda create -n python_examples_venv python
# 啟動虛擬環境
activate python_examples_venv

成功進入虛擬環境後(會出現小括號 python_examples_venv)代表已經進入虛擬環境,即可以在裡面執行 Python 程式並安裝相關套件於該虛擬環境下:

# 安裝 django web 框架套件
pip install django
# 執行 python 檔案
python hello.py

事實上,在 Python3 中還有另外兩種建立虛擬開發環境的方式,包括使用 Python 內建工具:

# 使用 Python3 內建工具建立名為 example_venv 的虛擬開發環境
python -m venv example_venv

使用 virtualenv,和 anaconda 不同的是 virtualenv 會在建立虛擬環境的專案資料夾下建立一個資料夾裡面放虛擬環境的東西:

# 先安裝 virtualenv
pip install virtualenv
# 使用 virtualenv 產生一個名為 example_venv 的
virtualenv example_venv
# 移動到 example_venv 的外面資料夾,執行進入虛擬環境
example_venv\Scripts\activate
# 安裝 django web 框架套件到虛擬環境中(只會安裝在該虛擬環境中)
pip install django

整合在一起:在 Windows 撰寫你的第一個 Python 程式

確認安裝好以下工具後,我們就可以開始撰寫你的第一個 Python 程式

  1. 安裝 Microsoft VSCode
  2. 安裝 Cmder
  3. 安裝 Anaconda(記得勾選加入環境變數)
  4. 安裝 virtualenv (在終端機使用:pip install virtualenv 安裝)
  5. 在桌面創建一個 python_example 資料夾,打開 Microsoft VSCode 後開啟該專案資料夾,創建一個 hello.py 的檔案並在裡面打上 print('hello python!!')
  6. 打開 cmder 終端機 cd 移動到 hello.py 所在資料夾
  7. 執行 python hello.py,恭喜你完成第一個 Python 程式!

在 Windows 上安裝 Linux/Ubuntu

  1. 安裝 VirtualBox 對應版本虛擬機(這邊安裝 Windows 版本,若你是 Mac 想嘗試 Linux 也可以安裝 Mac 版本),下載完按照步驟安裝完成

    title: 如何在 Windows 打造 Python 開發環境設定

  2. 官網下載 Linux/Ubuntu 光碟映像檔案,請根據電腦位元架構選擇最新桌面穩定版本 16.04 LTS(for windows)

    title: 如何在 Windows 打造 Python 開發環境設定

  3. 建立 Linux Ubuntu 虛擬機,可以參考這篇 VirtualBox 虛擬機器安裝 Ubuntu 設定教學,設定一下名稱、作業系統類型和版本,欲分配給虛擬的記憶體大小(建議調整為大約實體記憶體的 1/3,舉例來說你有 30G 記憶體,可以分配 10G 給虛擬機)。接著選擇立即建立虛擬硬碟、VDI (VirtualBox 磁碟映像)、動態配置硬碟大小不會造成浪費(虛擬硬碟容量建議 30G 以上)。

    title: 如何在 Windows 打造 Python 開發環境設定

  4. 選擇建立好的虛擬機並選設定值按鈕,選擇存放位置選項,控制器中選擇虛擬 CD/DVD 檔案選擇剛剛從官網下載下來的檔案,確定後接著選擇虛擬機並啟動,接下來選擇安裝 Linux/Ubuntu,選擇立即安裝和預設值,需要一段時間安裝和設定(中間會有語言相關的選擇和密碼設定)

    title: 如何在 Windows 打造 Python 開發環境設定

  5. 啟動使用 Linux/Ubuntu,按照上面教學安裝 Microsoft VSCode 編輯器,安裝 Anaconda,建立第一個 Python 檔案、打開終端機(termical)安裝 ,執行 Python 程式

    title: 如何在 Windows 打造 Python 開發環境設定

網路上也有許多相關參考教學文章:VirtualBox 5.2安裝Ubuntu 16.04 相關教學VirtualBox 虛擬機器安裝 Ubuntu 設定教學

若是螢幕太小可以在上排選單中選擇:裝置->插入 Guest Additions CD 映像...->執行->重開虛擬機->可以調整大小

整合在一起:用 Linux 撰寫你的第一個 Python 程式

確認安裝好以下工具後,我們就可以開始撰寫你的第一個 Python 程式

  1. 進入虛擬機的 Linux/Ubuntu
  2. 安裝 Microsoft VSCode
  3. 安裝 Anaconda(記得勾選加入環境變數)
  4. 安裝 virtualenv (在終端機使用:pip install virtualenv 安裝)
  5. 在桌面創建一個 python_example 資料夾,打開 Microsoft VSCode 後開啟該專案資料夾,創建一個 hello.py 的檔案並在裡面打上 print('hello python!!')
  6. 打開 terminal 終端機 cd 移動到 hello.py 所在資料夾
  7. 執行 python hello.py,恭喜你完成第一個 Python 程式!

總結

如何設定開發環境應該是每個初學程式設計者的痛(強烈建議使用 Virtual Box 虛擬機搭配 Linux/Ubuntu 環境),以上介紹了如何在 Windows 打造 Python 開發環境設定,請讀者務必照著自己的電腦作業系統環境安裝一次,當然若你有志於往程式設計領域發展,也要熟悉一下指令碼操作。

參考文件

  1. VirtualBox 5.2安裝Ubuntu 16.04
  2. Create virtual environments for python with conda
  3. conda vs. pip vs. virtualenv
  4. Anacodna之conda VS Virtualenv VS Python 3 venv 对比使用教程,创建虚拟环境
  5. 命令列指令碼查詢

(image via githubusercontentwebsiteoptimizationytimgytimgostechnix

用 Python 自學資料科學與機器學習入門實戰:Scikit Learn 基礎入門

· 閱讀時間約 17 分鐘

 如何使用 Python 學習機器學習(Machine Learning)

本系列文章將透過 Python 及其資料科學與機器學習生態系(Numpy、Scipy、Pandas、scikit-learn、Statsmodels、Matplotlib、Scrapy、Keras、TensorFlow 等)來系統性介紹資料科學與機器學習相關的知識。在這個單元中我們將介紹 scikit-learn 這個機器學習和資料分析神兵利器和基本的機器學習工作流程。接下來我們的範例將會使用 Ananconda、Python3 和 Jupyter Notebook 開發環境進行,若還沒安裝環境的讀者記得先行安裝。首先我們先來認識一下基本機器學習工作流程,讓讀者對於機器學習工作流有基本而全面的認識。

基本機器學習工作流程(Machine Learning Workflow)

 如何使用 Python 學習機器學習(Machine Learning)

  1. 明確定義問題 (Problem Definition)
  2. 獲取資料與探索性資料分析 (Get Data & Exploratory Data Analysis)
  3. 資料預處理與特徵工程 (Data Clean/Preprocessing & Feature Engineering)
  4. 訓練模型與校調 (Model Training)
  5. 模型驗證 (Model Predict & Testing)
  6. 模型優化 (Model Optimization)
  7. 上線運行 (Deploy Model)

明確定義問題 (Problem Definition)

 如何使用 Python 學習機器學習(Machine Learning)

明確定義問題是進行機器學習工作流的第一步。由於機器學習和一般的 Web 網頁應用程式開發比較不一樣,其需要的運算資源和時間成本比較高,若能一開始就定義好問題並將問題抽象為數學問題將有助於我們要蒐集的資料集和節省工作流程的時間。

舉例來說,本篇文章範例希望預測 Iris 鳶尾花屬於哪一個類別(setosa 山鳶尾、versicolor 變色鳶尾、virginica 維吉尼亞鳶尾),這邊我們就可以決定是要進行有對應結果的監督式學習:二元分類問題(binary classification)、多類別分類問題(multi-classification)還是連續量的迴歸問題(regression),或是沒有標籤結果的非監督式學習(例如:clustering)等,我們這邊假設這是一個多類別分類問題:給定未知資料希望能預測花朵屬於哪一類。換句話說,就是說我們先定義好我們想要解決或是預測的問題,然後去蒐集對應的資料。

獲取資料與探索性資料分析 (Get Data & Exploratory Data Analysis)

 如何使用 Python 學習機器學習(Machine Learning)

基本上資料集的完整性某種程度決定了預測結果是否能發揮模型最大功效。由於我們是教學文章,這邊我們的範例使用 scikit-learn 內建的玩具資料集 Iris(鳶尾花)的花萼、花蕊長寬進行花朵類別判別(setosa 山鳶尾、versicolor 變色鳶尾、virginica 維吉尼亞鳶尾)。在這個資料集中已經幫我們標註好每筆資料對應的類別,所以我們可以視為多類別分類問題(multi-classification)。

 如何使用 Python 學習機器學習(Machine Learning)

引入模組

# 引入 numpy、pd 和 sklearn(scikit-learn) 模組
import numpy as np
import pandas as pd
from sklearn import datasets
# 引入 train_test_split 分割方法,注意在 sklearn v0.18 後 train_test_split 從 sklearn.cross_validation 子模組搬到 sklearn.model_selection 中
from sklearn.model_selection import train_test_split
# 引入 KNeighbors 模型
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import LinearSVC

引入資料集並進行探索性資料分析

# 引入 iris 資料集
raw_iris = datasets.load_iris()
# 探索性分析 Exploratory data analysis,了解資料集內容
# 先印出 key 值,列出有哪些值:['data', 'target', 'target_names', 'DESCR', 'feature_names']
print(raw_iris.keys())

# 印出 feature 值
print(raw_iris['data'])
# 印出目標值,分別對應的是三種花的類別:['setosa 山鳶尾' 'versicolor 變色鳶尾' 'virginica 維吉尼亞鳶尾']
print(raw_iris['target'])
# 印出目標標籤,三種花的類別:['setosa' 'versicolor' 'virginica']
print(raw_iris['target_names'])
# 印出資料集內容描述
print(raw_iris['DESCR'])
# 印出屬性名稱,['sepal length 花萼長度 (cm)', 'sepal width 花萼寬度 (cm)', 'petal length 花蕊長度 (cm)', 'petal width 花蕊寬度 (cm)']
print(raw_iris['feature_names'])

# 類別種類
print(np.unique(raw_iris.target))

dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names']) [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2] [ 5.4 3.9 1.7 0.4] [ 4.6 3.4 1.4 0.3] [ 5. 3.4 1.5 0.2] [ 4.4 2.9 1.4 0.2] [ 4.9 3.1 1.5 0.1] [ 5.4 3.7 1.5 0.2] [ 4.8 3.4 1.6 0.2] [ 4.8 3. 1.4 0.1] [ 4.3 3. 1.1 0.1] [ 5.8 4. 1.2 0.2] [ 5.7 4.4 1.5 0.4] [ 5.4 3.9 1.3 0.4] [ 5.1 3.5 1.4 0.3] [ 5.7 3.8 1.7 0.3] [ 5.1 3.8 1.5 0.3] [ 5.4 3.4 1.7 0.2] [ 5.1 3.7 1.5 0.4] [ 4.6 3.6 1. 0.2] [ 5.1 3.3 1.7 0.5] [ 4.8 3.4 1.9 0.2] [ 5. 3. 1.6 0.2] [ 5. 3.4 1.6 0.4] [ 5.2 3.5 1.5 0.2] [ 5.2 3.4 1.4 0.2] [ 4.7 3.2 1.6 0.2] [ 4.8 3.1 1.6 0.2] [ 5.4 3.4 1.5 0.4] [ 5.2 4.1 1.5 0.1] [ 5.5 4.2 1.4 0.2] [ 4.9 3.1 1.5 0.1] [ 5. 3.2 1.2 0.2] [ 5.5 3.5 1.3 0.2] [ 4.9 3.1 1.5 0.1] [ 4.4 3. 1.3 0.2] [ 5.1 3.4 1.5 0.2] [ 5. 3.5 1.3 0.3] [ 4.5 2.3 1.3 0.3] [ 4.4 3.2 1.3 0.2] [ 5. 3.5 1.6 0.6] [ 5.1 3.8 1.9 0.4] [ 4.8 3. 1.4 0.3] [ 5.1 3.8 1.6 0.2] [ 4.6 3.2 1.4 0.2] [ 5.3 3.7 1.5 0.2] [ 5. 3.3 1.4 0.2] [ 7. 3.2 4.7 1.4] [ 6.4 3.2 4.5 1.5] [ 6.9 3.1 4.9 1.5] [ 5.5 2.3 4. 1.3] [ 6.5 2.8 4.6 1.5] [ 5.7 2.8 4.5 1.3] [ 6.3 3.3 4.7 1.6] [ 4.9 2.4 3.3 1. ] [ 6.6 2.9 4.6 1.3] [ 5.2 2.7 3.9 1.4] [ 5. 2. 3.5 1. ] [ 5.9 3. 4.2 1.5] [ 6. 2.2 4. 1. ] [ 6.1 2.9 4.7 1.4] [ 5.6 2.9 3.6 1.3] [ 6.7 3.1 4.4 1.4] [ 5.6 3. 4.5 1.5] [ 5.8 2.7 4.1 1. ] [ 6.2 2.2 4.5 1.5] [ 5.6 2.5 3.9 1.1] [ 5.9 3.2 4.8 1.8] [ 6.1 2.8 4. 1.3] [ 6.3 2.5 4.9 1.5] [ 6.1 2.8 4.7 1.2] [ 6.4 2.9 4.3 1.3] [ 6.6 3. 4.4 1.4] [ 6.8 2.8 4.8 1.4] [ 6.7 3. 5. 1.7] [ 6. 2.9 4.5 1.5] [ 5.7 2.6 3.5 1. ] [ 5.5 2.4 3.8 1.1] [ 5.5 2.4 3.7 1. ] [ 5.8 2.7 3.9 1.2] [ 6. 2.7 5.1 1.6] [ 5.4 3. 4.5 1.5] [ 6. 3.4 4.5 1.6] [ 6.7 3.1 4.7 1.5] [ 6.3 2.3 4.4 1.3] [ 5.6 3. 4.1 1.3] [ 5.5 2.5 4. 1.3] [ 5.5 2.6 4.4 1.2] [ 6.1 3. 4.6 1.4] [ 5.8 2.6 4. 1.2] [ 5. 2.3 3.3 1. ] [ 5.6 2.7 4.2 1.3] [ 5.7 3. 4.2 1.2] [ 5.7 2.9 4.2 1.3] [ 6.2 2.9 4.3 1.3] [ 5.1 2.5 3. 1.1] [ 5.7 2.8 4.1 1.3] [ 6.3 3.3 6. 2.5] [ 5.8 2.7 5.1 1.9] [ 7.1 3. 5.9 2.1] [ 6.3 2.9 5.6 1.8] [ 6.5 3. 5.8 2.2] [ 7.6 3. 6.6 2.1] [ 4.9 2.5 4.5 1.7] [ 7.3 2.9 6.3 1.8] [ 6.7 2.5 5.8 1.8] [ 7.2 3.6 6.1 2.5] [ 6.5 3.2 5.1 2. ] [ 6.4 2.7 5.3 1.9] [ 6.8 3. 5.5 2.1] [ 5.7 2.5 5. 2. ] [ 5.8 2.8 5.1 2.4] [ 6.4 3.2 5.3 2.3] [ 6.5 3. 5.5 1.8] [ 7.7 3.8 6.7 2.2] [ 7.7 2.6 6.9 2.3] [ 6. 2.2 5. 1.5] [ 6.9 3.2 5.7 2.3] [ 5.6 2.8 4.9 2. ] [ 7.7 2.8 6.7 2. ] [ 6.3 2.7 4.9 1.8] [ 6.7 3.3 5.7 2.1] [ 7.2 3.2 6. 1.8] [ 6.2 2.8 4.8 1.8] [ 6.1 3. 4.9 1.8] [ 6.4 2.8 5.6 2.1] [ 7.2 3. 5.8 1.6] [ 7.4 2.8 6.1 1.9] [ 7.9 3.8 6.4 2. ] [ 6.4 2.8 5.6 2.2] [ 6.3 2.8 5.1 1.5] [ 6.1 2.6 5.6 1.4] [ 7.7 3. 6.1 2.3] [ 6.3 3.4 5.6 2.4] [ 6.4 3.1 5.5 1.8] [ 6. 3. 4.8 1.8] [ 6.9 3.1 5.4 2.1] [ 6.7 3.1 5.6 2.4] [ 6.9 3.1 5.1 2.3] [ 5.8 2.7 5.1 1.9] [ 6.8 3.2 5.9 2.3] [ 6.7 3.3 5.7 2.5] [ 6.7 3. 5.2 2.3] [ 6.3 2.5 5. 1.9] [ 6.5 3. 5.2 2. ] [ 6.2 3.4 5.4 2.3] [ 5.9 3. 5.1 1.8]] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2] ['setosa' 'versicolor' 'virginica'] Iris Plants Database

Notes

Data Set Characteristics: :Number of Instances: 150 (50 in each of three classes) :Number of Attributes: 4 numeric, predictive attributes and the class :Attribute Information:

  • sepal length in cm
  • sepal width in cm
  • petal length in cm
  • petal width in cm
  • class:
    • Iris-Setosa
    • Iris-Versicolour
    • Iris-Virginica :Summary Statistics:

============== ==== ==== ======= ===== ==================== Min Max Mean SD Class Correlation ============== ==== ==== ======= ===== ==================== sepal length: 4.3 7.9 5.84 0.83 0.7826 sepal width: 2.0 4.4 3.05 0.43 -0.4194 petal length: 1.0 6.9 3.76 1.76 0.9490 (high!) petal width: 0.1 2.5 1.20 0.76 0.9565 (high!) ============== ==== ==== ======= ===== ====================

:Missing Attribute Values: None :Class Distribution: 33.3% for each of 3 classes. :Creator: R.A. Fisher :Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov) :Date: July, 1988

This is a copy of UCI ML iris datasets. http://archive.ics.uci.edu/ml/datasets/Iris

The famous Iris database, first used by Sir R.A Fisher

This is perhaps the best known database to be found in the pattern recognition literature. Fisher's paper is a classic in the field and is referenced frequently to this day. (See Duda & Hart, for example.) The data set contains 3 classes of 50 instances each, where each class refers to a type of iris plant. One class is linearly separable from the other 2; the latter are NOT linearly separable from each other.

References

  • Fisher,R.A. "The use of multiple measurements in taxonomic problems" Annual Eugenics, 7, Part II, 179-188 (1936); also in "Contributions to Mathematical Statistics" (John Wiley, NY, 1950).
  • Duda,R.O., & Hart,P.E. (1973) Pattern Classification and Scene Analysis. (Q327.D83) John Wiley & Sons. ISBN 0-471-22361-1. See page 218.
  • Dasarathy, B.V. (1980) "Nosing Around the Neighborhood: A New System Structure and Classification Rule for Recognition in Partially Exposed Environments". IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. PAMI-2, No. 1, 67-71.
  • Gates, G.W. (1972) "The Reduced Nearest Neighbor Rule". IEEE Transactions on Information Theory, May 1972, 431-433.
  • See also: 1988 MLC Proceedings, 54-64. Cheeseman et al"s AUTOCLASS II conceptual clustering system finds 3 classes in the data.
  • Many, many more ...

['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'] [0 1 2]

資料預處理與特徵工程 (Data Clean/Preprocessing & Feature Engineering)

 如何使用 Python 學習機器學習(Machine Learning)

良好的資料輸入取決於資料預處理與特徵工程,而好的輸入將大大影響到模型是否可以發揮其理論正常水準。以下把資料轉成 DataFrame 格式方便進行操作。由於這邊的資料集已經是相當完整的資料集,所以我們這邊就不用特別進行資料預處理和特徵工程的部份,然而在真實世界中,真正在進行機器學習工作流程的時候資料預處理往往是最花時間的部份。同時為了方便模型的校調,我們這邊把資料集分為 70% 訓練資料,30% 驗證資料。

# 將資料轉為 pandas DataFrame
# data 為觀察目標變數
df_X = pd.DataFrame(raw_iris.data)
# target 為預測變數
df_y = pd.DataFrame(raw_iris.target)

# 將資料切分為 training data 和 testing data,其中 random_state 若設為 0 或不設則即便實例不同但因種子相同產生同樣隨機編號,若設為 1 則每次隨機產生不同編號
# test_size 為切分 training data 和 testing data 的比例
X_train, X_test, y_train, y_test = train_test_split(df_X, df_y, test_size=0.3)
# 印出所有資料集筆數
print(len(df_y))

150

# 印出切分 y_train 的數量為所有資料集的 70%,共 105 筆
print(y_train)
print(len(y_train))

0 39 0 106 2 99 1 0 0 16 0 118 2 80 1 29 0 11 0 104 2 100 2 72 1 108 2 42 0 20 0 31 0 115 2 111 2 89 1 83 1 130 2 41 0 66 1 120 2 113 2 6 0 126 2 62 1 23 0 97 1 .. .. 10 0 76 1 129 2 144 2 137 2 12 0 79 1 123 2 127 2 36 0 74 1 37 0 131 2 110 2 22 0 32 0 147 2 134 2 102 2 75 1 88 1 148 2 33 0 56 1 28 0 90 1 82 1 25 0 121 2 13 0

[105 rows x 1 columns] 105

# 印出切分的 y_test 資料為所有資料集的 30%,共 45 筆
print(y_test)
print(len(y_test))

0 102 2 53 1 143 2 70 1 61 1 67 1 24 0 124 2 36 0 92 1 114 2 31 0 120 2 87 1 74 1 47 0 69 1 56 1 93 1 16 0 144 2 133 2 29 0 57 1 116 2 50 1 86 1 44 0 3 0 21 0 82 1 99 1 134 2 111 2 135 2 4 0 2 0 91 1 85 1 122 2 127 2 11 0 27 0 79 1 51 1 45

訓練模型與校調 (Model Training)

 如何使用 Python 學習機器學習(Machine Learning)

上面是 scikit-learn 提供的演算法 cheat-sheet,當你面對琳琅滿目的模型一開始不知道要選擇什麼的話可以按圖索驥參考,另外這邊提供大圖支援連結

這邊我們參考上圖來選擇適合模型:

  1. 樣本資料是否大於 50 筆:範例資料集總共有 150 筆資料,大於 50
  2. 是否為分類問題:Iris 花朵類別預測是多類別分類問題
  3. 是否有標籤好的資料:已經有 label 資料
  4. 樣本資料是否小於 100K:資料小於 100K
  5. 選擇 Linear SVC 模型(第一個選擇的模型)
  6. 是否是文字資料:不是
  7. 選擇 KNeighborsClassifier 模型(第二個選擇的模型)
  8. 後續優化 / SVC / Ensemble
# 初始化 LinearSVC 實例
lin_clf = LinearSVC()
# 使用 fit 來建置模型,其參數接收 training data matrix, testing data array,所以進行 y_train.values.ravel() Data Frame 轉換
lin_clf.fit(X_train, y_train.values.ravel())

LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True, intercept_scaling=1, loss='squared_hinge', max_iter=1000, multi_class='ovr', penalty='l2', random_state=None, tol=0.0001, verbose=0)

# 初始化 KNeighborsClassifier 實例
knn = KNeighborsClassifier()

# 使用 fit 來建置模型,其參數接收 training data matrix, testing data array,所以進行 y_train.values.ravel() 轉換
knn.fit(X_train, y_train.values.ravel())

KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=1, n_neighbors=5, p=2, weights='uniform')

模型驗證 (Model Predict & Testing)

 如何使用 Python 學習機器學習(Machine Learning)

監督式學習的分類問題通常會分為訓練模型和驗證模型,這邊我們使用 predict 去產生對應的目標值,此時和正確答案(已經標籤好的目標值)比較可以知道模型預測的正確率。我們可以看到 KNeighborsClassifier 在正確率(accuracy)表現上相對比較好一點(0.98 比 0.93)。

# 使用 X_test 來預測結果
print(lin_clf.predict(X_test))

[1 1 0 2 1 2 0 1 1 2 2 1 0 2 0 0 2 1 2 0 0 1 2 0 2 1 2 0 0 0 1 0 2 1 1 0 0 0 1 0 1 2 2 1 1]

# 印出預測準確率
print(lin_clf.score(X_test, y_test))

0.933333333333

# 使用 X_test 來預測結果
print(knn.predict(X_test))

[1 1 0 1 1 2 0 1 1 2 2 1 0 2 0 0 2 1 2 0 0 1 2 0 2 1 2 0 0 0 1 0 1 1 1 0 0 0 1 0 1 2 2 1 1]

# 印出 testing data 預測標籤機率
print(knn.predict_proba(X_test))

[[ 0. 1. 0. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 0. 0.8 0.2] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 0. 0. 1. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 0. 1. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 0. 0.2 0.8] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 1. 0. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 0.6 0.4] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 0. 0. 1. ] [ 0. 1. 0. ] [ 0. 1. 0. ]]

# 印出預測準確率
print(knn.score(X_test, y_test))

0.977777777778

模型優化 (Model Optimization)

由於本文是簡易範例,這邊就沒有示範如何進行模型優化(這邊可以嘗試使用 SVC 和 Ensemble 方法)。不過一般來說在分類模型優化上,讓模型預測表現的更好的方法大約有幾種:

  1. 特徵工程:選擇更適合特徵值或是更好的資料清理,某種程度上很需要專業知識的協助(domain konwledge)去發現和整合出更好的 feature
  2. 調整模型參數:調整模型的參數
  3. 模型融合:結合幾個弱分類器結果來變成強的分類器

上線運行 (Deploy Model)

當模型優化完畢就可以進行上線運行,其中 Python 比 R 更具優勢的地方,那就是 Python 很容易跟現有的系統進行整合,Python 也有許多好用的 Web 框架可以使用,也因為 Python 是膠水語言,若要進行效能優化也可以很容易呼叫 C/C++ 進行操作,提昇執行效能。

總結

以上用一個簡單的範例介紹了 Python 機器學習套件 Scikit Learn 的基本功能和機器學習整個基本 Workflow。由於是基礎範例所以省略一些比較繁瑣的資料處理部分,事實上,真實世界資料大多是非結構化資料的髒資料,而資料分析的過程往往需要花上許多時間進行資料預處理和資料清理上。接下來我們將介紹其他 Python 資料科學和機器學習生態系和相關工具。

延伸閱讀

  1. 机器学习实战 之 kNN 分类
  2. Machine Learning Workflow
  3. Kaggle机器学习之模型融合(stacking)心得
  4. Python 資料視覺化
  5. Train & Predict workflow
  6. Sample Classification Pipeline workflow
  7. 【机器学习】模型融合方法概述

(image via mediummaprsilvrbackcamoscipymirlabconcreteinteractivesndimg

用 Python 自學資料科學與機器學習入門實戰:Matplotlib 基礎入門

· 閱讀時間約 8 分鐘

 從零開始學資料科學:Numpy 基礎入門

本系列文章將透過系統介紹資料科學(Data Science)相關的知識,透過 Python 帶領讀者從零開始進入資料科學的世界。這邊我們將介紹 Matplotlib 這個 Python 資料視覺化的核心工具。

什麼是 Matplotlib?

Python 的視覺化套件有靜態的 MatplotlibSeabornggplot(借鏡於 Rggplot2)套件以及動態的 Bokeh 套件(類似於 D3.js)。其中 Matplotlib 是 Python 的一個重要模組(Python 是一個高階語言也是一種膠水語言,可以透過整合其他低階語言同時擁有效能和高效率的開發),主要用於資料視覺化上。一般來說使用 Matplotlib 有兩種主要方式:直接和 Matplotlib 的全域 pyplot 模組互動操作,第二種則是物件導向形式的操作方式。若是只有一張圖的話使用全域 pyplot 很方便,若是有多張圖的話用物件導向操作。一般來說 Matplotlib 預設值並不理想,但它的優點在於很容易在上面外包一層提供更好的預設值或是自己修改預設值。

第一張 Matplotlib 圖片

# 引入模組
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x = pd.period_range(pd.datetime.now(), periods=200, freq='d')
x = x.to_timestamp().to_pydatetime()
# 產生三組,每組 200 個隨機常態分布元素
y = np.random.randn(200, 3).cumsum(0)
plt.plot(x, y)
plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

常用屬性和參數調整

# Matplotlib 使用點 point 而非 pixel 為圖的尺寸測量單位,適合用於印刷出版。1 point = 1 / 72 英吋,但可以調整

import matplotlib as mpl
mpl.rcParams['lines.linewidth'] = 5
mpl.rcParams['lines.color'] = 'r'
mpl.rcParams['figure.figsize'] = (10, 10)
plt.gcf().set_size_inches(10, 10)

x = pd.period_range(pd.datetime.now(), periods=200, freq='d')
x = x.to_timestamp().to_pydatetime()
# 產生三組,每組 200 個隨機常態分布元素
y = np.random.randn(200, 3).cumsum(0)
plt.plot(x, y)
plt.show()

物件導向式 Matplotlib

 從零開始學資料科學:Matplotlib 基礎入門

# 設定標籤
plots = plt.plot(x, y)
plt.legend(plots, ('Apple', 'Facebook', 'Google'), loc='best', framealpha=0.5, prop={'size': 'large', 'family': 'monospace'})
plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

# 標題與軸標籤
plt.title('Random Trends')
plt.xlabel('Date')
plt.ylabel('Cum. Sum')
plt.figtext(0.995, 0.01, 'CopyRight', ha='right', va='bottom')
# 避免被圖表元素被蓋住
plt.tight_layout()
plt.plot(x, y)
plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

# 儲存圖表
plt.savefig('plt.svg')
# 使用物件導向方式控制圖表,透過控制 figure 和 axes 來操作。其中 figure 和全域 pyplot 部分屬性相同。例如: fig.text() 對應到 plt.fig_text()
fig = plt.figure(figsize=(8, 4), dpi=200, tight_layout=True, linewidth=1, edgecolor='r')
# 軸與子圖表
fig = plt.figure(figsize=(8, 4))

# 插入主要軸,可以透過 add_axes 控制軸在圖裡的位置。例如:[bottom*0.1, left*0.1, top*0.5, right*0.5],fig.add_axes([0.1, 0.1, 0.5, 0.5])
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.set_title('Main Axes with Insert Child Axes')
ax.plot(x, y[:, 0])
ax.set_xlabel('Date')
ax.set_ylabel('Cum. sum')

# 插入軸
ax = fig.add_axes([0.15, 0.15, 0.3, 0.3])
ax.plot(x, y[:, 1], color='g')
ax.set_xticks([])

 從零開始學資料科學:Matplotlib 基礎入門

# 單一圖與軸繪製(subplots 不帶參數回傳擁有一軸 figure 物件,幾乎等同於 matplotlib 全域物件)
# matplotlib 內建版面編排系統相對好用。圖表大小不一可以使用 gridspec 模組
figure, ax = plt.subplots()
plots = ax.plot(x, y, label='')
figure.set_size_inches(8, 4)
ax.legend(plots, ('Apple', 'Faceook', 'Google'), loc='best', framealpha=0.25, prop={'size': 'small', 'family': 'monospace'})

ax.set_title('Random trends')
ax.set_xlabel('Date')
ax.set_ylabel('Cum. sum')

ax.grid(True) # 使用格子
figure.text(0.995, 0.01, 'ACM 2015', ha='right', va='bottom')
figure.tight_layout()

 從零開始學資料科學:Matplotlib 基礎入門

# 使用子圖表
figure, ax = plt.subplots()
plots = ax.plot(x, y, label='')
figure.set_size_inches(8, 4)
ax.legend(plots, ('Apple', 'Faceook', 'Google'), loc='best', framealpha=0.25, prop={'size': 'small', 'family': 'monospace'})
ax.set_title('Random trends')
ax.set_xlabel('Date')
ax.set_ylabel('Cum. sum')
ax.grid(True)

figure.text(0.995, 0.01, 'Acm', ha='right', va='bottom')
figure.tight_layout()

 從零開始學資料科學:Matplotlib 基礎入門

# 使用子圖表產生多個圖表
fig, axes = plt.subplots(nrows=3, ncols=1, sharex=True, sharey=True, figsize=(8, 8))
labelled_data = zip(y.transpose(), ('Apple', 'Faceook', 'Google'), ('b', 'g', 'r'))
fig.suptitle('Three Random Trends', fontsize=16)

for i, ld in enumerate(labelled_data):
ax = axes[i]
ax.plot(x, ld[0], label=ld[1], color=ld[2])
ax.set_ylabel('Cum. sum')
ax.legend(loc='upper left', framealpha=0.5, prop={'size': 'small'})
axes[-1].set_xlabel('Date')

 從零開始學資料科學:Matplotlib 基礎入門

常見圖表

  1. 直方圖(Histogram)

    # 直方圖
    normal_samples = np.random.normal(size=100) # 生成 100 組標準常態分配(平均值為 0,標準差為 1 的常態分配)隨機變數
    plt.hist(normal_samples, width=0.1)
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

  2. 散佈圖(Scatter plot)

    # 散佈圖
    num_points = 100
    gradient = 0.5
    x = np.array(range(num_points))
    y = np.random.randn(num_points) * 10 + x * gradient
    fig, ax = plt.subplots(figsize=(8, 4))
    ax.scatter(x, y)

    fig.suptitle('A Simple Scatter Plot')
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

    # 散佈圖 + 迴歸
    num_points = 100
    gradient = 0.5
    x = np.array(range(num_points))
    y = np.random.randn(num_points) * 10 + x * gradient

    fig, ax = plt.subplots(figsize=(8, 4))

    ax.scatter(x, y)

    m, c = np.polyfit(x, y, 1) # 使用 Numpy 的 polyfit,參數 1 代表一維,算出 fit 直線斜率
    ax.plot(x, m * x + c) # 使用 y = m * x + c 斜率和常數匯出直線
    fig.suptitle('Scatter with regression')
    plt.show()
  3. 線圖(Line plot)

     從零開始學資料科學:Matplotlib 基礎入門

    # 線圖
    age = [4, 4, 17, 17, 18]
    points = [2, 20, 22, 24, 20]

    plt.plot(age, points)
    plt.show()
  4. 長條圖(Bar plot)

     從零開始學資料科學:Matplotlib 基礎入門

    # 長條圖
    labels = ['Physics', 'Chemistry', 'Literature', 'Peace']
    foo_data = [3, 6, 10, 4]
    bar_width = 0.5
    xlocations = np.array(range(len(foo_data))) + bar_width

    plt.bar(xlocations, foo_data, width=bar_width)

    plt.title('Stock Price')
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

  5. 盒鬚圖(Box plot)

    # 盒鬚圖
    normal_examples = np.random.normal(size = 100) # 生成 100 組標準常態分配(平均值為 0,標準差為 1 的常態分配)隨機變數

    plt.boxplot(normal_examples)
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

  6. 圓餅圖(Pie plot)

    # 圓餅圖
    data = np.random.randint(1, 11, 5) # 生成
    x = np.arange(len(data))

    plt.pie(data)

    plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

Python 其他資料視覺化套件

  1. Seaborn

    # Seaborn
    import numpy as np
    import seaborn as sns
    import matplotlib.pyplot as plt
    sns.set(style="white", context="talk")
    rs = np.random.RandomState(7)


    # 準備 matplotlib 圖表
    f, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(8, 6), sharex=True)

    # 產生連續資料
    x = np.array(list("ABCDEFGHI"))
    y1 = np.arange(1, 10)
    sns.barplot(x, y1, palette="BuGn_d", ax=ax1)
    ax1.set_ylabel("Sequential")

    # 調整成 diverging 資料
    y2 = y1 - 5
    sns.barplot(x, y2, palette="RdBu_r", ax=ax2)
    ax2.set_ylabel("Diverging")

    # 隨機資料
    y3 = rs.choice(y1, 9, replace=False)
    sns.barplot(x, y3, palette="Set3", ax=ax3)
    ax3.set_ylabel("Qualitative")

    # 秀出圖片
    sns.despine(bottom=True)
    plt.setp(f.axes, yticks=[])
    plt.tight_layout(h_pad=3)

     從零開始學資料科學:Matplotlib 基礎入門

  2. Bokeh

    # Bokeh
    from bokeh.plotting import figure, output_file, show

    # 準備資料
    x = [1, 2, 3, 4, 5]
    y = [6, 7, 2, 4, 5]

    # 輸出成靜態 HTML
    output_file("lines.html")

    # 創建新的標題和軸圖表
    p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')

    # 繪製直線圖
    p.line(x, y, legend="Temp.", line_width=2)

    # 呈現結果
    show(p)

總結

以上介紹了 Matplotlib 的基礎知識和 api,同時也介紹了 Python 其他資料視覺化套件。一般來說 Matplotlib 預設值並不理想,但它的優點在於很容易在上面外包一層提供更好的預設值或是自己修改預設值。一般來說我們在進行資料科學和機器學習分析的過程中我們會先使用資訊視覺化工具來了解整個資料集的特色並針對資料進行後續的處理和特徵選取,所以說資料視覺化不僅能呈現資料分析的結果,對於資料分析的過程也十分重要。

延伸閱讀

  1. [python] numpy axis概念整理筆記
  2. [第 18 天] 資料視覺化 matplotlib
  3. 数据可视化(三)- Seaborn简易入门

(image via matplotlib

用 Python 自學資料科學與機器學習入門實戰:Pandas 基礎入門

· 閱讀時間約 12 分鐘
Python 資料科學系列教學

本文是 Python 資料科學與機器學習系列 的第三篇文章:

  1. Python 資料科學入門介紹
  2. NumPy 基礎教學
  3. Pandas 基礎入門 (本文)
  4. Matplotlib 資料視覺化
  5. Scikit-learn 機器學習

📚 查看完整系列

 如何使用 Python 學習機器學習(Machine Learning)

本系列文章將透過 Python 及其資料科學生態系(Numpy、Scipy、Pandas、Scikit-learn、Statsmodels、Matplotlib、Scrapy、Keras、TensorFlow 等)來系統性介紹資料科學和相關的知識,透過 Python 帶領讀者進入資料科學的世界和機器學習的世界。在這個單元中我們將介紹 Pandas 這個基於 Numpy 的資料處理和分析神兵利器。

事實上,真實世界並非如此美好,大部分資料分析的工作時間有很大一部分都是在處理髒資料,希望讓資料可以符合模型輸入的需求,而 Pandas 正是扮演這個資料預處理和資料清洗的核心角色,是 Python 在和 R 爭奪資料科學第一程式語言霸主時的生力軍,接下來我們將介紹 Pandas 核心功能和資料的操作方式。

 如何使用 Python 學習機器學習(Machine Learning)

Pandas 核心功能介紹

創建資料結構

在 Pandas 中主要有兩大資料結構:Series、DataFrame,與 Numpy 中的 ndarray 比較不同的是 Pandas DataFrame 可以存異質資料(不同資料型別)。

Series 類似於 Python 本身的 list 資料結構,不同的是每個元素有自己的 index(可以自己命名):

%matplotlib inline
# 引入 numpy 和 pandas 模組
import numpy as np
import pandas as pd
s1 = pd.Series([1, 3, 5, np.nan, 6, 8]) # 使用 Python lits 產生 Series,其中包含一個值為 NaN

print(s1)

0 1.0 1 3.0 2 5.0 3 NaN 4 6.0 5 8.0 dtype: float64

s2 = pd.Series(np.random.randint(2, size=[3])) # 使用 np.random.randint 產生 3 個 0-2(不含 2)的數組

print(s2)

0 1 1 1 2 1 dtype: int64

DataFrame 可以使用 np.random.randn 產生值來創建,也可以使用 Python dict 進行創建:

# 產生 20170101-20170106 的值,DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04', '2017-01-05', '2017-01-06'], dtype='datetime64[ns]', freq='D')
dates = pd.date_range('20170101', periods=6)

# 產生 row6,column4 個 standard normal distribution 隨機值,使用 ABCD 當 columns,使用 dates 當 index
df0 = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
print(df0)

A B C D 2017-01-01 1.112542 -0.142577 0.832830 -2.755133 2017-01-02 -0.218838 -0.304488 1.437599 -0.402454 2017-01-03 0.295245 -0.786898 -1.231896 -0.224959 2017-01-04 -0.346745 -1.582944 -0.464175 -0.410576 2017-01-05 0.163782 0.948795 -0.420505 -0.641032 2017-01-06 0.515806 -0.935421 -0.701349 -0.820109

# 使用 dict 來創建 DataFrame
teams = ['Web', 'Mobile', 'Data']
nums = [12, 14, 34]
rd_team_dict = {
'teams': teams,
'nums': nums
}
rd_team_df = pd.DataFrame(rd_team_dict)

print(rd_team_df)

nums teams 0 12 Web 1 14 Mobile 2 34 Data

觀察資料

# 觀察資料型態、結構、內容值
df = pd.DataFrame({ 'A' : 1.,
'B' : pd.Timestamp('20170102'),
'C' : pd.Series(1,index=list(range(4)),dtype='float32'),
'D' : np.array([3] * 4,dtype='int32'),
'E' : pd.Categorical(["test","train","test","train"]),
'F' : 'foo' })

# 印出內容值資料型別
print(df.dtypes)

A float64 B datetime64[ns] C float32 D int32 E category F object dtype: object

# 印出資料維度
print(df.shape)

(4, 6)

# 印出每行資料長度
print(len(df))

4

# 印出 DataFrame 資料概況
print(df.info())

<class 'pandas.core.frame.DataFrame'> Int64Index: 4 entries, 0 to 3 Data columns (total 6 columns): A 4 non-null float64 B 4 non-null datetime64[ns] C 4 non-null float32 D 4 non-null int32 E 4 non-null category F 4 non-null object dtypes: category(1), datetime64ns, float32(1), float64(1), int32(1), object(1) memory usage: 180.0+ bytes None

# 印出基本敘述統計數據
print(df.describe())

A C D count 4.0 4.0 4.0 mean 1.0 1.0 3.0 std 0.0 0.0 0.0 min 1.0 1.0 3.0 25% 1.0 1.0 3.0 50% 1.0 1.0 3.0 75% 1.0 1.0 3.0 max 1.0 1.0 3.0

# 印出首 i 個數據
print(df.head(2))

A B C D E F 0 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo

# 印出尾 i 個數據
print(df.tail(2))

A B C D E F 2 1.0 2017-01-02 1.0 3 test foo 3 1.0 2017-01-02 1.0 3 train foo

# 印出 index 值
print(df.index)

Int64Index([0, 1, 2, 3], dtype='int64')

# 印出 columns 值
print(df.columns)

Index(['A', 'B', 'C', 'D', 'E', 'F'], dtype='object')

# 印出 values 值
print(df.values)

[[1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'test' 'foo'] [1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'train' 'foo'] [1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'test' 'foo'] [1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'train' 'foo']]

# 印出轉置 DataFrame
print(df.T)

0 1 2
A 1 1 1
B 2017-01-02 00:00:00 2017-01-02 00:00:00 2017-01-02 00:00:00
C 1 1 1
D 3 3 3
E test train test
F foo foo foo

3
A 1
B 2017-01-02 00:00:00
C 1
D 3
E train
F foo

# sort by the index labels。axis=0 使用 index 進行 sort,axis=1 使用 columns 進行 sort。ascending 決定是否由小到大
print(df.sort_index(axis=0, ascending=False))

A B C D E F 3 1.0 2017-01-02 1.0 3 train foo 2 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo 0 1.0 2017-01-02 1.0 3 test foo

# sort by the values of columns
print(df.sort_values(by='E'))

A B C D E F 0 1.0 2017-01-02 1.0 3 test foo 2 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo 3 1.0 2017-01-02 1.0 3 train foo

選取資料

# 選取值的方式一般建議使用 1. loc, 2. iloc, 3. ix
# label-location based 行列標籤值取值,以下取出 index=1 那一欄,[列, 行]
print(df.loc[0])

A 1 B 2017-01-02 00:00:00 C 1 D 3 E test F foo Name: 0, dtype: object

# iloc 則通過行列數字索引取值,[列,行]
print(df.iloc[0:3, 1:2])

B 0 2017-01-02 1 2017-01-02 2 2017-01-02

# 兼容 loc 和 iloc
print(df.ix[0, 'B'])

2017-01-02 00:00:00

# 兼容 loc 和 iloc
print(df.ix[1, 3])

3

# 布林取值,取出 A 行大於 0 的資料
print(df[df.A > 0])

A B C D E F 0 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo 2 1.0 2017-01-02 1.0 3 test foo 3 1.0 2017-01-02 1.0 3 train foo

# 產生 Series 值
s1 = pd.Series([1,2,3,4,5,6], index=pd.date_range('20170102', periods=6))
print(s1)

2017-01-02 1 2017-01-03 2 2017-01-04 3 2017-01-05 4 2017-01-06 5 2017-01-07 6 Freq: D, dtype: int64

# 更新值
df.loc[:,'D'] = np.array([5] * len(df))
print(df)

A B C D E F 0 1.0 2017-01-02 1.0 5 test foo 1 1.0 2017-01-02 1.0 5 train foo 2 1.0 2017-01-02 1.0 5 test foo 3 1.0 2017-01-02 1.0 5 train foo

處理遺失資料

# 查缺補漏
df2 = pd.DataFrame(index=dates[0:4], columns=list(df.columns) + ['E'])

df2.loc[dates[0]:dates[1], :] = 1

# drop 掉 NaN 值
print(df2.dropna(how='any'))
# 補充 NaN 為 3
print(df2.fillna(value=3))
print(df2)

# 回傳 NaN 布林值
print(pd.isnull(df2))

# inplace 為 True 為直接操作資料,不是操作 copy 副本
df2.dropna(how='any', inplace=True)

A B C D E F E 2017-01-01 1 1 1 1 1 1 1 2017-01-02 1 1 1 1 1 1 1 A B C D E F E 2017-01-01 1 1 1 1 1 1 1 2017-01-02 1 1 1 1 1 1 1 2017-01-03 3 3 3 3 3 3 3 2017-01-04 3 3 3 3 3 3 3 A B C D E F E 2017-01-01 1 1 1 1 1 1 1 2017-01-02 1 1 1 1 1 1 1 2017-01-03 NaN NaN NaN NaN NaN NaN NaN 2017-01-04 NaN NaN NaN NaN NaN NaN NaN A B C D E F E 2017-01-01 False False False False False False False 2017-01-02 False False False False False False False 2017-01-03 True True True True True True True 2017-01-04 True True True True True True True

資料操作

# 針對每一個值進行操作
df.apply(lambda x: x.max() - x.min())

A 2.696944 B 5.285329 C 1.948946 D 2.615037 dtype: float64

串接資料

# 串接資料

df = pd.DataFrame(np.random.randn(10, 4))
print(df)
pieces = [df[:3], df[3:7], df[7:]]
print(pieces)
print(pd.concat(pieces))

0 1 2 3 0 -0.171208 2.200967 0.385574 -0.481588 1 1.447335 1.756239 0.083053 0.255434 2 -0.508576 0.818774 -0.438210 -0.819860 3 1.704828 -0.329642 -1.059202 -0.820319 4 -1.792491 -0.761873 -1.090574 -0.484552 5 0.166621 1.704577 -1.613185 -0.391985 6 0.806292 0.699608 -1.768223 -1.081318 7 -1.168532 0.768302 0.831701 0.422367 8 0.065940 -0.038649 -0.060712 -0.500365 9 0.623535 0.558461 -0.956861 1.229675 [ 0 1 2 3 0 -0.171208 2.200967 0.385574 -0.481588 1 1.447335 1.756239 0.083053 0.255434 2 -0.508576 0.818774 -0.438210 -0.819860, 0 1 2 3 3 1.704828 -0.329642 -1.059202 -0.820319 4 -1.792491 -0.761873 -1.090574 -0.484552 5 0.166621 1.704577 -1.613185 -0.391985 6 0.806292 0.699608 -1.768223 -1.081318, 0 1 2 3 7 -1.168532 0.768302 0.831701 0.422367 8 0.065940 -0.038649 -0.060712 -0.500365 9 0.623535 0.558461 -0.956861 1.229675] 0 1 2 3 0 -0.171208 2.200967 0.385574 -0.481588 1 1.447335 1.756239 0.083053 0.255434 2 -0.508576 0.818774 -0.438210 -0.819860 3 1.704828 -0.329642 -1.059202 -0.820319 4 -1.792491 -0.761873 -1.090574 -0.484552 5 0.166621 1.704577 -1.613185 -0.391985 6 0.806292 0.699608 -1.768223 -1.081318 7 -1.168532 0.768302 0.831701 0.422367 8 0.065940 -0.038649 -0.060712 -0.500365 9 0.623535 0.558461 -0.956861 1.229675

合併資料

# 合併資料
left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})

print(pd.merge(left, right, on='key'))

key lval rval 0 foo 1 4 1 foo 1 5 2 foo 2 4 3 foo 2 5

新增資料

# 新增資料於最後
df = pd.DataFrame(np.random.randn(8, 4), columns=['A','B','C','D'])
print(df)
s = df.iloc[3]
print(df.append(s, ignore_index=True))

A B C D 0 1.780499 1.207626 0.631475 -1.747506 1 -0.603999 -2.364099 1.153066 0.504784 2 0.721924 0.199784 -0.158318 -0.882946 3 -0.378070 -0.379311 0.478997 0.271056 4 0.620888 -0.366262 -0.738695 -0.380854 5 -0.587604 -1.728096 0.279645 -0.927843 6 -0.916445 2.921231 -0.795880 0.867531 7 -0.373190 1.526771 0.136712 0.015765 A B C D 0 1.780499 1.207626 0.631475 -1.747506 1 -0.603999 -2.364099 1.153066 0.504784 2 0.721924 0.199784 -0.158318 -0.882946 3 -0.378070 -0.379311 0.478997 0.271056 4 0.620888 -0.366262 -0.738695 -0.380854 5 -0.587604 -1.728096 0.279645 -0.927843 6 -0.916445 2.921231 -0.795880 0.867531 7 -0.373190 1.526771 0.136712 0.015765 8 -0.378070 -0.379311 0.478997 0.271056

群組操作

# 群組操作
print(df.groupby(['A','B']).sum())

C D A B
-1.232691 0.489020 0.436602 -1.439868 -0.259460 -0.269874 1.655001 0.530137 -0.256261 -0.743254 0.128837 1.050430 0.015723 0.596866 -0.232503 1.247810 0.049633 -0.093130 0.895723 1.049938 0.458667 0.348883 -0.681931 -0.517437 1.446492 0.007736 0.208870 0.211517 2.357912 -0.187805 -0.376578 -0.459085

繪圖

# 印出圖表
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.plot()

png

輸入/輸出

# 讀取檔案/輸出檔案,支援 csv, h5, xlsx 檔案格式
df.to_csv('foo.csv')
pd.read_csv('foo.csv')
df.to_excel('foo.xlsx', sheet_name='Sheet1')
print(pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA']))

A B C D 0 1.446492 0.007736 0.208870 0.211517 1 0.049633 -0.093130 0.895723 1.049938 2 -1.232691 0.489020 0.436602 -1.439868 3 -0.259460 -0.269874 1.655001 0.530137 4 0.015723 0.596866 -0.232503 1.247810 5 0.458667 0.348883 -0.681931 -0.517437 6 2.357912 -0.187805 -0.376578 -0.459085 7 -0.256261 -0.743254 0.128837 1.050430

總結

以上整理了一些 Pandas 核心功能和如何操作資料,接下來我們將介紹其他 Python 資料科學和機器學習生態系和相關工具。

延伸閱讀

  1. 10 Minutes to pandas
  2. Pandas 使用教學 - 第一部分
  3. Python Pandas - Understanding inplace=True
  4. pandas学习笔记
  5. 【Python实战】Pandas:让你像写SQL一样做数据分析(一)

(image via pydatanbcnews

用 Python 自學資料科學與機器學習入門實戰:Numpy 基礎入門

· 閱讀時間約 4 分鐘

 從零開始學資料科學:Numpy 基礎入門

本系列文章將透過系統介紹資料科學(Data Science)相關的知識,透過 Python 帶領讀者從零開始進入資料科學的世界。這邊我們將介紹 Numpy 這個強大的 Python 函式庫。

什麼是 Numpy?

Numpy 是 Python 的一個重要模組(Python 是一個高階語言也是一種膠水語言,可以透過整合其他低階語言同時擁有效能和高效率的開發),主要用於資料處理上。Numpy 底層以 C 和 Fortran 語言實作,所以能快速操作多重維度的陣列。當 Python 處理龐大資料時,其原生 list 效能表現並不理想(但可以動態存異質資料),而 Numpy 具備平行處理的能力,可以將操作動作一次套用在大型陣列上。此外 Python 其餘重量級的資料科學相關套件(例如:Pandas、SciPy、Scikit-learn 等)都幾乎是奠基在 Numpy 的基礎上。因此學會 Numpy 對於往後學習其他資料科學相關套件打好堅實的基礎。

Numpy 基礎操作

 從零開始學資料科學:Numpy 基礎入門

  1. Numpy 陣列 Numpy 的重點在於陣列的操作,其所有功能特色都建築在同質且多重維度的 ndarray(N-dimensional array)上。ndarray 的關鍵屬性是維度(ndim)、形狀(shape)和數值類型(dtype)。 一般我們稱一維陣列為 vector 而二維陣列為 matrix。一開始我們會引入 numpy 模組,透過傳入 listnumpy.array() 創建陣列。

    # 引入 numpy 模組
    import numpy as np
    np1 = np.array([1, 2, 3])
    np2 = np.array([3, 4, 5])

    # 陣列相加
    print(np1 + np2) # [4 6 8]

    # 顯示相關資訊
    print(np1.ndim, np1.shape, np1.dtype) # 1 (3,) int64 => 一維陣列, 三個元素, 資料型別

    np3 = np.array([1, 2, 3, 4, 5, 6])

    從檔案取資料:

    npd = np.genfromtxt('data.csv', delimiter=',')

    改變陣列維度:

    np3 = np3.reshape([2, 3])
    print(np3.ndim, np3.shape, np3.dtype) # 2 (2, 3) int64

    改變陣列型別(bool、int、float、string):

    bool 可以包含 True、False,int 可以包含 int16、int32、int64。其中數字是指 bitsfloat 可以包含 16、32、64 表示小數點後幾位。string 可以是 string、unicode。nan 則表示遺失值。

    np3 = np3.astype('int64')
    np3.dtype
    # dtype('int64')
  2. 建立陣列 建立填滿 0 或 1 的陣列:

    np1 = np.zeros([2, 3]) # array([[ 0.,  0.,  0.], [ 0.,  0.,  0.]])
    np2 = np.ones([2, 3]) # array([[ 1., 1., 1.], [ 1., 1., 1.]])

 從零開始學資料科學:Numpy 基礎入門

  1. 陣列索引與切片 一維陣列操作和 Python 原生 list 類似:

    np3 = np.array([1, 2, 3, 4, 5, 6])
    print(np3[2]) # 3

    二維陣列:

    np3 = np3.reshape([2, 3])

    print(np3[1, 0]) # 4

 從零開始學資料科學:Numpy 基礎入門

  1. 基本操作 使用布林遮罩來取值:

    np3 = np.array([1, 2, 3, 4, 5, 6])
    print(np3 > 3) # [False False False True True True]
    print(np3[np3 > 3]) # [4 5 6]

    加總:

    np3 = np3.reshape([2, 3])
    print(np3.sum(axis=1)) # 將 axis=1 橫向加總 [6 15]

總結

以上介紹了 Numpy 的基礎知識,建立了基本的 array 和 ndarray 的觀念。相信在熟悉 Numpy 之後 Pandas 的學習將會比較容易 (Pandas 的資料容器 DataFrame、Series 事實上是奠基在 Numpy 的陣列上)

延伸閱讀

  1. 7 Steps to Mastering Machine Learning With Python
  2. [python] numpy axis概念整理筆記
  3. Python科学计算:numpy

(image via berkeleycodingeekcornellscipy-lectures

用 Python 自學資料科學與機器學習入門實戰:入門導論

· 閱讀時間約 9 分鐘
Python 資料科學系列教學

本文是 Python 資料科學與機器學習系列 的第一篇文章:

  1. Python 資料科學入門介紹 (本文)
  2. NumPy 基礎教學
  3. Pandas 基礎入門
  4. Matplotlib 資料視覺化
  5. Scikit-learn 機器學習

📚 查看完整系列

 如何使用 Python 學習機器學習(Machine Learning)

隨著資料科學(Data Science)技術的興起,人工智慧(Artificial Intelligence)機器學習(Machine Learning) 成為近幾年來電腦科學界十分熱門的研究領域,如今在實體和線上的學習機器學習的資源有很多,本文整理了一些好用學習資源希望幫助初學者能更容易使用 Python 入門機器學習的領域中,從零開始學習機器學習。若是對於資料科學不熟悉的讀者可以先參考適用於初學者的資料科學影片 ,讓自己對於資料科學有初步的認識。

 如何使用 Python 學習機器學習(Machine Learning)

「人工智慧」(Artificial Intelligence)這專有名稱正式出現在西元 1956 年,在美國達特茅斯學院 (Dartmouth College)召開的第一次人工智慧會議。根據維基百科的定義,人工智慧係指由機器所展現的智慧,一般而言人工智慧又分為「強人工智慧」(Strong AI)和「弱人工智慧」(Weak AI) 兩種不同的主張。所謂的強人工智慧指的是有自我意識、有知覺可以自己推理和解決問題的機器智慧,而「弱人工智慧」只能模擬人類的思維與行為表現,但缺乏真正的推理與解決問題的能力,也不具有自主意識。人工智慧在歷史上經歷了幾次熱潮和寒冬,從最早的邏輯推理到後來的專家系統,再到目前的機器學習/深度學習,機器學習可以視為人工智慧的一個實現方式或是發展的一個歷程。

事實上,人工智慧或是機器學習都是一門跨領域的學門,牽涉了電腦科學、數學、神經學、心理學、經濟學、統計學等層面,也有許多相關的學門:

 如何使用 Python 學習機器學習(Machine Learning)

隨著運算資源(雲端運算、GPU 等)、海量資料(目前還有許多資料還沒被創造,等待我們去發掘呢)以及機器學習/深度學習的發展,生活上許多產品已經可以看到人工智慧的應用。但人工智慧最美好的境界莫過於人機之間的互動以及相輔相成,以 AlphaGO 為例,雖然人類在圍棋領域輸給人機器,但也從機器的思考方式去重新思考了圍棋的真諦和有別於人類的思考方式。

「就因為某樣東西思考的方式跟你不一樣,就代表它沒在思考嗎?」 "Just because something thinks differently from you, does it mean it’s not thinking?" ---《模仿遊戲》《Imitation Game》(2015)

 如何使用 Python 學習機器學習(Machine Learning)

什麼是機器學習(Machine Learning)?

機器學習是一種資料科學的技術也是一種實現人工智慧的一種方式,協助電腦從現有的資料學習,以便預測未來的行為、結果和趨勢。根據學習的方式又可以分為需要解答的監督式學習(Supervised learning)非監督式學習(Unsupervised learning)增強學習(Reinforcement learning)等(還有一種混合式的半監督式學習)等子類別。機器學習技術可以應用的範圍十分廣泛,總的來說機器學習可以解決以下幾種問題:

  1. 分類問題:這是 A 類 或 B 類嗎?

  2. 異常值判斷:這很奇怪嗎?

  3. 預測性分析:有多少?

  4. 分群問題:這是如何組織的?

  5. 增強學習協助決策:我接下來該怎麼辦?

當我們蒐集到相關、精確、連貫、足夠資料就可以挑選合適的演算法進行模型的的建置。

為什麼選擇 Python?

在資料科學和機器學習領域最重要的兩大程式語言就是 Python 和 R,Python 簡潔易學、應用範圍廣(不限於數據分析)且學習曲線平緩,適合作為第一個入門的程式語言,透過 pandas、SciPy/NumPy、sckikit-learn、matplotlib 和 statsmodels 可以進行數據分析的工作,適合工程任務和需要和網路應用程式整合的專案。至於 R 由於是統計學家開發的程式語言,則是擅長於統計分析、圖表繪製,常用於學術研究領域,建議也要有一定程度的掌握。一般情況下 Python 和 R 並非互斥,而是互補,許多資料工程師、科學家往往是在 Python 和 R 兩個語言中轉換,小量模型驗證、統計分析和圖表繪製使用 R,當要撰寫演算法和資料庫、網路服務互動等情況時在移轉到 Python。為了降低學習成本。

此外 Python 本身是一種通用語言,除了資料科學外也可以廣泛使用在網路開發、網站建置、遊戲開發、網路爬蟲等領域,當你需要整合系統產品服務時,可以擔任一站式的開發語言,更重要的是 Python 也可以當成膠水語言非常輕易和 C/C++ 等效能較佳的語言整合。簡而言之,Python 是一種簡潔易學但功能強大,值得投資的程式語言,所以我們這邊先使用 Python 進行介紹。

若對於 Python 和 R 比較,這邊有兩篇文章可以參考 数据科学界华山论剑:R与Python巅峰对决Which is better for data analysis: R or Python?

如何開始入門機器學習?

事實上,資料科學是個跨領域學門,在學習如何使用 Python 進行機器學習過程中通常必須掌握以下知識:

  • 機器學習演算法
  • Python 程式語言和資料分析函式庫
  • 線性代數/統計學等相關學門
  • 專業領域的領域知識(Domain Knowledge)

為了掌握以上三大領域知識(我們先把焦點放在機器學習核心技法,暫時忽略資料科學中對於領域知識的掌握),具體來說我們可以有以下步驟可以參考:

  1. 掌握基礎 Python 程式語言知識

    線上學習資源:

  1. 了解基礎數學/統計學和機器學習基礎知識
  1. 知道如何使用 Python 科學計算函式庫和套件

    推薦安裝 Anaconda,支援跨平台多種版本 Python,預設將數據分析、科學計算的套件裝好,自帶 spyder 編輯器、Jupyter Notebook(IPython Notebook),可以提供一個網頁版介面,讓使用者可以透過瀏覽器進行 Julia、Python 或 R 程式的開發與維護。

  1. 使用 scikit-learn 學習 Python 機器學習應用
  1. 運用 Python 實作機器學習演算法
  • 感知器
  • 決策樹
  • 線性迴歸
  • k-means 分群
  1. 實作進階機器學習演算法
  • SVM
  • KNN
  • Random Forests
  • 降低維度
  • 驗證模型
  1. 了解深度學習(Deep Learning)在 Python 的實作和應用

總結

以上整理了一些機器學習網路學習資源,若你累積一些小小經驗後,不妨挑戰一下 Kaggle 或是 KDD 測試一下自己的實力並累積更多數據分析的經驗。

延伸閱讀

  1. 7 Steps to Mastering Machine Learning With Python
  2. 人人都可成為資料科學大師!一整年的網路自學清單就在這了
  3. Analytics Vidhya
  4. 台灣資料科學年會
  5. 「2016 台灣資料科學愛好者年會」精彩資料總整理(持續更新中)
  6. 大數據會消失,資料科學不會!你該知道的資料科學第一堂課
  7. 如何選擇 Microsoft Azure Machine Learning 的演算法
  8. Microsoft Azure Machine Learning 機器學習服務文件
  9. Kdnuggets
  10. Bigdatafinance
  11. Using Python and R together: 3 main approaches
  12. 机器学习最佳入门学习资源
  13. 机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1)
  14. SIRAJ RAVAL'S DEEP LEARNING

(image via respondr

用 Python 自學程式設計:list、tuple、dict and set

· 閱讀時間約 6 分鐘

Python 自學程式設計:程式設計思維入門

Markdown 是一種輕量級的標記語言,最初為 John Gruber 所設計。Markdown 特色在於允許人們「使用易讀易寫的純文字格式編寫文件,然後轉換成有效的 HTML 文件」。簡而言之,Markdown 就是一種簡潔易懂的語法,讓我們可以專注在內容上,不用花時間思考外觀樣式,在透過轉換變成可以呈現在網頁上的 HTML 語法。目前在許多知名技術/開發者論壇或是開發者工具(例如:Github)、技術部落格工具都有支援 Markdown 語法。

什麼是 HTML?

在開始學習 Markdown 之前我們先來認識一下 HTML,畢竟 Markdown 最終還是要轉換成 HTML 這個網頁上內容結構的標準語法。HTML 中文稱作超文本標記語言(英文全名為 HyperText Markup Language,簡稱 HTML),是一種用於建立網頁的標準標記語言。

這樣講起來有點抽象,事實上我們每天在觀看瀏覽的網頁就是由一個個 HTML 所組成。所以我們可以透過瀏覽器的檢視原始碼功能去一窺目前網頁的 HTML 樣貌。

這邊我們使用 Google Chrome 瀏覽器當作範例,可以在畫面中點選右鍵 > 檢視原始碼(View Page Source):

就可以看到該網頁的 HTML 內容:

網頁來源:Wikipedia HTML 頁面

由於這個網頁已經有點複雜,因為它已經包含了 CSS 外觀樣式語法和 JavaScript 互動邏輯程式的部分,對於初學者來說比較難一眼理解。所以我們用一下範例來介紹 HTML 最基礎的部分:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是標題</h1>
<p>我是段落</p>
<a href="https://zh.wikipedia.org/zh-tw/Markdown">我是超連結</a>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/HTML.svg/200px-HTML.svg.png" alt="">
</body>
</html>

若是使用瀏覽器打開這個 HTML 網頁會呈現:

HTML 標籤語法每個標籤皆有其意義且大部分成對出現,標籤元素內可以設定屬性值。網頁元素主要放置於 <body></body> 中,<head></head> 內主要放置 meta data 設定檔案和放置引入的外觀樣式檔案、程式邏輯等。元素內可以透過設定屬性值(attribute)來宣告元素功能,以下 href="https://zh.wikipedia.org/zh-tw/Markdown" 代表點擊該連結會到該 wikipedia 網址。

<!-- href 是屬性,決定連結點擊後目的地 -->
<a href="https://zh.wikipedia.org/zh-tw/Markdown">我是超連結</a>

<!-- src 是屬性,決定載入圖片位置-->
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/HTML.svg/200px-HTML.svg.png">

元素包裹內容在內,代表標題元素:

<h1>我是標題</h1>

Markdown 常見語法教學

一般 Markdwon 段落以空白行分隔。若是序列則內容需要內縮(一個 tab)。

標題

是一级標題
=======

# 一級標題
## 二级標題

其 HTML 元素為:

<h1>是一级標題</h1>
<h1>一級標題</h1>
<h2>二级標題</h2>

效果如下:

是一级標題

一級標題

二级標題

文字

_斜體_
**粗體**
`等寬字型Monospace`

其 HTML 元素為:

<em>斜體</em>
<strong>粗體</strong>
<code>等寬字型Monospace</code>

效果如下:

斜體 粗體 等寬字型Monospace

多行程式碼

其 HTML 元素為:

<pre>
<code>
<span>print('hello world')</span>
</code>
</pre>

效果如下:

print('hello world code :)')

水平線

---

其 HTML 元素為:

<hr>

效果如下:


無序列表

* 張三
* 李四
* 王二

其 HTML 元素為:

<ul>
<li>張三</li>
<li>李四</li>
<li>王二</li>
</ul>

效果如下:

  • 張三
  • 李四
  • 王二

有序列表

1. 不論
2. 三七
3. 二十一

有序列表,其 HTML 元素為:

<ol>
<li>不論</li>
<li>三七</li>
<li>二十一</li>
</ol>

效果如下:

  1. 不論
  2. 三七
  3. 二十一

巢狀有序列表

1. 不論
- 第一
- 第二
- 第三
2. 三七
1. 第一
2. 第二
3. 第三
3. 二十一

有序列表,其 HTML 元素為:

<ol>
<li>不論
<ul>
<li>第一</li>
<li>第二</li>
<li>第三</li>
</ul>
</li>
<li>三七
<ol>
<li>第一</li>
<li>第二</li>
<li>第三</li>
</ol>
</li>
<li>二十一</li>
</ol>

效果如下:

  1. 不論
    • 第一
    • 第二
    • 第三
  2. 三七
    1. 第一
    2. 第二
    3. 第三
  3. 二十一

超連結

[連結文字](連結網址)

其 HTML 元素為:

<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/HTML.svg/200px-HTML.svg.png">連結文字</a>

效果如下:

連結文字

圖片

![文字屬性](Icon-pictures.png "文字標題")

其 HTML 元素為(少數沒有成對出現的元素標籤):

<img src="連結網址" alt="文字屬性" title="文字標題" />

效果如下:

圖片文字

注釋引用

> Markdown使用電郵用字元「>」來引用。

其 HTML 元素為:

<a href="連結網址">連結文字</a>

效果如下:

Markdown 使用電郵用字元「>」來引用。

表格

| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Text | Text | Text |

其 HTML 元素為:

<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Text</td>
<td>Text</td>
<td>Text</td>
</tr>
</tbody>
</table>

效果如下:

Column 1Column 2Column 3
TextTextText

總結

以上簡單介紹了:

  1. 什麼是 HTML?
  2. Markdown 常見語法教學

以上介紹了 HTML 和 Markdown 基礎語法的教學,透過 Markdown 這一種簡潔易懂的語法,我們可以更專注在內容創作上。對於一個自學程式設計新手而言,培養撰寫文章的習慣(例如:建立自己的技術部落格)是很重要的環節,不但可以累計自己經歷也可以強化記憶並幫助到需要的人。若是需要完整語法介紹可以參考markdown.tw,當然,只要多加練習就可以慢慢掌握 Markdown 語法的訣竅,進而喜歡這種簡潔的書寫方式。

參考文件

  1. Github Basic writing and formatting syntax
  2. markdown.tw
  3. markdown wiki

用 Python 自學程式設計:list、tuple、dict and set

· 閱讀時間約 5 分鐘

Python 自學程式設計:程式設計思維入門

在前一單元中我們了解了變數和 Python 世界物件的重要性,也介紹了簡單的資料型別,我們也有提到簡單資料型別(布林、整數、浮點數和字串)就像是原子一樣,而複雜資料型別就像是分子一樣,在這一單元中我們將更進一步了解 Python 複雜的資料型別以及如何操作它們。

串列 list 與元組 tuple

在程式語言中通常可以利用序列式方式去記錄資料,在 Python 中,我們使用 list 串列和 tuple 元組來儲存序列式資料。兩者最大的不同在於 tuple 是不可以改變的。

  1. 串列 list 串列是一連串順序性的元素組成,我們可以新增、讀取、刪除和修改串列,串列中可以有重複的元素。

    • 建立串列

    串列可以透過中括號或是使用 list 關鍵字來創建,裡面元素由逗號分隔

    my_list0 = []
    my_list1 = list()
    my_list2 = ['python', 'js', 'SQL']

    list('js')
    # ['j', 's']
    • 使用 index offset 和範圍來取得元素

    在電腦科學世界,index 通常是從 0 開始,-1 從結尾數回來:

    languages = ['python', 'js', 'go']
    languages[0] # python
    languages[1] # js
    languages[-1] # go

    範圍取值 [開始:結束(不含):間隔(default 1)]:

    languages = ['python', 'js', 'go']
    my_list2[0:1] # ['python']
    • append 元素到串列最後
    languages = ['python', 'js', 'go']
    languages.append('java')
    • extend 串連串列
    languages = ['python', 'js', 'go']

    languages.extend('c++') # ['python', 'js', 'go', 'c++']

    languages += ['ruby', 'c'] # ['python', 'js', 'go', 'c++', 'ruby', 'c']
    • insert 插入元素到位置上
    languages = ['python', 'js', 'go']
    languages.insert(0, 'java') # ['java', 'python', 'js', 'go']
    • del 刪除特定 index 值
    languages = ['python', 'js', 'go']

    del languages[-1] # ['python', 'js']

    • len() 元素長度
    len(['python', 'js', 'go']) # 3
    • in 檢查元素是否在串列
    'java' in ['python', 'js', 'go'] # False

    還有更多好用的方法,讀者可以進一步查詢使用: remove()index()count()join()、sort()、copy()

  2. 元組 tuple 元組可以視為不可改變的串列,使用方式如下:

    languages = python', 'js', 'go' # (python', 'js', 'go')
    tuple(['python', 'js', 'go'])

    元組比起串列好處:

    • 佔用空間較少
    • 可以當做字典的 key(因不可變)
    • 具名 tuple 可當做物件替代
    • 當做函式引數

字典 dict 和集合 set

  1. dict 在其他程式語言可能稱 {'key':'value'} 字典為關聯式陣列或是雜湊表,其用獨一無二不可變的鍵(布林、整數、浮點數、字串和串列)去對應值,字典通常是可變的,可以新增刪除、修改鍵值。

    • 創建 dict
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    dict([('name', 'python'), ('version', '3.5')])
    • 新增和取值
    languages = {}

    languages['name'] = 'python'

    print(languages['name']) # python
    • 合併
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    languages2 = {
    'name': 'js',
    'version': '6'
    }

    languages.update(languages2)
    • keys() 取得所有鍵、values() 取得所有值、items() 取得所有鍵值對
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    languages.keys() # ['name', 'version']
    languages.values() # ['python', '3.5']
    languages.items() # [('name', 'python'), ('version', '3.5')]
    • 使用 in 判斷 key 是否存在 dict
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    'name' in languages # True
  2. set 類似小學時候學習的數學集合,可以想成就是留下鍵值的 dict。由於 set 存不重複值。當你只想知道值是否存在就是使用 set 的時機,例如使用 in 來判斷值是否存在。

    • 建立 set
    languages = set()

    languages = {'python', 'js', 'python', 'go'}
    # {'python', 'js', 'go'}
    • 轉換成 set
    set('python') # {'p', 'y', 't', 'h', 'o', 'n'}
    set(['python', 'js']) # {'python', 'js'}
    set(('python', 'js')) # {'python', 'js'}
    • 使用 intersection 取交集,union 取聯集,difference 取差集
    languages1 = {'js', 'python', 'go'}
    languages2 = {'python', 'go', 'java'}
    languages1.intersection(languages2) # {'python', 'go'}
    languages1.union(languages2) # {'js', 'python', 'java', 'go'}
    languages1.difference(languages2) # {'js'}

整合在一起

回想一下,我們可以使用 [] 建立 list 串列,用 , 來創立 tuple 元組,使用 來建立字典。雖然建立方式不盡相同,但相同的是你都可以透過中括號來存取內容值:

languages0 = ['python', 'js'] # languages0[0]
languages1 = ('python', 'js') # languages1[0]
languages2 = {
'name': 'python',
'version': '3.5'
} # languages2['name']

總結

以上就是程式設計思維入門簡介,透過了解什麼是程式設計思維和不同語言的特性,我們將對於自學程式設計有更正確的認識。接下來我們將透過 Python 介紹程式設計的內涵和不同的應用情境。當然,網路上也有許多學習資源可以當做參考。

(image via mshcdn

延伸閱讀

  1. Python 官網
  2. JavaScript 程式設計新手村
  3. Python Web 程式設計入門實戰
  4. 非本科生,我想半路出家學寫程式,該如何開始?
  5. 自學程式設計學習資源懶人包

用 Python 自學程式設計:變數(variable)與資料型別(type)

· 閱讀時間約 7 分鐘

Python 自學程式設計:程式設計思維入門

在前一單元中我們了解了程式設計思維的概念和建立了 Python 的開發環境,在這一單元中我們將了解 Python 變數與資料型別以及如何操作字串。

電腦最初的用途就是一台超大台計算機

資料的儲存以及操作在程式設計中扮演非常重要的角色,因為最早的電腦程式就是一種大型的計算機(最早的電腦就稱為計算機),即便現在學校教授電腦科學概論往往都會把課程稱為計算機概論呢!在操作資料的過程中如何儲存資料就是非常重要的事情,一般而言資料儲存有分為暫時儲存的揮發性資料(儲存在記憶體中的變數資料)和持久性儲存的資料(例如:資料庫、檔案等),在這邊我們討論的是變數的資料。

在 Python 世界,所有東西都是物件

在 Python 世界中,所有東西都是物件,物件可以視為透明的箱子,裡面存了一些資料。物件會有自己的資料型別,決定它做什麼樣的操作。另外,又依據箱子內的值可否改變而分為不可變物件可變物件

在前面我們有提到資料可以儲存在記憶體中的變數,在 Python 中變數只是一種名稱,當給定值時不會將值複製,而是將名稱貼到給定的物件上(注意 Python 程式語言中的 = 是給定值,== 才是相等的意思)

談到資料,就不得不談一下資料型別(type),雖然在 Python 不用像 C 語言之類程式語言需要在變數前面定義資料型別(在 Python 中 class 類別和 type 類型幾乎代表同一件事情,class 類別則是定義物件的基礎),但物件的資料型別會影響資料操作,所以值得我們好好認識。在 Python 世界裡,可以分為以下幾種簡單資料型別(可以想像成化學課中的原子):

  1. bool 布林,分為 TrueFalse 通常用於條件判斷
  2. int 整數,例如: 10999999
  3. float 浮點數,係指有小數點的整數:1.2221.0e7 等同於 10 的 7 次方
  4. string 字串,一串文字字元

我們可以透過 type(物件) 去確認該物件的型別:

print(True)
print(101)
print(3.14)
print('happy coding')

另外一種是複雜資料型別(可以想像成是化學課中的分子),這個我們會在下一個單元做討論:

  1. list 串列,用於儲存一系列序列資料(可以儲存不同資料型別),類似於其他程式語言的陣列但更為強大
  2. tuple 元組,類似於 list 串列,但不同的是 tuple 給定元素後不能改變
  3. dict 字典,和串列很像但不在乎元素順序,而且不會使用 0,1,...等的序列 index 來選擇項目,反之我們必須宣告唯一的 key 鍵值來對應想儲存的 value 值
  4. set 集合,集合就像是被移除 value 值的字典,只有保留 key 鍵值,也就是說 set 的內容元素都必須是獨一無二的

物件又分可變和不可變物件

  1. 不可變物件(int, string, float, tuple),亦即若資料改變,會複製一份資料到新的記憶體空間然後資料更新,下面是一個簡單範例:

    i = 101 # 宣告一個變數將 i 便條紙貼到 101 物件
    j = 101 # 宣告一個變數將 j 便條紙貼到 101 物件
    print(id(101)) # 印出 101 物件 id,可以想成是記憶體位置
    print('i id:' + str(id(i))) # 印出 i 指向的 id,和 101 物件值相同
    print('j id:' + str(id(j))) # 印出 j 指向的 id,和 101 物件值相同
    print(i is j) # 因為兩者會貼到同一個物件所以會顯示相等,True
    j = j + 1 # 若資料改變,會複製一份資料到新的記憶體空間然後資料更新
    print('new i id:' + str(id(i))) # 印出一樣的 id
    print('new j id:' + str(id(j))) # 印出新的 id
    print(i is j) # 兩者指到不同的記憶體位置,False

    執行結果:

    140181136769920
    i id:140181136769920
    j id:140181136769920
    True
    new i id:140181136769920
    new j id:140181136769952
    False
  2. 可變物件(list, dict, set),亦即若資料改變則直接在指向的記憶體空間改變資料,下面是一個簡單範例:

    a = {} # 宣告一個變數指到一個空字典 dict
    b = a # 將 b 變數指到 a 同樣記憶體位置
    print(id(a)) # 印出 a 的 id
    print(a is b) # 兩者指到相同的記憶體位置,True
    a['a'] = 'python' # 改變 a 的鍵值
    print('id a:' + str(id(a))) # 印出 a id
    print('a:' + str(a)) # 印出內容值
    print('id b:' + str(id(b))) # 印出 b id,dict 為可變物件,印出 id 會和 a 一樣
    print('b:' + str(b)) # dict 為可變物件,印出內容值會和 a 一樣
    print(a is b) # 兩者指到相同的記憶體位置,True

    執行結果:

    140181112792336
    id a:140181112792336
    a:{'a': 'python'}
    True
    id b:140181112792336
    b:{'a': 'python'}
    True

另外,Python 支援強制轉換資料型別: 可以透過 int()、float()、str() 進行資料型別轉換

int(1.2)
float('1.3')
str('1')

字串操作好好玩

在程式設計的世界中,操作字串基本上是家常便飯,接著我們來談談在 Python 中如何進行字串的操作:

在 Python 中若要宣告字串,可以使用單引號或雙引號,會有兩種方式是因為讓開發者可以產生有 '" 內容的字串。

my_str = 'This is a "good" language!'

但要特別留意的是在 Python3 和 Python2 對於字串的支援不盡相同,在 Python 中支援 Unicode 標準。與其他程式語言不同的是 Python 字元是不可變的,不能直接改變字串,但可以將一部分字串複製到其他字串。

以下是常見字串操作方式:

  1. 宣告字串

    language = 'python'
  2. 串連字串 +

    language = 'python'
    word = 'I love'
    word + language
  3. 複製字串 *

    language = 'python'
    language * 3
  4. 選取字串 [開始:結束:間隔]

    language = 'python'
    language[0:1] # p
    language[0:-1] # pytho
    language[0:4:2] # ph
  5. len、split、join、replace 字串操作

    language = 'python'
    print(len(language)) # 印出字串長度 6
    print(language.split(3)) # 切割字串長度
    print(language.join(3)) # 切割字串長度
    print(language.replace(3)) # 切割字串長度

總結

以上我們介紹了在 Python 世界中物件是基本元素,也介紹了變數以及字串的操作,接下來我們將透過 Python 介紹程式設計的內涵和不同的應用情境以及複雜資料型別的使用。

(image via mshcdn

延伸閱讀

  1. Python 官網
  2. JavaScript 程式設計新手村
  3. Python Web 程式設計入門實戰
  4. 非本科生,我想半路出家學寫程式,該如何開始?
  5. 自學程式設計學習資源懶人包
  6. python可变和不可变对象

用 Python 自學程式設計:程式設計思維入門

· 閱讀時間約 14 分鐘

Python 自學程式設計:程式設計思維入門

最近幾年全球刮起了一股爭相學習電腦科學(Computer Science)和程式設計(Programming)的風氣,上至總統、首相下至升斗小民都爭相開始學寫程式。事實上,學寫程式最重要的是學習電腦科學背後思考方式和邏輯,學習如何透過科技解決生活上的問題。更進一步說,程式設計與其說是一種科學,更偏向一種藝術人文的創作與科學的混合體。以前畫家或是作家是拿紙筆創作,現在只要有一部電腦,連上網路,就可以透過敲打鍵盤將自己的創意付諸實踐。

有人說:程式設計 = 演算法 + 資料結構

這樣的說法不能說錯。事實上,具備良好資料結構和演算法素養的程式設計師往往可以寫出品質較好的程式碼,但大部分人看到演算法和資料結構就已經滿臉問號了,更別提曾經在學校被這兩門課程心靈受挫的學生們。所以對於初學者來說,更應該讓他了解,事實上學程式設計思維就是在學習解決問題的能力:

  1. 尋找並發現問題
  2. 釐清並定義問題
  3. 分解問題
  4. 尋找解決方法和資源
  5. 驗證問題和解決方式

唯有具備這樣解決問題的能力,才能稱得上真正學會程式設計思維。而這樣的思考方式的訓練是不管將來到哪裡,是否有從事程式設計相關工作都受用,這才是對於學習電腦科學與程式設計思維正確的認知。

寫程式就是下指令請電腦做事情

剛剛我們在上面提到程式設計思維中有一個部分是分解問題,事實上,寫程式在定義問題後,我們必須把問題切分,就像是食譜一樣,不管是再豐盛的料理或是滿漢全席,都有一個個步驟去完成。舉例來說,我們今天要創作一道蔥花蛋或菜脯蛋,我的步驟會是:

  1. 放點油
  2. 打蛋
  3. 如果喜歡蔥花可以加入蔥花,如果喜歡菜脯可以加入菜脯(程式術語:if...else 條件判斷)
  4. 放入少許鹽巴
  5. 中火快炒,翻五次面(程式術語:for 迴圈)
  6. 當看到蛋面呈現金黃色時可以起鍋,結束料理(程式術語:while 迴圈)
  7. 好吃的蔥花蛋或菜脯蛋上桌

再大程式切分後就變成一個個小程式和指令,將程式切分成一個個模組,再將它們都組裝起來就成我們的應用程式和系統。

第一次學寫程式,學哪一種語言好呢?

既然程式設計思維很重要,究竟第一次學寫程式,學哪一種語言好呢?

先講結論:Python 語法平易近人,學習曲線平緩,應用廣,可以很快做出一些解決生活上問題的應用,累積成就感,適合初學者。當然若你是國中小的學生,Scratch 之類的拖拉式圖象化程式語言或許是合適選擇,但成人一般對於這種玩具比較排斥些,認為不是真正在學寫程式。

一般而言除了區分高低階程式語言外,我們會把程式語言分為:

靜態語言:在程式語言中我們會使用變數(variable)儲存程式的值,在靜態語言中需要事先宣告變數型態(type),也宣告了它會在記憶體中佔有多少空間等資訊。電腦會透過這些資訊把程式編譯(compile)成低階的機器語言讓電腦可以執行。這樣的設計可以讓電腦執行起來更有效率,但對於開發者來說會比較繁瑣一些(例如:宣告字串變數要在變數前加 string 宣告),也由於類型被宣告後無法改變,所以被稱為靜態語言。常見的靜態語言包括:C/C++、Java、C#、Go、Swift 等)。

動態語言(又稱為 script language):相對於靜態語言,動態語言不會強制變數類型宣告,它不是使用編譯器而是使用直譯器(interpreter)來解譯。動態語言雖然開發和撰寫程式上效率較快,但執行速度往往比靜態語言慢(現在差距已經慢慢變小)。一般常見的動態語言包括:Python、JavaScript、PHP、Ruby 等)。

以下就來先簡單介紹常見程式語言和它的簡單語法範例(可以透過 repl.it 可以將程式碼貼在網頁上呈現所見即所得效果):

  1. Python 本系列文章的主角,Python 是一種物件導向、直譯式的跨平台動態程式語言,它包含了一組功能完備的標準庫和豐富套件生態系,可以輕鬆完成很多常見的任務(例如:物聯網應用開發、遊戲、讀寫檔案、自然語言處理、網路爬蟲、網站開發、機器學習等),因為它可以很輕易整合其他底層語言,所以又稱為膠水語言。它的語法簡單,與其它大多數程式設計語言使用大括弧不一樣,它使用縮進來定義語句塊。由於具備簡潔易學等特性,是許多開發者推薦 Python 為初學者第一個學習的程式語言。由於版本更迭,我們接下來討論的主要是以 Python3 為主。以下是使用 Python 印出最喜歡的語言:

    language = 'Python'
    print('My favorite Language is {}'.format(language))
  2. C 經典的傳統主力程式語言,適用於需要效能重視速度的應用,可以操作許多小細節,但學習門檻稍微高一些,執行前需要事先編譯完成:

    #include <stdio.h>
    int main(int atgc, char *argv[]) {
    string language = "C++";
    printf("My favorite Language is %s", language);
    return 0;
    }
  3. C++ 屬於 C 家族成員,具備物件導向特性,同樣是適用於需要效能重視速度和操作底層韌體、硬體的好選擇:

    #include <iostream>
    using namespace std;
    int main() {
    string language = "C++";
    cout << "My favorite Language is " << language;
    return(0);
    }
  4. Java 常見於企業系統和 Android 行動應用開發的 Java 是物件導向程式語言,由於跨平台開發等特性讓 Java 一直是市場蠻熱門的語言。

    public class CodeLanguage {
    public static void main(String[] args) {
    string language = "Java";
    System.out.format("My favorite Language is %s", language);
    }
    }
  5. C# 由微軟推出吸收了 C++/Java 等優點的物件導向程式語言,常見於開發微軟平台相關的應用程式。

    using System;
    namespace CodeLanguage {
    class CodeLanguage {
    static void Main() {
    string language = "C#";
    Console.WriteLine("My favorite Language is {}", language);
    }
    }
    }
  6. JavaScript 隨著版本演進和 Node.js 的推出後從玩具語言到可以挑大樑的程式語言,應用範圍遍及網頁前後端開發、遊戲開發、物聯網程式開發、手機程式開發等。是程式設計師社群平台 Github 和程式問答平台 StackOverflow 上最受歡迎的程式語言之一。且由於應用範圍廣泛,程式江湖更傳言:可以使用 JavaScript 編寫的程式,最終都會出現 JavaScript 版本。

    var language = 'JavaScript'
    console.log('My My favorite Language is ' + language);
  7. PHP 吸收了 C/Java/Perl 特點的網站開發主力語言,世界上有許多的網站都是使用 PHP 進行開發。

    <?php
    $language = 'PHP';
    echo 'My favorite Language is ' + language;
    ?>
  8. Ruby 常見於網頁 Web 開發,以 Ruby on Rails Web 開發框架聞名於程式設計社群。

    language = 'Ruby'
    puts 'My favorite Language is #{language}'
  9. Swift 由 Apple 推出的推出的程式語言,主要用於開發 iOS/Mac 系列產品,應用範圍也涉及到了伺服器端開發(Server)。

    let language = 'Swift'
    print("My favorite Language is ", language)

  10. Go 由 Google 推出的程式語言,適合用於平行化程式開發。

    package main
    import "fmt"

    func main() {
    language := 'Go'
    fmt.Printf("My favorite Language is %s", language)
    }

看完了眾多語言是不是發現其實 Python 語法還蠻可愛平易近人的呢?事實上,世界上沒有最好的程式語言,只有最適合的使用地方。接下來我們將透過 Python 學習程式設計思維。

Python 環境建置

在開始之前我們必須先建置相關的開發環境,讓自己從麻瓜(不會寫程式的人)變成擁有程式魔力的魔法師。

所謂工欲善其事,必先利其器,要開發好的應用程式必須先準備好開發環境才行。以下介紹我們在接下來開發 Python Flask Web 應用程式所需要安裝的開發環境工具(以下以 Mac OS 等 Unix-like 作業系統為示範,若是 Windows 使用者建議安裝 Virtualbox 並運行 Linux Ubuntu 作業系統,參考安裝文件):

  1. Microsoft VSCode 編輯器 Microsoft VSCode 是 Microsoft 推出的編輯器(非整合開發環境 IDE),夾帶著 Microsoft 過去打造 Visual studio 整合開發環境的豐富經驗,相比 Sublime Text 和其他編輯器,VSCode 的優勢在於開源且活躍的開發社群、內建 debugger 框架、原生 Git 整合、套件整合容易等特性。所以對於初學者來說 VSCode 是一個蠻適合入門的開發環境。它的安裝方式也十分簡易,在官網下載後按照指示安裝完成即可。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    我們可以安裝 Python 語法和格式檢查的相關 Python 套件幫助除錯:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

  2. 終端機環境(iTterm/內建 terminal) terminal(終端機)是我們下指令的地方,許多時候我們進行程式開發時不會使用 GUI 的介面而是使用下指令方式請電腦做相對應的行為。在 Linux 和 Mac 裡面都有內建的 terminal 的應用程式,若你是 Mac 用戶想使用更便利的工具(分割視窗、熱鍵、搜尋、自動補完等)可以額外安裝 iterm2 做使用。若是不想使用 Virtualbox,使用 Windows 讀者可以使用 Cmder 這個軟體當做終端機環境。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    下指令($ 為提示字元,不用輸入):

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    對於有志於從事程式開發相關工作的讀者建議可以多熟悉指令碼的輸入,更多指令碼可以參考鳥哥撰寫的 Linux 基本指令介紹Linux 學習資源

  3. Git 版本控制系統/註冊 GitHub 帳戶 Git 是一種分散式版本控制系統,可以讓我們可以更方便地管理我們的程式碼。在網路上有非常多優秀的 Git 教學文件(連猴子都能懂的Git入門指南寫給大家的 Git 教學初心者 Git 上手攻略)。安裝 Git 方式是到官網下載軟體,依照指示安裝。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    互動式語法學習:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    在介紹完 git 之後我們來了解一下 GitHub。GitHub 是一個可以存放 git 程式碼專案的平台,透過 GitHub 我們可以接觸到最新的開放原始碼資訊,也可以將我們的程式碼開源出來。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    從 GitHub 上複製程式碼

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    # 複製一份到本地端
    $ git clone https://github.com/happycoderorg/flask101.git
    # 移動到資料夾
    $ cd flask101

    常見 Git 指令:

    # 初始化專案
    $ git init
    # 查看狀態
    $ git status
    # 檢查差異
    $ git diff
    # 將變更檔案放入暫存區
    $ git add index.py
    # 使用 commit -m 提交變更
    $ git -a -m 'init commit'
    # 查看歷史
    $ git log
    # 放棄已經 commit 的檔案重回暫存區
    $ git reset HEAD index.py
    # 放棄檔案變更
    $ git checkout index.py
  4. Anaconda Python3 版本 Anaconda 是一個 all-in-one 的 Python 開發環境,對於初學者來說是個十分合適的開發環境包。Anaconda 具備了幾項特點:

    • 便於安裝許多流行的科學、數學、工程、數據分析的 Python 模組
    • 開源和免費
    • 跨平台支持:Linux、Windows、Mac
    • 支持 Python 版本切換,方便建立不同的虛擬開發環境
    • 內建 Spyder 編輯器和 Jupyter Notebook 環境

    安裝流程也十分簡單,進入 Anaconda 首頁,選擇對應作業系統(這邊使用 Mac OS): Python Web Flask 實戰開發教學 - 簡介與環境建置

    選擇對應 Python 版本下載,我們使用 Graphical Installer(圖像介面安裝方式),接著在下載完成時按照預設的安裝方式完成安裝; Python Web Flask 實戰開發教學 - 簡介與環境建置

    若是完整安裝成功,可以打開終端機輸入,若是顯示 Python 3.6.0 :: Anaconda 4.3.0 (x86_64) 版本號即安裝成功:

    $ python -V
    Python 3.6.0 :: Anaconda 4.3.0 (x86_64)

    接著要建立我們專案虛擬環境,這樣在安裝操作套件時比較不容易被污染到 root 的環境,啟動後會出現(套件名稱)的提示字元:

    # 顯示目前虛擬環境列表
    $ conda info -e
    # 創建虛擬環境
    $ conda create -n 套件名稱 python=3.6
    # 進入虛擬環境(若是 Windows cmder 環境不用加 source) ,成功後提示字元變成:(套件名稱)$
    $ source activate 套件名稱
    # 離開虛擬環境(若是 Windows cmder 環境不用加 source)
    $ source deactivate

建立虛擬環境

在建立相關開發工具後我們正式來建立一個 Python 的專案:

打開終端機移動到桌面,建立專案資料夾

$ cd ~/Desktop
$ mkdir python_examples
$ cd python_examples

建立獨立虛擬環境,並進入虛擬環境:

$ conda create -n python_examples_venv python
$ source activate python_examples_venv

成功進入虛擬環境後

你的第一個 Python 程式

一般而言我們會使用編輯器或是整合開發環境(IDE)進行程式撰寫,然後在終端機下指令執行程式。當然你也可以在終端機上使用內建互動式介面或是 jupyter notebook 進行。以下是我們要介紹給大家的簡單範例,第一個是隨機印出不同的喜愛程式語言,第二個是使用第三方套件擷取政府公開資料。程式設計唯有動手實際操作和實踐才能學的好,希望讀者打開你的編輯器透過自己實作去熟悉 Python 程式撰寫:

隨機印出不同的喜愛程式語言:

  1. 引入 random 套件
  2. 定義 language 變數,並將儲存程式語言字串的串列(list)資料結構給定給變數
  3. 產生 1 到 2 之間的隨機整數
  4. 列印出最喜歡的程式語言字串(含根據隨機產生的 index 選取到的串列值)
import random

language = ['Python', 'JavaScript', 'Java']
rnd = random.randint(1, 2)
print('My favorite Language is' + language[rnd])

可以在終端機移動到檔案資料夾執行程式檔案,例如:

python favorite_language.py

使用第三方套件擷取政府公開資料:

  1. 引入 requests 套件
  2. 爬取政府公開 Wifi 熱點資料,將取得資料回應給定給 response 變數
  3. 將資料轉換成以 { "key": "value "} 形式的 json 格式
  4. 印出取得的資料
import requests

url = 'http://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=b087af42-2c54-4dbf-86c8-427d788779e5'
response = requests.get(url)
data = response.json()
print(data)

總結

以上就是程式設計思維入門簡介,透過了解什麼是程式設計思維和不同語言的特性,我們將對於自學程式設計有更正確的認識。接下來我們將透過 Python 介紹程式設計的內涵和不同的應用情境。當然,網路上也有許多學習資源可以當做參考,若你需要先建立基本的電腦科學知識的話,可以參考哈佛大學的熱門公開課程 CS50

(image via mshcdn

延伸閱讀

  1. Python 官網
  2. JavaScript 程式設計新手村
  3. Python Web 程式設計入門實戰
  4. 非本科生,我想半路出家學寫程式,該如何開始?
  5. 自學程式設計學習資源懶人包
  6. CS50
  7. CS50 TV

Python Web Flask 實戰開發教學 - SQLAlchemy 與 ORM

· 閱讀時間約 8 分鐘

Python Web Flask 實戰開發教學

Web 開發涉及層面很廣,包含了前後端開發、資料庫優化、平行處理、負載平衡、高可用性、資訊安全、雲端伺服器部屬等議題,本系列文章將透過介紹 Python Web Flask 實戰開發來學習現代化網站開發的方方面面。上一篇我們完成了環境建置,這一單元我們將進入 MVC 架構的 Models 部分並學習如何使用 SQLAlchemy 建立和資料庫互動的 ORM 機制。

Python Web Flask 實戰開發教學

什麼是 MVC?

MVC 模式(Model–view–controller)是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。

  • 控制器(Controller)- 對 Request/Response 進行處理並透過 Controller 把 Model 的資料串接到 View(Templates)。
  • 視圖(View) - 直接面對使用者的使用者介面設計。
  • 模型(Model) - 負責和資料庫互動,儲存資料。

使用 MVC 的好處在於可以用更高階的角度去思考整個程式架構提高程式可重用性和降低程式耦合性。 事實上 Django、Rails 和 ASP.NET MVC 等較成熟的 Web 框架也是參考 MVC 的架構去設計。

什麼是關聯式資料庫(RDB)?

Database 資料庫一個資料儲存的集合,方便我們去讀取新增刪除修改,而 Relational Database(關聯式資料庫)廣泛應用資料庫應用程式中,它把資料儲存在行列表格中,有可能不同資料表的內容會彼此依賴關聯。常見的關聯式資料庫,例如:MySQL、Postgres、Oracle、MSSSQL、SQLite,本文我們將使用 SQLite 這個輕量級的關聯式資料庫來當做範例教學。

什麼是 ORM?

ORM 指的是 Object Relational Mapping(物件關聯對應),是一種程式設計技術,用於實現物件導向程式語言裡不同類型系統的資料之間的轉換。一般而言物件導向是從軟體工程基本原則(例如:耦合、聚合、封裝)的基礎上發展起來的,然而關聯式資料庫則是從數學理論發展而來的,兩套理論存在顯著的區別。為了解決這個不符合的現象,物件關聯對映技術搬演著中介層的角色,讓開發可以使用物件方式來操作資料庫,而不用使用 SQL 語法,當然若是要使用複雜的操作,仍需要使用到 SQL 語法。

更多 SQL 語法學習:SQL語法教學- 1Keydata

Python Web Flask 實戰開發教學

Flask SQLAlchemy 使用設定

SQLAlchemy 是 Python 社群最廣泛使用的 ORM 套件。為了方便使用 ORM 來操作資料庫,我們使用 SQLAlchemy 的封裝 Flask SQLAlchemy 來進行 Models 的建立(當然你也可以單獨使用 SQLAlchemy)。以下是 SQLAlchemy 使用的簡單範例:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 設定資料庫位置,並建立 app
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
# 建立資料表欄位
from main import db

class Todo(db.Model):
# __table__name = 'user_table',若不寫則看 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(80))

def __init__(self, content):
self.content = content

def __repr__(self):
return '<Todo %r>' % self.content
from flask_script import Manager, Server
from main import app
from models import Todo

# 設定你的 app
manager = Manager(app)
# 設定 python manage.py runserver 為啟動 server 指令
manager.add_command('runserver', Server())

# 設定 python manage.py shell 為啟動互動式指令 shell 的指令
@manager.shell
def make_shell_context():
return dict(app=app, Todo=Todo)

if __name__ == '__main__':
manager.run()

操作指令:

$ python manage.py shell
>>> db.create_all()

CRUD 操作設計

CRUD 是一般網路應用程式最常見的資料庫操作(create, read, update, delete),接著我們要使用 session 來操作我們的 CRUD 功能,首先先在終端機中輸入 $ python manage.py shell 後進行資料庫指令模擬操作(要注意的是 Flask SQLAlchemy 針對每個 request 會創建一個新的 session,若沒有 commit 的操作即被丟棄):

  1. 新增(Create) 新增一筆資料後將它加到 db.session 中,完成 commit:

    >>> todo = Todo(content='hacking')
    >>> db.session.add(todo)
    >>> db.session.commit()

2. 讀取(Read)
Model.query 是 db.session.query(Model) 的簡寫,所以我們可以使用以下方式讀取資料庫資料:

取得所有 todo 資料

todos = Todo.query.all() todos

限制 1 筆資料

todos = Todo.query.limit(1).all()

正向/逆向排序

todos = Todo.query.order_by(Todo.content).all() todos = Todo.query.order_by(Todo.content.desc()).all()

取得第一筆資料

todo = Todo.query.first()

取得 primary key=1 一筆資料

todo = Todo.query.get(1)


- 分頁(Pagination)

todos = Todo.query.paginate(1, 10)

總頁數

todos.pages

上/下一頁

todos.prev() todos.next()


- 條件查詢(Filter)

todo = Todo.query.filter_by(content='hacking').first()

todos = Todo.query.filter(Todo.id > 1).all()


3. 修改(Update)

```python
todo = Todo.query.filter_by(contant='hacking').update({
'content': 'reading'
})
db.session.commit()
  1. 刪除(Delete)

    >>> todo = Todo.query.filter_by(content='reading').first()
    >>> db.session.delete(todo)
    >>> db.session.commit()

資料庫關聯用法

在關聯式資料庫中,最重要的就是資料表之間的關聯,透過關聯的使用,可以讓我們取得我們想要的資料。舉例而言,一篇部落格文章通常會對應多則評論,所以若是建立好關係則可以透過文章去取得所有和這篇文章有關的評論。同理,一篇文章通常會有多個 tag,而一個 tag 通常對應多篇文章,所以是個多對多關係。

  • 一對多
# 建立資料表欄位
from main import db

class Todo(db.Model):
# __table__name = 'user_table',若不寫則看 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(80))
user_id = db.Column(db.String(80), db.ForeignKey('user.id))

def __init__(self, content):
self.content = content

def __repr__(self):
return '<Todo %r>' % self.content

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
todos = db.relationship(
'Todo',
backref='user', # ref 可以讓我們使用 Todo.user 進行對 User 操作
lazy='dynamic' # 有使用才載入,提昇效能
)

def __init__(self, name):
self.name = name

def __repr__(self):
return '<User %r>' % self.name

操作方式:

>>> user = User.query.get(1)
>>> new_todo = Todo('Booking')
>>> new_todo.user_id = user.id
>>> db.session.add(new_todo)
>>> db.session.commit()
>>> user.todos
  • 多對多
tags = db.Table('todo_tags',
db.Column('todo_id', db.Integer, db.ForeignKey('todo.id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'))
)

# 建立資料表欄位
from main import db

class Post(db.Model):
# __table__name = 'user_table',若不寫則看小寫 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))
content = db.Column(db.String(80))

def __init__(self, title, content):
self.title = title
self.content = content

def __repr__(self):
return '<Todo %r>' % self.content

class Tag(db.Model):
# __table__name = 'user_table',若不寫則看 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))

def __init__(self, title):
self.title = title

def __repr__(self):
return '<Tag %r>' % self.title

操作方式:

# 創建 3 個 todo
>>> todo_1 = Todo('Python')
>>> todo_2 = Todo('JS')
>>> todo_3 = Todo('R')

>>> tag_1 = Tag('coding')
>>> tag_1.tags = [todo_1, todo_2]
>>> db.session.add()
>>> db.session.commit()

Python Web Flask 實戰開發教學

Flask Migration(Alembic)使用

隨著網路應用程式的發展,我們的 models 會不斷變更,為了記錄所有有關 models 的改動,我們使用 Flask-Migrate 這個 extensions。所有 models 改動都會記錄在 migration 檔案中,就像是資料庫的 git 一樣方便版本控制。

安裝 Flask-Migrate

$ pip install Flask-Migrate

將 db 加入 Flask-Migrate 控制:

from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager, Server
from main import app
from models import Todo

# 設定你的 app
manager = Manager(app)
# 設定 python manage.py db 來管理 models
manager.add_command('db', MigrateCommand)
# 設定 python manage.py runserver 為啟動 server 指令
manager.add_command('runserver', Server())

# 設定 python manage.py shell 為啟動互動式指令 shell 的指令
@manager.shell
def make_shell_context():
return dict(app=app, Todo=Todo)

if __name__ == '__main__':
manager.run()

使用 Flask-Migrate 操作 DB:

# 初始化
$ python manage.py db init
# 記錄 model 變化
$ python manage.py db migrate
# 更新同步到 db
$ python manage.py db upgrade
# 查詢指令
$ python manage.py db --help

總結

本文介紹了資料庫、關聯式資料庫、ORM 的概念,我們也實際使用了 Flask SQLAlchemy 和 Flask-Migrate 來操作我們的資料庫。在接下來章節中我們將持續介紹 Python Web Flask 實戰開發,並學習現代化網站開發的方方面面。

延伸閱讀

  1. Wiki MVC
  2. Python Web 程式設計入門實戰線上課程

(image via basicsofwebdevelopment

Python Web Flask 實戰開發教學 - 簡介與環境建置

· 閱讀時間約 10 分鐘

Python Web Flask 實戰開發教學 - 簡介與環境建置

Web 開發涉及層面很廣,包含了前後端開發、資料庫優化、平行處理、負載平衡、高可用性、資訊安全、雲端伺服器部屬等議題,本系列文章將透過介紹 Python Web Flask 實戰開發來學習現代化網站開發的方方面面。一開始先從簡介和環境建置開始吧!

什麼是 Python?

Python 是一種物件導向、直譯式的跨平台電腦程式語言,它包含了一組功能完備的標準庫和豐富套件生態系,可以輕鬆完成很多常見的任務(例如:讀寫檔案、自然語言處理、網路爬蟲、網站開發、機器學習等),因為它可以很輕易整合其他底層語言(例如:C/C++ 等),所以又稱為膠水語言。它的語法簡單,與其它大多數程式設計語言使用大括弧不一樣,它使用空白縮進來定義語句塊。由於具備簡潔易學等特性,許多開發者推薦 Python 為初學者第一個學習的程式語言。由於版本更迭,我們接下來討論的主要是以 Python3 為主,若電腦沒有安裝的話,你可以在官方網站下載,若你不是安裝 Anaconda 這個 all-in-one 版本的話(自帶許多套件和科學運算工具,也可以建立虛擬開發環境),記得要安裝 pipIPython

接下來我們將以 Anaconda 這個開發環境為主要講解環境。由於我們假定讀者已經有一些 Python 基礎,所以我們會跳過有關 Python 語法的基本較邵,若您對於 Python 入門基礎較不熟悉的話建議參考 Python 101 快速入門教學 ,此外我們也提供了 Python Web 程式設計入門實戰線上課程 可以參考。那就讓我們開始吧!

什麼是 Flask?

Python Web Flask 實戰開發教學 - 簡介與環境建置

Flask 是一個使用 Python 撰寫的輕量級 Web 應用程式框架,由於其輕量特性,也稱為 micro-framework(微框架)。Flask 核心十分簡單,主要是由 Werkzeug WSGI 工具箱Jinja2 模板引擎所組成,Flask 和 Django 不同的地方在於 Flask 給予開發者非常大的彈性(當然你也可以說是需要思考更多事情),可以選用不同的用的 extension 來增加其功能。相比之下,Django 雖然完善但技術選擇相對不彈性,不論是 ORM、表單驗證或是模版引擎都有自己的作法。事實上沒有最好的框架,只有合適的使用情境,Django 相比之下適合需要快速的開發大型的應用程式,和 Ruby 中的 Ruby on Rails 相似,而 Flask 則是相對輕量彈性,更像是 Ruby 界的 Sinatra。若讀者想先體驗看看 Flask 的程式狀況,以下是 Flask 簡易運行的程式,啟動測試伺服器後,可以在瀏覽器中(http://localhost:5000/)印出 Hello World!

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
return "Hello World!"

if __name__ == "__main__":
app.run()

Python Web 開發環境建置

所謂工欲善其事,必先利其器,要開發好的應用程式必須先準備好開發環境才行。以下介紹我們在接下來開發 Python Flask Web 應用程式所需要安裝的開發環境工具(以下以 Mac OS 等 Unix-like 作業系統為示範,若是 Windows 使用者建議安裝 Virtualbox 並運行 Linux Ubuntu 作業系統,參考安裝文件):

  1. Microsoft VSCode 編輯器 Microsoft VSCode 是 Microsoft 推出的編輯器(非整合開發環境 IDE),夾帶著 Microsoft 過去打造 Visual studio 整合開發環境的豐富經驗,相比 Sublime Text 和其他編輯器,VSCode 的優勢在於開源且活躍的開發社群、內建 debugger 框架、原生 Git 整合、套件整合容易等特性。所以對於初學者來說 VSCode 是一個蠻適合入門的開發環境。它的安裝方式也十分簡易,在官網下載後按照指示安裝完成即可。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    我們可以安裝 Python 語法和格式檢查的相關 Python 套件幫助除錯:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

  2. 終端機環境(iTterm/內建 terminal) terminal(終端機)是我們下指令的地方,許多時候我們進行程式開發時不會使用 GUI 的介面而是使用下指令方式請電腦做相對應的行為。在 Linux 和 Mac 裡面都有內建的 terminal 的應用程式,若你是 Mac 用戶想使用更便利的工具(分割視窗、熱鍵、搜尋、自動補完等)可以額外安裝 iterm2 做使用。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    下指令($ 為提示字元,不用輸入):

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    對於有志於從事程式開發相關工作的讀者建議可以多熟悉指令碼的輸入,更多指令碼可以參考鳥哥撰寫的 Linux 基本指令介紹Linux 學習資源

  3. Git 版本控制系統/註冊 GitHub 帳戶 Git 是一種分散式版本控制系統,可以讓我們可以更方便地管理我們的程式碼。在網路上有非常多優秀的 Git 教學文件(連猴子都能懂的Git入門指南寫給大家的 Git 教學初心者 Git 上手攻略)。安裝 Git 方式是到官網下載軟體,依照指示安裝。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    互動式語法學習:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    在介紹完 git 之後我們來了解一下 GitHub。GitHub 是一個可以存放 git 程式碼專案的平台,透過 GitHub 我們可以接觸到最新的開放原始碼資訊,也可以將我們的程式碼開源出來。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    從 GitHub 上複製程式碼

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    # 複製一份到本地端
    $ git clone https://github.com/happycoderorg/flask101.git
    # 移動到資料夾
    $ cd flask101

    常見 Git 指令:

    # 初始化專案
    $ git init
    # 查看狀態
    $ git status
    # 檢查差異
    $ git diff
    # 將變更檔案放入暫存區
    $ git add index.py
    # 使用 commit -m 提交變更
    $ git -a -m 'init commit'
    # 查看歷史
    $ git log
    # 放棄已經 commit 的檔案重回暫存區
    $ git reset HEAD index.py
    # 放棄檔案變更
    $ git checkout index.py
  4. Anaconda Python3 版本 Anaconda 是一個 all-in-one 的 Python 開發環境,對於初學者來說是個十分合適的開發環境包。Anaconda 具備了幾項特點:

    • 便於安裝許多流行的科學、數學、工程、數據分析的 Python 模組
    • 開源和免費
    • 跨平台支持:Linux、Windows、Mac
    • 支持 Python 版本切換,方便建立不同的虛擬開發環境
    • 內建 Spyder 編輯器和 Jupyter Notebook 環境

    安裝流程也十分簡單,進入 Anaconda 首頁,選擇對應作業系統(這邊使用 Mac OS): Python Web Flask 實戰開發教學 - 簡介與環境建置

    選擇對應 Python 版本下載,我們使用 Graphical Installer(圖像介面安裝方式),接著在下載完成時按照預設的安裝方式完成安裝; Python Web Flask 實戰開發教學 - 簡介與環境建置

    若是完整安裝成功,可以打開終端機輸入,若是顯示 Python 3.6.0 :: Anaconda 4.3.0 (x86_64) 版本號即安裝成功:

    $ python -V
    Python 3.6.0 :: Anaconda 4.3.0 (x86_64)

    接著要建立我們專案虛擬環境,這樣在安裝操作套件時比較不容易被污染到 root 的環境,啟動後會出現(套件名稱)的提示字元:

    # 顯示目前虛擬環境列表
    $ conda info -e
    # 創建虛擬環境
    $ conda create -n 套件名稱 python=3.6
    # 進入虛擬環境(若是 Windows cmder 環境不用加 source) ,成功後提示字元變成:(套件名稱)$
    $ source activate 套件名稱
    # 離開虛擬環境(若是 Windows cmder 環境不用加 source)
    $ source deactivate

建立第一個 Flask 開發專案

使用 pip 管理 Python 模組

# 安裝模組
$ pip install 模組名
# 移除模組
$ pip uninstall 模組名
# 搜尋模組
$ pip search 模組名

通常開發專案時我們會將已安裝模組名稱和版本號存成一個列表,以便下次安裝使用:

$ pip freeze > requirements.txt

根據 requirements.txt 列表安裝模組:

$ pip install -r requirements.txt

建立虛擬環境

在了解 pip 套件管理工具後我們正式來建立一個 Flask 的專案:

建立專案資料夾

$ mkdir python-flask-todo-app
$ cd python-flask-todo-app

建立獨立虛擬環境

$ conda create -n python-flask-todo-app python=3.6
$ source activate python-flask-todo-app

安裝 Flask 模組

$ pip install flask

設定 Config 設定檔案

建立設定檔 config.py 檔案在專案資料夾的根目錄中:

class Config(object):
pass

class ProdConfig(Config):
pass

class DevConfig(Config):
DEBUG = True

建立一個 main.py 檔案初始化 Flask App 和使用其 API,若是一切正常在終端機執行 python main.py 會在瀏覽器網址列輸入 localhost:5000 後看到 Hello World 了!

from flask import Flask
from config import DevConfig

# 初始化 Flask 類別成為 instance
app = Flask(__name__)
app.config.from_object(DevConfig)

# 路由和處理函式配對
@app.route('/')
def index():
return 'Hello World!'

# 判斷自己執行非被當做引入的模組,因為 __name__ 這變數若被當做模組引入使用就不會是 __main__
if __name__ == '__main__':
app.run()

使用 Flask Script

Flask Script 是 Flask 常用的 extensions,可以讓我們使用指令列來操作 Flask 程式並在 shell 環境下操作 app context,使用方式如下:

安裝模組

$ pip install flask-script

建立 manage.py 於根目錄

from flask_script import Manager, Server
from main import app

# 設定你的 app
manager = Manager(app)
# 設定 python manage.py runserver 為啟動 server 指令
manager.add_command('runserver', Server())

# 設定 python manage.py shell 為啟動互動式指令 shell 的指令
@manager.shell
def make_shell_context():
return dict(app=app)

if __name__ == '__main__':
manager.run()

當執行 $ python manage.py runserver 即會執行測試伺服器,$ python manage.py shell 可以在對話指令列中中輸入 app 找到被引入的 <Flask 'main'>,可以讓我們在互動式指令對話框中測試操作使用。

總結

本文介紹了如何建置 Python Web 開發環境,我們也實際完成了我們第一個 Python Flask 程式。在接下來章節中我們將持續介紹 Python Web Flask 實戰開發,並學習現代化網站開發的方方面面。

延伸閱讀

  1. Wiki Flask (web framework)
  2. Python Web 程式設計入門實戰線上課程

(image via fedoramagazine