{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "WUZm-Jbl3V6n"
},
"source": [
"## $\\Large{Numpy\\; Tutorial\\; (part2)}$\n",
"\n",
"Numpy 是使用Python進行科學運算中最基礎的模組,主要的功能環繞在**ndarray (n-dimensional array,中文為多維陣列)**物件上。\n",
"\n",
"上一個部份我們已經知道Numpy中多維陣列的一些特性以及常見的用法,在這個部分當中我們將會介紹如何操作一個或多個陣列、以及Numpy所提供的其他模組。"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Yu2EwrJLEXg7"
},
"source": [
"### 本章節內容大綱\n",
"* [操作多維陣列(Array Manipulation)](#操作多維陣列)\n",
" - [改變陣列維度](#改變陣列維度)\n",
" - [取得陣列元素](#取得陣列元素)\n",
" - [取得陣列片段](#取得陣列片段)\n",
" - [陣列搜尋與判斷](#陣列搜尋與判斷)\n",
" - [重複陣列元素](#重複陣列元素)\n",
" - [排序陣列內元素](#排序陣列內元素)\n",
"* [合併或堆疊多個陣列(Array Concatenation / Stacking)](#合併或堆疊多個陣列)\n",
" - [合併陣列](#合併陣列)\n",
" - [堆疊陣列](#堆疊陣列)\n",
"* [Numpy內的其他模組](#Numpy內的其他模組)\n",
" - [線性代數模組](#線性代數模組)\n",
" - [隨機模組](#隨機模組)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "KVj80H7XEXhG"
},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3q1YeiIuEXhJ"
},
"source": [
"---\n",
"\n",
"## 操作多維陣列\n",
"\n",
"Reference: 手把手打開資料分析大門\n",
"https://www.slideshare.net/tw_dsconf/python-83977705/47"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "05eDQfOH3V7O"
},
"source": [
"\n",
"- ### 改變陣列維度\n",
"\n",
"Numpy所提供的多維陣列除了在計算上很便利之外,也可以彈性地改變陣列的維度。在此我們主要介紹以下三個函數功能\n",
" - reshape:改變陣列維度\n",
" - expand_dim:增加陣列維度\n",
" - squeeze:壓縮陣列維度"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QiSbKpouEXhV"
},
"source": [
"#### reshape 功能\n",
"\n",
"reshape是在改變陣列維度中最常被使用的函數,它可以彈性地重塑陣列的形狀、增加、或是減少陣列維度。\n",
"\n",
"
\n",
"\n",
"\n",
"如上面這個例子,原先儲存 [0,1,2,3,4,5] 共六個元素的陣列維度可以是(6, )的一維陣列,也可以是(3,2)的二維陣列,甚至是(2,3,1)的三維陣列,唯一的需求就是改變後陣列的元素總數需與改變前相同。另外值得注意的是在改變形狀後陣列元素會依照維度依序排列,不會隨便亂跑!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Y15a15b93V7P"
},
"outputs": [],
"source": [
"# 創建一個一維陣列,裡面共有6個元素\n",
"x = np.arange(6)\n",
"\n",
"print(x)\n",
"print(x.shape)\n",
"# [0 1 2 3 4 5]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "UKcv2MESEXhZ"
},
"outputs": [],
"source": [
"# 使用reshape 將原本的陣列改成(3,2)的形狀\n",
"new_x = x.reshape(3, 2)\n",
"print(new_x)\n",
"print(new_x.shape)\n",
"# [[0 1]\n",
"# [2 3]\n",
"# [4 5]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "n_aDLDnMEXhk"
},
"outputs": [],
"source": [
"# 使用reshape 將原本的陣列改成(2,3,1)的形狀\n",
"new_x2 = np.arange(6).reshape(2, 3, 1)\n",
"print(new_x2)\n",
"print(new_x2.shape)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ZcQTzVDLfZlV"
},
"outputs": [],
"source": [
"x"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "jUkjmyo1EXhm"
},
"outputs": [],
"source": [
"# extra\n",
"\n",
"# 如果懶得算要轉換的維度,也可以給予 -1 讓numpy自已計算\n",
"new_x4 = x.reshape(2, -1)\n",
"print(new_x4, new_x4.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cONtt7hWEXhn"
},
"source": [
"#### expand_dims 與 squeeze 功能\n",
"\n",
"相較於reshape強大且彈性的功能,expand_dims與squeeze各自負責的是在不改變陣列形狀的前提下增加或是減少維度。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2jzW8qiNEXhx"
},
"outputs": [],
"source": [
"# 創建一個一維陣列\n",
"x = np.arange(6)\n",
"print(x, x.shape)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "LfvDCa1HEXh2"
},
"outputs": [],
"source": [
"# 在x這個陣列額外增加一個維度並且命名為x2,在這邊我們加在第一個軸,因此axis = 0\n",
"x2 = np.expand_dims(x, axis=0)\n",
"print(x2, x2.shape)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "9SQ5WmXhEXh3"
},
"outputs": [],
"source": [
"# 將x2這個陣列裡面多的維度(長度為一的維度)壓縮\n",
"x3 = np.squeeze(x2)\n",
"print(x3, x3.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_mwttuJm3V7a"
},
"source": [
"\n",
"- ### 取得陣列元素\n",
"\n",
"如果我們想要取出一個或多個陣列的元素的話,我們就需要使用陣列內元素的索引去取得元素本身,還記得python原生的列表(list)嗎?陣列元素索引的使用方式與列表其實非常類似,只要在陣列後面以中括號**[ ]**並在裡面填入索引就可以了,差異在於陣列的維度是多維的,因此陣列元素的索引也是多維的。\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "_fcHtZer3V7b"
},
"outputs": [],
"source": [
"# 創建一個一維陣列\n",
"x = np.arange(6)\n",
"print(x)\n",
"# array([0, 1, 2, 3, 4, 5])\n",
"\n",
"# 取出這個陣列的第三個元素\n",
"print(x[2])\n",
"# 2\n",
"\n",
"# 取出這個陣列的倒數第二個元素\n",
"print(x[-2])\n",
"# 4"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "90MR0Zb1EXiB"
},
"outputs": [],
"source": [
"# 創建一個二維陣列\n",
"x = np.arange(6).reshape(2, 3)\n",
"print(x)\n",
"# [[0, 1, 2],\n",
"# [3, 4, 5]])\n",
"\n",
"# 取出第一個維度索引為0,第二個維度索引為2的元素\n",
"print(x[0, 2])\n",
"# 2\n",
"\n",
"# 取出第一個維度索引為1,第二個維度索引為-1 (倒數第一)的元素\n",
"print(x[1, -1])\n",
"# 5"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1Z5PpmM83V7g"
},
"source": [
"\n",
"- ### 取得陣列片段\n",
"\n",
"同樣地,在陣列中要取得某一部份的元素我們同樣可以利用和列表(list)相似的辦法。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "3XkOklq73V7h"
},
"outputs": [],
"source": [
"# 創建一個一維陣列\n",
"x = np.arange(6)\n",
"# array([0, 1, 2, 3, 4, 5])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "hJznhi2OfZlZ"
},
"outputs": [],
"source": [
"x"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "HKNEwbJ6EXiJ"
},
"outputs": [],
"source": [
"# 取出這個陣列第二到第六個元素的片段(不含第六個元素)\n",
"print(x[1:5])\n",
"# [1, 2, 3, 4]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "phjTnhZIEXlH"
},
"outputs": [],
"source": [
"# 取出這個陣列從頭開始到第三個元素的片段(不含第三個元素)\n",
"print(x[:2])\n",
"# [0, 1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "aI8nKwTsEXlI"
},
"outputs": [],
"source": [
"# 取出這個陣列第二個到第六個元素的片段(不含第六個元素),且每隔兩個值取一個元素\n",
"print(x[1:5:2])\n",
"# [1, 3]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "5llncKKIEXlL"
},
"outputs": [],
"source": [
"# 創建一個二維陣列\n",
"x = np.arange(6).reshape(2, 3)\n",
"# [[0, 1, 2],\n",
"# [3, 4, 5]])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "HQ47dYETfZla"
},
"outputs": [],
"source": [
"x"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "yU1zOBG4EXlS"
},
"outputs": [],
"source": [
"# 取出這個陣列第一個維度索引為0,第二個維度從第一個到第三個元素的片段(不含第三個元素)\n",
"print(x[0, 0:2])\n",
"# [0, 1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "o6vy3XdJEXlT"
},
"outputs": [],
"source": [
"# 取出這個陣列第一個維度的所有索引,第二個維度從第二個到最後一個元素的片段\n",
"print(x[:, 1:])\n",
"# [[1, 2],\n",
"# [4, 5]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "NHuPkEsVEXlU"
},
"outputs": [],
"source": [
"# 取出這個陣列第一個維度從頭到尾且每隔一個值取一個元素,第二個維度從頭到尾且每隔兩個值取一個元素的片段\n",
"print(x[::1, ::2])\n",
"# [[0, 2],\n",
"# [3, 5]]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "41_qi6yyEXlU"
},
"source": [
"\n",
"- ### 陣列搜尋與判斷\n",
"\n",
"在一個陣列中我們也可以做搜尋或是每個元素的判斷,讓我們來看一下要如何操作吧。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "-Rsy8DsHEXlW"
},
"outputs": [],
"source": [
"# 創建一個一維陣列\n",
"x = np.arange(6)\n",
"# array([0, 1, 2, 3, 4, 5])\n",
"\n",
"# 針對每個元素判斷是不是小於3,若小於3則為True、大於等於3則為False\n",
"condition = x < 3\n",
"\n",
"# 這個只有True / Fasle 的陣列也被稱為布林遮罩(boolean mask)\n",
"print(condition)\n",
"# [ True True True False False False]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "-wYqXmfjEXlb"
},
"outputs": [],
"source": [
"# 創建一個一維陣列\n",
"x = np.array([3, 1, 6, 4, 2])\n",
"\n",
"# 使用argmax去找陣列中最大的元素索引\n",
"idx_ = np.argmax(x)\n",
"print('陣列x中最大數值的索引是:', idx_)\n",
"print('陣列x中最大數值是 : ', x[idx_])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nwLTG7yE3V7m"
},
"source": [
"我們也可以使用判斷過後的遮罩幫助我們取出陣列中的元素"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cI4Eqxbj3V7n"
},
"outputs": [],
"source": [
"# 創建一個一維陣列\n",
"x = np.arange(6)\n",
"# array([0, 1, 2, 3, 4, 5])\n",
"\n",
"# 判斷這個陣列的元素是否小於3\n",
"condition = x < 3\n",
"\n",
"# 可以在索引當中放入剛剛的判斷式,就可以只取出小於3的元素們\n",
"print(x[condition])\n",
"# [0, 1, 2]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "taXuSVjwEXlh"
},
"outputs": [],
"source": [
"# 也可以應用這樣個方法直接取代陣列中的元素數值\n",
"x[condition] = 0\n",
"print(x)\n",
"# [0, 0, 0, 3, 4, 5]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "AC5qdsD1EXlk"
},
"source": [
"\n",
"- ### 重複陣列元素\n",
"\n",
"如果需要快速複製陣列中的元素,我們可以使用repeat函數功能,而若需要做的是重複整個陣列內容則可以用tile函數做到這件事情。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bK5VwyRbEXll"
},
"outputs": [],
"source": [
"# 創建一個二維陣列\n",
"x = np.array([[0, 1], [2, 3]])\n",
"print(x)\n",
"# [[0, 1]\n",
"# [2, 3]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "pohFXXVkEXll"
},
"outputs": [],
"source": [
"# 重複陣列中的元素兩次,預設會將陣列攤平成一維陣列\n",
"np.repeat(x, repeats=2)\n",
"# [0, 0, 1, 1, 2, 2, 3, 3]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "XbhYyBtEEXlu"
},
"outputs": [],
"source": [
"# 指定每個元素的重複次數\n",
"np.repeat(x, repeats=(1, 2, 3, 4))\n",
"# [0, 1, 1, 2, 2, 2, 3, 3, 3, 3]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "1UZjDVaeEXly"
},
"outputs": [],
"source": [
"# 以axis參數指定要重複時所依據的維度\n",
"# 指定axis = 0,numpy就會將第一軸index相同的元素(ex.[0, 1])當作同一組做重複。\n",
"np.repeat(x, repeats=2, axis=0)\n",
"# [[0, 1],\n",
"# [0, 1],\n",
"# [2, 3],\n",
"# [2, 3]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "QzaWaTu1EXlz"
},
"outputs": [],
"source": [
"# 以axis參數指定要重複時所依據的維度\n",
"# 指定axis = 1,numpy就會將第二軸index相同的元素當作同一組做重複。\n",
"# (ex.[0\n",
"# 2])\n",
"\n",
"np.repeat(x, repeats=2, axis=1)\n",
"# [[0, 0, 1, 1],\n",
"# [2, 2, 3, 3]]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "OAgW1sYCEXl0"
},
"source": [
"#### tile 功能"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "9WRnzx34EXl1"
},
"outputs": [],
"source": [
"# 創建一個二維陣列\n",
"x = np.array([[0, 1], [2, 3]])\n",
"print(x)\n",
"# [[0, 1]\n",
"# [2, 3]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "RRtBKeLQEXl2"
},
"outputs": [],
"source": [
"# 預設在重複時會沿著最後一個維度(在這邊是axis=1)增加\n",
"np.tile(x, reps=2)\n",
"# [[0, 1, 0, 1],\n",
"# [2, 3, 2, 3]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "X9j7loFzEXl2"
},
"outputs": [],
"source": [
"# 在reps參數中也可以指定每個維度的重複次數\n",
"np.tile(x, reps=(1, 2))\n",
"# [[0, 1, 0, 1],\n",
"# [2, 3, 2, 3]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "gBeDjZ0JEXl3"
},
"outputs": [],
"source": [
"# 設定在第一個維度重複兩次,第二個維度不做重複動作\n",
"np.tile(x, reps=(2, 1))\n",
"# [[0, 1],\n",
"# [2, 3],]\n",
"# [0, 1],]\n",
"# [2, 3],]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0hZRUldcEXl4"
},
"outputs": [],
"source": [
"# 若reps參數中填入的維度大於原本陣列的維度,則會自動增加陣列維度\n",
"np.tile(x, reps=(2, 2, 2))\n",
"# [[[0, 1, 0, 1],\n",
"# [2, 3, 2, 3],\n",
"# [0, 1, 0, 1],\n",
"# [2, 3, 2, 3]],\n",
"#\n",
"# [[0, 1, 0, 1],\n",
"# [2, 3, 2, 3],\n",
"# [0, 1, 0, 1],\n",
"# [2, 3, 2, 3]]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "dggPVbGvEXl4"
},
"outputs": [],
"source": [
"np.tile(x, reps=(2, 2, 2)).shape"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uSZTvc1rEXl5"
},
"source": [
"\n",
"- ### 排序陣列內元素\n",
"\n",
"針對陣列中的元素,我們也可以進行排序讓他們交換位置,另外在這邊我們也可以利用axis參數讓功能更加彈性。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bZlctJGIEXl6"
},
"outputs": [],
"source": [
"# 創建一個二維陣列\n",
"x = np.array([[6, 5, 4], [1, 2, 3]])\n",
"print(x)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "nRpAxi_dEXl7"
},
"outputs": [],
"source": [
"# 使用np.sort排序陣列內元素,預設會沿著最後一個維度做排序\n",
"np.sort(x)\n",
"# [[4, 5, 6],\n",
"# [1, 2, 3]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ZR0DdZN9EXl7"
},
"outputs": [],
"source": [
"# 也可以直接使用axis參數指定要依照哪個維度做排序\n",
"# 在此範例中因為x的維度有(0,1)兩種可能性,指定axis=-1 將等於 axis=1\n",
"np.sort(x, axis=-1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "a-G_tBhLEXmF"
},
"outputs": [],
"source": [
"# 依據第一個維度做排序\n",
"np.sort(x, axis=0)\n",
"# [[1, 2, 3],\n",
"# [6, 5, 4]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "I3-KUIFpEXmG"
},
"outputs": [],
"source": [
"# 若指定axis = None,則會排序陣列中所有元素並且攤平\n",
"np.sort(x, axis=None)\n",
"# [1, 2, 3, 4, 5, 6]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JyTdvATW3V7r"
},
"source": [
"\n",
"## 合併或堆疊多個陣列\n",
"\n",
"除了對一個陣列做操作之外,有的時候也會遇到將多個陣列合併在一起的狀況,此時依據需求不同我們可以使用concatenate或是stack幫我們做到這件事情。"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "83eTK_aoEXmI"
},
"source": [
"\n",
"- ### 合併陣列\n",
"\n",
"concatenate可以幫助我們把多個陣列沿著某一個維度合併在一起,合併之後的陣列維度會跟原本的維度數量相同,不會額外增加新的維度。\n",
"\n",
"要注意的是要合併的陣列除了要合併的維度之外,其餘的維度長度都要一樣喔!\n",
"\n",
"
\n",
"\n",
"---\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "t8yIrW_L3V7s"
},
"outputs": [],
"source": [
"# 創建兩個二維陣列\n",
"a = np.array([[1, 2, 3], [4, 5, 6]])\n",
"b = np.array([[7, 8, 9]])\n",
"\n",
"print(a)\n",
"print('--------')\n",
"print(b)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "mu8FxsqbEXmJ"
},
"outputs": [],
"source": [
"# 將兩個陣列沿著第一個維度合併起來,我們可以用三個陣列的shape看一下到底發生了甚麼事情\n",
"c = np.concatenate((a, b), axis=0)\n",
"print(c)\n",
"print(a.shape, b.shape, c.shape)\n",
"# [[1, 2, 3],\n",
"# [4, 5, 6],\n",
"# [7, 8, 9]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "i3BUIdeMEXmL"
},
"outputs": [],
"source": [
"# 創建另外一個二維陣列\n",
"d = np.array([[0], [0]])\n",
"\n",
"# 將a與d兩個陣列沿著第二個維度合併起來\n",
"np.concatenate((a, d), axis=1)\n",
"# [[1, 2, 3, 0],\n",
"# [4, 5, 6, 0]]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cLcs0Nvz3V8A"
},
"source": [
"\n",
"- ### 堆疊陣列\n",
"\n",
"stack與concatenate不同的地方在於,需要合併的陣列無論是維度或是各維度的長度都需要相同,另外合併後的陣列會額外新增一個維度。\n",
"\n",
"而vstack(vertical stacking)與hstack(horizontal stacking)則與concatenate功能類似,只是不需要指定合併的維度。\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "VyE0M7WS3V8B"
},
"outputs": [],
"source": [
"# 創建三個二維陣列\n",
"a = np.array([[0, 1], [2, 3]])\n",
"\n",
"b = np.array([[4, 5], [6, 7]])\n",
"\n",
"c = np.array([[8, 9], [10, 11]])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "lnjYObbiEXmR"
},
"outputs": [],
"source": [
"# 將三個陣列在第一個維度堆疊起來\n",
"s = np.stack([a, b, c], axis=0)\n",
"print(s)\n",
"print(s.shape)\n",
"# (3, 2, 2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "k3eh8WjVEXmS"
},
"outputs": [],
"source": [
"# 將三個陣列沿著第一個維度合併起來\n",
"v = np.vstack([a, b, c])\n",
"print(v)\n",
"print(v.shape)\n",
"# (6, 2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "NQZ5KArLEXmS"
},
"outputs": [],
"source": [
"# 將三個陣列沿著第二個維度合併起來\n",
"h = np.hstack([a, b, c])\n",
"print(h)\n",
"print(h.shape)\n",
"# (2, 6)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6lEVdrjmEXmT"
},
"source": [
"---\n",
"\n",
"## Numpy內的其他模組\n",
"\n",
"由於numpy提供的是通用性的陣列物件,除了上述的基本功能之外,也有其他模組供使用者進行其他的數學運算,在此我們介紹兩個較常使用的模組,分別為線性代數模組與隨機模組。"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "L-uLxLnm3V77"
},
"source": [
"\n",
"- ### 線性代數模組\n",
"\n",
"在numpy中,二維的陣列即可以當作矩陣來使用,因此在numpy.linalg 模組中提供許多針對矩陣進行操作的函數和方法。在此我們簡單介紹如何將一個矩陣作轉置、得到它的反矩陣、以及做內積。\n",
"\n",
"轉置矩陣:m \\* n 矩陣在向量空間上轉置為 n \\* m 矩陣 \n",
"反矩陣:n \\* n 矩陣 A 存在一個 n \\* n 矩陣 B,使得 AB = BA = I"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ELGfnIl53V78"
},
"outputs": [],
"source": [
"# 創建一個二維陣列,可視為矩陣\n",
"x = np.array([[0, 1], [2, 3]])\n",
"\n",
"print(x)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2yqjqeOkEXmV"
},
"outputs": [],
"source": [
"# 取得x的轉置矩陣\n",
"print(x.T)\n",
"# [[0, 2],\n",
"# [1, 3]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "IMuHm9LrEXmW"
},
"outputs": [],
"source": [
"# 取得x的反矩陣\n",
"inverse = np.linalg.inv(x)\n",
"print(inverse)\n",
"# [[-1.5, 0.5],\n",
"# [1, 0]]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "rtjVndSGEXmW"
},
"outputs": [],
"source": [
"# 將x與x的反矩陣進行內積,結果應為單位矩陣\n",
"print(np.dot(x, inverse))\n",
"# [[ 1. 0.]\n",
"# [ 0. 1.]]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "waNAnYMUEXmX"
},
"source": [
"\n",
"- ### 隨機模組\n",
"\n",
"在數學運算或模擬的過程中,我們很常需要隨機地產生數字,此時我們就可以使用numpy的隨機模組。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "mgERenOeEXmY"
},
"outputs": [],
"source": [
"# 設定隨機種子\n",
"np.random.seed(seed=818)\n",
"\n",
"# 使用np.random模組產生隨機整數\n",
"# 設定範圍為1到10,並且產生5個隨機整數 (每個整數出現的機率相同)\n",
"print(np.random.randint(low=1, high=10, size=5))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ZcEI5dlNEXmZ"
},
"outputs": [],
"source": [
"# 從標準常態分配中取得10個數字\n",
"print(np.random.randn(10))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IAMRkrUwEXma"
},
"source": [
"大家可能會疑惑一開始的隨機種子到底是甚麼意思,事實上在電腦裡面所取的隨機數並非真正的隨機,而是透過演算法所產生出來的隨機數字,這樣的方式又被稱為偽隨機(Pseudo-Randomness)。\n",
"\n",
"也因為這樣,只要我們給予相同的數字作為輸入給產生隨機數的演算法,就能夠得到一模一樣的同一組隨機數字,這個決定隨機演算法輸出的數字也被稱為隨機種子。在numpy內我們可以使用np.random.seed 設定當使用到隨機模組時要使用的隨機種子數值是多少。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "zMEni-4WEXmb"
},
"outputs": [],
"source": [
"# 設定隨機種子為10,並且從標準常態分配中抽取一個樣本\n",
"np.random.seed(seed=10)\n",
"print(np.random.randn(1))\n",
"\n",
"# 再一次設定這次要用的隨機種子是10,看看我們可不可以得到相同的結果\n",
"np.random.seed(seed=10)\n",
"print(np.random.randn(1))"
]
}
],
"metadata": {
"colab": {
"name": "Numpy_part2.ipynb",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}