1. 程式人生 > >python科學計算(利用numpy建立並訪問陣列)

python科學計算(利用numpy建立並訪問陣列)

利用numpy建立並訪問陣列

引入numpy包:

import numpy as np

建立np陣列

a = np.array([1,2,3,4])
#b = np.array([1,2,3,4],[5,6,7,8]) #報錯
c = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]])
c1 = np.array(([1,2,3,4],[4,5,6,7],[7,8,9,10]))
# c2 = np.array({[1,2,3,4],[4,5,6,7],[7,8,9,10]})  #報錯

# print(a)
# print(c)
# print(c1)
# print(c.dtype)
 '''
# 輸出:
# [1 2 3 4]
# [[ 1  2  3  4]
#  [ 4  5  6  7]
#  [ 7  8  9 10]]
# [[ 1  2  3  4]
#  [ 4  5  6  7]
#  [ 7  8  9 10]]
# int32
 '''

獲取陣列大小

 print(a.shape)
 print(c.shape)
# '''
# 輸出:
# (4,)
# (3, 4)
# '''

通過修改陣列的shape屬性,在保持陣列元素個數不變的情況下,改變陣列每個軸的長度

c1.shape = 4,3
print(c1)
# '''
# 輸出:
# [[ 1  2  3]
#  [ 4  4  5]
#  [ 6  7  7]
#  [ 8  9 10]]
# '''

當某個軸的元素為-1時,將根據陣列元素的個數自動計算此軸的長度

 c1.shape = 2 , -1
print(c1)
# '''
# output:
# [[ 1  2  3  4  4  5]
#  [ 6  7  7  8  9 10]]
# '''

使用陣列的reshape方法,可以建立一個改變了尺寸的新陣列,原陣列的shape保持不變

d = a.reshape((2,2))
print(d)
print(a)
# '''
# output
# [[1 2]
#  [3 4]]
# [1 2 3 4]
# '''

注意: 陣列a和d其實共享資料儲存記憶體區域,因此修改其中任意一個數組的元素都會同時修改另外一個數組的內容

a[1] = 100
print(a)
print(d)
# '''
# output:
# [  1 100   3   4]
# [[  1 100]
#  [  3   4]]
# '''

dtype可以獲得陣列的元素型別

,也可以通過dtype引數在建立時指定元素型別

b = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.float)
print(b.dtype)
'''
output:
float64
'''

直接用numpy中的函式建立陣列
arange函式類似於python的range函式,通過指定開始值、終值和步長來建立一維陣列,注意陣列不包括終值:

ar = np.arange(0,1,0.1)
print(ar)
'''
output:
[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9]
'''

linspace函式通過指定開始值、終值和元素個數來建立一維陣列,可以通過endpoint關鍵字指定是否包括終值,預設設定是包括終值

li = np.linspace(0, 1, 12)
 print(li)
li1 = np.linspace(0, 1, 12,endpoint=0)
print(li1)
'''
output:
[ 0.          0.09090909  0.18181818  0.27272727  0.36363636  0.45454545
  0.54545455  0.63636364  0.72727273  0.81818182  0.90909091  1.        ]
[ 0.          0.08333333  0.16666667  0.25        0.33333333  0.41666667
  0.5         0.58333333  0.66666667  0.75        0.83333333  0.91666667]
'''

logspace函式和linspace類似,不過它建立等比數列,下面的例子

# 產生1(10^0)到100(10^2)、有20個元素的等比數列:
lo = np.logspace(0, 2, 20)
print(lo)
'''
output:
[   1.            1.27427499    1.62377674    2.06913808    2.6366509
    3.35981829    4.2813324     5.45559478    6.95192796    8.8586679
   11.28837892   14.38449888   18.32980711   23.35721469   29.76351442
   37.92690191   48.32930239   61.58482111   78.47599704  100.        ]
'''

使用frombuffer, fromstring, fromfile等函式可以從位元組序列建立陣列

s = "abcdefgh"
fs8 = np.fromstring(s, dtype=np.int8)
fs16 = np.fromstring(s, dtype=np.int16)

print(fs8)
print(fs16)
'''
output:
[ 97  98  99 100 101 102 103 104]
[25185 25699 26213 26727]
'''

註釋: Python的字串實際上是位元組序列,每個字元佔一個位元組,因此如果從字串s建立一個8bit的整數陣列的話,所得到的陣列正好就是字串中每個字元的ASCII編碼:
如果從字串s建立16bit的整數陣列,那麼兩個相鄰的位元組就表示一個整數,把位元組98和位元組97當作一個16位的整數,它的值就是98*256+97 = 25185。可以看出記憶體中是以little endian(低位位元組在
前)方式儲存資料的

延伸: 利用fromstring讀取二進位制檔案?
如果我們用C語言的二進位制方式寫了一組double型別的數值到某個檔案中,那們可以從此檔案讀取相應的資料,並通過fromstring函式將其轉換為float64型別的陣列。

fromfunction函式 的第一個引數為計算每個陣列元素的函式,第二個引數為陣列的大小(shape),因為它支援多維陣列,所以第二個引數必須是一個序列
如:將陣列下標轉換為陣列中對應的值,然後使用此函式建立陣列

def func(i):
    return i % 4 + 1    #下標取餘後加一

fu1 = np.fromfunction(func, (10,))
print(fu1)
'''
output:[ 1.  2.  3.  4.  1.  2.  3.  4.  1.  2.]
'''
#建立99乘法表
def func2(i, j):
    return (i+1) * (j+1)

fu2 = np.fromfunction(func2, (9,9))
print(fu2)
'''
output:
[[  1.   2.   3.   4.   5.   6.   7.   8.   9.]
 [  2.   4.   6.   8.  10.  12.  14.  16.  18.]
 [  3.   6.   9.  12.  15.  18.  21.  24.  27.]
 [  4.   8.  12.  16.  20.  24.  28.  32.  36.]
 [  5.  10.  15.  20.  25.  30.  35.  40.  45.]
 [  6.  12.  18.  24.  30.  36.  42.  48.  54.]
 [  7.  14.  21.  28.  35.  42.  49.  56.  63.]
 [  8.  16.  24.  32.  40.  48.  56.  64.  72.]
 [  9.  18.  27.  36.  45.  54.  63.  72.  81.]]
'''

儲存元素

a = np.arange(10)
print(a[5])    # 用整數作為下標可以獲取陣列中的某個元素
print(a[3:5])  # 用範圍作為下標獲取陣列的一個切片,包括a[3]不包括a[5]
print(a[:5])   # 省略開始下標,表示從a[0]開始
print(a[:-1])  # 下標可以使用負數,表示從陣列後往前數
a[2:4] = 100,101  # 下標還可以用來修改元素的值
print(a)
print(a[1:-1:2])  # 範圍中的第三個引數表示步長,2表示隔一個元素取一個元素
print(a[::-1])    # 省略範圍的開始下標和結束下標,步長為-1,整個陣列頭尾顛倒
print(a[5:1:-2])  # 步長為負數時,開始下標必須大於結束下標

注意: 和Python的列表序列不同,通過下標範圍獲取的新的陣列是原始陣列的一個檢視。它與原始陣列共享同一塊資料空間

a = np.arange(10)
b = a[3:7] # 通過下標範圍產生一個新的陣列b,b和a共享同一塊資料空間
print(b)   #output:[3 4 5 6]
b[2] = 100
print(a,b)
'''
a、b都變了
output:
[  0   1   2   3   4 100   6   7   8   9] 
[  3   4 100   6]
'''

如何不共享資料空間?
1、使用整數序列,整數序列可以是列表或者陣列。

x = np.arange(10,1,-1)
x2 = x[[3, 3, 1, 8]]
x1 = x[np.array([3,3,-3,8])]    #下標可以為負
x1[2] = 100
x2[2] = 100
print(x1)    #output:[  7   7 100   2]
print(x2)    #output:[  7   7 100   2]
print(x)     #output:[10  9  8  7  6  5  4  3  2]
x[[3,5,1]] = -1, -2, -3  # 整數序列下標也可以用來修改元素的值
print(x)    #output:[10 -3  8 -1  6 -2  4  3  2]

2、使用布林陣列

x = np.arange(5,0,-1)    #[5, 4, 3, 2, 1]
x1 =  x[np.array([True, False, True, False, False])]
# 布林陣列中下標為0,2的元素為True,因此獲取x中下標為0,2的元素
print(x1)   #[5, 3]
x2 =  x[[True, False, True, False, False]]
# 如果是布林列表,則把True當作1, False當作0,按照整數序列方式獲取x中的元素
print(x2)    #[4, 5, 4, 5, 5]
x3 = x[np.array([True, False, True, True])]
# 布林陣列的長度不夠時,不夠的部分都當作False
print(x3)    #[5, 3, 2]
x[np.array([True, False, True, True])] = -1, -2, -3
# 布林陣列下標也可以用來修改元素
print(x)    #[-1, 4, -2, -3, 1]

產生 一個長度為10,元素值為0-1的隨機數的陣列

x = np.random.rand(10) 
print(x)
'''
[ 0.72223939, 0.921226 , 0.7770805 , 0.2055047 , 0.17567449,
0.95799412, 0.12015178, 0.7627083 , 0.43260184, 0.91379859]
'''

利用布林陣列提取滿足條件的陣列中的元素

p = x > 0.5    # 陣列x中的每個元素和0.5進行大小比較,得到一個布林陣列,True表示x中對應的值大於0.5
print(p)       #[ True  True  True False False False False False  True False]
print(x[p])    #[ 0.5764845   0.84377671  0.91877546  0.54866511]