01_Python NumPy數(shù)組

2019.3.23

因?yàn)樽约簺](méi)什么動(dòng)力,真的很久沒(méi)有順著自己的心思來(lái)學(xué)習(xí)了,趁著有數(shù)據(jù)分析的課,今天一大早起來(lái)學(xué)習(xí)一下Numpy庫(kù)的使用。特以此文記錄學(xué)習(xí)進(jìn)度。


Numpy

一.ndarray數(shù)組的創(chuàng)建


1. 概述

numpy官網(wǎng)

NumPy是使用Python進(jìn)行科學(xué)計(jì)算的基礎(chǔ)包它包含其他內(nèi)容:一個(gè)強(qiáng)大的N維數(shù)組對(duì)象、復(fù)雜的(廣播)功能、用于集成C / C ++和Fortran代碼的工具、有用的線性代數(shù),傅里葉變換和隨機(jī)數(shù)功能除了明顯的科學(xué)用途外,NumPy還可以用作通用數(shù)據(jù)的高效多維容器??梢远x任意數(shù)據(jù)類型。這使NumPy能夠無(wú)縫快速地與各種數(shù)據(jù)庫(kù)集成Numpy具有兩類對(duì)象,分別是ndarray(N-dimensional Array Object)以及ufunc(Universal Function Object),前者類似于多維數(shù)組,后者則是可以對(duì)前者操作的函數(shù)。



2. 基本方法


  1. numpy.array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)

numpy.array()是最原始的手動(dòng)生成ndarray對(duì)象的方法。其中的object 需傳入一個(gè)數(shù)組對(duì)象(n維)。注:當(dāng)ndarray的維度過(guò)大時(shí),numpy的輸出會(huì)折疊中間結(jié)果。如果想要取消折疊。需要這樣設(shè)置

np.set_printoptions(threshold=np.nan)
# Use the numpy.array to create the ndarray
import numpy as np
array1 = np.array([[1, 2, 3], [4, 5, 6]]) #必須傳入一個(gè)列表或數(shù)組
"""Output: 
[[1 2 3]
 [4 5 6]]
"""
  • 常用屬性

    常用屬性 屬性說(shuō)明
    ndim 矩陣的秩,即軸的數(shù)量或維度的數(shù)量
    shape 數(shù)組的維度,對(duì)于矩陣,n 行 m 列
    size 數(shù)組元素的總個(gè)數(shù),相當(dāng)于 .shape 中 nm 的值*
    dtype ndarray 對(duì)象的元素類型
    real ndarray元素的實(shí)部
    imag ndarray 元素的虛部
  • 使用樣例

    # Use the numpy.array to create the ndarray
    import numpy as np
    array1 = np.array([[1, 2, 3], [4, 5, 6]])
    print(array1.ndim)
    """ Output: 2 """
    

  1. arange([start]stop[,step], dtype=Nope)

numpy.arange()用于生成一個(gè)指定步長(zhǎng)的等差數(shù)組。其做法與range()相似,包括start而不包括stop。其中start和step為可選參數(shù),默認(rèn)start為0,step為1;stop指定了區(qū)間的結(jié)束(開(kāi)區(qū)間);dtype默認(rèn)為Nope。可惜的是,無(wú)法指定其形狀shape,故只能通過(guò)修改shape的值的方法來(lái)生成多維數(shù)組。

  • 使用樣例

    # Use the numpy.array to create the ndarray
    import numpy as np
    print("利用arange()來(lái)創(chuàng)建一個(gè)ndarray:", np.arange(0, 1, 0.1))
    """ Output: 利用arange()來(lái)創(chuàng)建一個(gè)ndarray: [0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] """
    

  1. numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)

numpy.logspace()用于創(chuàng)建一個(gè)等比數(shù)組。其中start, stop 都是必須給出的參數(shù),表示區(qū)間(規(guī)則與range()相同)。num表示元素的個(gè)數(shù),默認(rèn)50。在閉合區(qū)間[start,stop]或半開(kāi)區(qū)間[start,stop]中存在數(shù)量等間距的樣本(取決于端點(diǎn)是True還是False)。


  1. numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0)

numpy.logspace()與numpy.lonspqce()的區(qū)別在于,前者多了一個(gè)參數(shù)base,這意味著numpy.logspace()是根據(jù)10為底數(shù)來(lái)創(chuàng)建等比數(shù)組的(當(dāng)然,可以傳入別的值作為底),start與stop將被理解為“在[10^start, 10^stop]區(qū)間內(nèi)構(gòu)建等比數(shù)組”


  1. 幾個(gè)構(gòu)建特殊矩陣數(shù)組的函數(shù)(不予以例子說(shuō)明)

numpy.zeros()需要一個(gè)元組類似于(3,4)來(lái)指定形狀,元素全部用0充填
numpy.ones()需要一個(gè)元組類似于(3,4)來(lái)指定形狀,元素全部用1充填
numpy.eye()只需傳入一個(gè)代表維數(shù)的int型整數(shù)即可,生成一個(gè)單位n維矩陣
numpy.diag()需要傳入一個(gè)具有n個(gè)元素的一維數(shù)組, 生成一個(gè)n維的,對(duì)角線上的元素依次為傳入的一維數(shù)組的元素的矩陣(類似于對(duì)角矩陣)



二.Numpy的各種操作方式


  1. 矩陣運(yùn)算
import numpy as np
a = np.array([20, 30, 40, 50])
b = np.arange(4)
print(a-b)
""" Output: [20 29 38 47] """
print(b**2)
""" Output: [0 1 4 9] """
print(10*np.sin(a))
""" Output: array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854]) """
print(a<35)
""" Output: [ True  True False False] """

與大部分的數(shù)學(xué)語(yǔ)言(如MATLAB)不同,Numpy中的乘號(hào)(*) 的數(shù)組運(yùn)算是求元素積,而不是數(shù)量積(矩陣相乘)。如果需要求數(shù)量積,就需要使用@或者dot()。其他的諸如加減除(+ - /)等運(yùn)算符,均在Numpy中通用。還有一些諸如求和,求最大最小值的函數(shù)也可用(sum(), min()等)。

import numpy as np
A = np.array([[1, 1],  [0, 1]]) 
B = np.array([[2, 0],  [3, 4]])
print(A * B)
""" Output: 
[[2, 0]
 [0, 4]]
"""
print(A @ B)
""" Output: 
[[5, 4]
 [3, 4]]
"""
print(A.dot(B)) 
""" Output:
[5, 4]
 [3, 4]]
"""

  1. 通用函數(shù)

一些通用的數(shù)學(xué)函數(shù),例如sin、cos、exp等,此類函數(shù)被稱作 通用函數(shù),其操作的對(duì)象也是數(shù)組的元素,即元素積之類的。

import numpy as np
B = np.arange(3)
print(np.exp(B))
""" Output: [1.         2.71828183 7.3890561 ] """
print(np.sqrt(B))
""" Output: [0.         1.         1.41421356] """

  1. 索引

ndarray的索引使用方法與列表的寫(xiě)法相近。如果是多維的數(shù)組,則每一維的索引用逗號(hào)分隔。 其中還有一種比較有趣的寫(xiě)法--- 省略號(hào):表示全集(即那個(gè)維度的全部元素)。索引甚至可以是一個(gè)數(shù)組,表示一次索引多個(gè)值、還可以是布爾表達(dá)式。 還有更多的高級(jí)玩法就不一一演示了。

import numpy as np
a = np.arange(10)**3 # 冪的寫(xiě)法,表示3次方
print(a[2:5])
""" Output: [ 8 27 64] """
def f(x, y):
  return 10*x + y
# fromfunction()可以從一個(gè)函數(shù)中獲得數(shù)據(jù)來(lái)創(chuàng)建ndarray
b = np.fromfunction(f, (5, 4), dtype=int) 
print(b[1:3, 2:3])
"""Output:
[[12]
 [22]]
"""
print(b[:2 ,...]) #表示第二維輸出全部元素
"""Output:
[[ 0  1  2  3]
 [10 11 12 13]]
"""
print(b[..., :2]) #表示第一維輸出所有元素
"""Output:
[[ 0  1]
 [10 11]
 [20 21]
 [30 31]
 [40 41]]
"""

  1. 遍歷

對(duì)一個(gè)多維的ndarray對(duì)象使用迭代器的話,默認(rèn)是遍歷一行。

import numpy as np
def f(x, y):
  return 10*x + y
b = np.fromfunction(f, (5, 4), dtype=int) 
for row in b:
  print(row)
"""Output:
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
"""
for elements in b.flat:
    print(elements)
"""Output:
0
1
2
3
...
"""

  1. 維度控制

numpy中有很多函數(shù)可以改變一個(gè)ndarray的維度。以下列出幾個(gè)常用的。

  • ravel(): 對(duì)多維的矩陣進(jìn)行降到一維的操作。并且,numpy.ravel()返回的是視圖,會(huì)影響原始矩陣。
  • flatten():功能與ravel()一致。但其是對(duì)矩陣的一個(gè)深拷貝進(jìn)行操作,所以不會(huì)改變?cè)仃嚒?/strong>(不予以例子)
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
print(a) # 輸出原矩陣
"""Output:
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
"""
a = a.ravel()
print(a) #輸出降維的矩陣,發(fā)現(xiàn)確實(shí)改變了原矩陣
"""Output: [ 1  2  3  4  5  6  7  8  9 10 11 12] """
  • reshape()與resize():兩者的功能都是將矩陣改變成指定的維度。reshape()傳入一個(gè)元組,表示指定的維度(要合理);resize()需要傳入矩陣,和一個(gè)指定的元組。區(qū)別是,resize()會(huì)改變?cè)仃嚒?/strong>
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
print(a.reshape(3, 4))
"""Output:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
"""Output:
print(a) # 原數(shù)組并沒(méi)有被改變
"""Output:
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
"""
print(np.resize(a, (3, 4))) # 必須這樣來(lái)調(diào)用
"""Output:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
"""
print(a) # 原矩陣被改變
"""Output:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
"""
print(a.reshape(2, -1)) # 可以傳入-1,numpy會(huì)自動(dòng)計(jì)算剩下的維度,但還是要合理
"""Output:
[[ 1  2  3  4  5  6]
 [ 7  8  9 10 11 12]]
"""

  1. 復(fù)制

一般的矩陣復(fù)制并不會(huì)復(fù)制任何內(nèi)存(只是改變了標(biāo)簽名)。 而視圖(view)是矩陣的一個(gè)淺拷貝,雖不是原矩陣(即會(huì)另外分配內(nèi)存),但對(duì)視圖的操作會(huì)影響到原矩陣。 深復(fù)制則是另外分配內(nèi)存,把原矩陣所有值復(fù)制過(guò)來(lái),操作不會(huì)改變?cè)仃嚒?/em>

import numpy as np
a = np.arange(12).reshape(3, 4)
b = a
b is a # True表示b和a是同一個(gè)內(nèi)存對(duì)象
"""Output: True """
c = a.view()
c is a # c并不和a是同一個(gè)對(duì)象
"""Output: False """ 
print(a) # 輸出原矩陣
"""Output:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
"""
c[0, 0] = 111
print(a) # 改變視圖,原矩陣元素改變
"""Output:
[[111   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]]
"""
b = a.copy()
b is a # 深拷貝不是同一對(duì)象
"""Output: False """
b[0, 0] = 222
print(a) # 深拷貝的操作不會(huì)改變?cè)仃?"""Output:
[[111   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]]
"""


更多的進(jìn)階功能:
官方教程
函數(shù)詳細(xì)說(shuō)明文檔及手冊(cè)



三.實(shí)例聯(lián)系:康威生命棋(用Numpy和pygame模擬)

劍橋大學(xué) 約翰·何頓·康威(John Horton Conway) 教授設(shè)計(jì)了一個(gè)叫做“生命游戲”的計(jì)算機(jī)程序,生命游戲是一個(gè)二維網(wǎng)格游戲,這個(gè)網(wǎng)格中每個(gè)方格居住著一個(gè)活著或死了的細(xì)胞。一個(gè)細(xì)胞在下一個(gè)時(shí)刻的生死取決于相鄰8個(gè)方格中活著或死了的細(xì)胞的數(shù)量。如果相鄰方格活著的細(xì)胞數(shù)量過(guò)多,這個(gè)細(xì)胞會(huì)因?yàn)橘Y源匱乏而在下一個(gè)時(shí)刻死去;相反,如果周圍活細(xì)胞過(guò)少,這個(gè)細(xì)胞會(huì)因?yàn)楣聠味廊ァ?/em>

大致規(guī)則
(1)當(dāng)前細(xì)胞為死亡狀態(tài)時(shí),當(dāng)周圍有3個(gè)存活細(xì)胞時(shí),則迭代后該細(xì)胞變成存活狀態(tài)(模擬繁殖);若原先為生,則保持不變。
(2)當(dāng)前細(xì)胞為存活狀態(tài)時(shí),當(dāng)周圍的鄰居細(xì)胞低于兩個(gè)(不包含兩個(gè))存活時(shí),該細(xì)胞變成死亡狀態(tài)(模擬生命數(shù)量稀少)。
(3)當(dāng)前細(xì)胞為存活狀態(tài)時(shí),當(dāng)周圍有兩個(gè)或3個(gè)存活細(xì)胞時(shí),該細(xì)胞保持原樣。
(4)當(dāng)前細(xì)胞為存活狀態(tài)時(shí),當(dāng)周圍有3個(gè)以上的存活細(xì)胞時(shí),該細(xì)胞變成死亡狀態(tài)(模擬生命數(shù)量過(guò)多)。

這里就不多說(shuō)什么了,直接上訓(xùn)練的代碼。

import sys
import numpy as np # numpy用于存儲(chǔ)康威生命棋的矩陣
import pygame # pygame可以提供游戲窗口


def life_step(x, y, world):
    # sum(a[, axis, dtype, out, keepdims]) 給定軸上的數(shù)組元素的總和
    neighbours = np.sum(world[x-1:x+2, y-1:y+2])-world[x, y]
    if world[x, y] == 1 and not 2 <= neighbours <= 3:
         return 0
    elif neighbours == 3:
         return 1
    return world[x, y]


def main():
    screen_size = 500
    tile_size = 10
    background_color = (0, 0, 0)
    cell_color = (255, 55, 255)
    pygame.init()
    screen = pygame.display.set_mode((screen_size, screen_size))
    pygame.display.set_caption('Convay\'s Game of Life')
    clock = pygame.time.Clock()
    world = np.random.choice(a=[0], size=(screen_size // tile_size + 1, screen_size // tile_size+1))
    gun = [(5, 1), (5, 2), (6, 1), (6, 2), (5, 11), (6, 11), (7, 11), (4, 12),
              (3, 13), (3, 14), (8, 12), (9, 13), (9, 14), (6, 15), (4, 16), (5, 17),
              (6, 17), (7, 17), (6, 18), (8, 16), (3, 21), (4, 21), (5, 21), (3, 22),
              (4, 22), (5, 22), (2, 23), (6, 23), (1, 25), (2, 25), (6, 25), (7, 25),
              (3, 35), (4, 35), (3, 36), (4, 36)]

    # 根據(jù)gun里的元素,將world相應(yīng)位置的元素設(shè)置為1
    for i, j in gun:
        world[j, i] = 1

    fps = 0
    epoch = 0

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        pygame.display.set_caption("Convay\'s Game of Life /" + str(fps) +"FPS /" + str(epoch) + "epoch")
        screen.fill(background_color)
        new_world = np.copy(world)
        for (x, y), value in np.ndenumerate(world):
            new_world[x, y] = life_step(x, y, world)
            if new_world[x, y] == 1:
                pygame.draw.rect(screen, cell_color, (tile_size*(x-1), tile_size*(y-1), tile_size, tile_size), 0)
        world = new_world
        epoch += 1
        pygame.display.update()
        clock.tick(fps)


if __name__ == '__main__':
    main()

運(yùn)行截圖

康威生命棋01.png
康威生命棋02.png


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 基礎(chǔ)篇NumPy的主要對(duì)象是同種元素的多維數(shù)組。這是一個(gè)所有的元素都是一種類型、通過(guò)一個(gè)正整數(shù)元組索引的元素表格(...
    oyan99閱讀 5,288評(píng)論 0 18
  • 先決條件 在閱讀這個(gè)教程之前,你多少需要知道點(diǎn)python。如果你想從新回憶下,請(qǐng)看看Python Tutoria...
    舒map閱讀 2,725評(píng)論 1 13
  • NumPy是Python中關(guān)于科學(xué)計(jì)算的一個(gè)類庫(kù),在這里簡(jiǎn)單介紹一下。 來(lái)源:https://docs.scipy...
    灰太狼_black閱讀 1,331評(píng)論 0 5
  • 介紹 NumPy 是一個(gè) Python 包。 它代表 “Numeric Python”。 它是一個(gè)由多維數(shù)組對(duì)象和...
    喔蕾喔蕾喔蕾蕾蕾閱讀 1,865評(píng)論 0 5
  • 一、numpy概述 numpy(Numerical Python)提供了python對(duì)多維數(shù)組對(duì)象的支持:ndar...
    L_steven的貓閱讀 3,609評(píng)論 1 24

友情鏈接更多精彩內(nèi)容