本章涉及的主題如下:
- 數(shù)據(jù)類型
- 數(shù)組類型
- 類型轉(zhuǎn)換
- 創(chuàng)建數(shù)組
- 索引
- 花式索引
- 切片
- 處理數(shù)組的形狀
2.1NumPy數(shù)組對(duì)象
NumPy中的多為數(shù)組成為ndarray杰刽,它有兩個(gè)組成部分。
- 數(shù)據(jù)本身
- 描述數(shù)據(jù)的元數(shù)據(jù)
在數(shù)組的處理過程中涝婉,原始信息不受影響墩弯,變化的只是元數(shù)據(jù)而已渔工。
在第一章中引矩,我們?cè)?jīng)用arange()函數(shù)來生成數(shù)組旺韭。實(shí)際上区端,那是用來存放一組數(shù)值的一維數(shù)組织盼,這里的nadarray則可以具有一個(gè)以上的維度沥邻。
NumPy數(shù)組的優(yōu)勢(shì)
NumPy數(shù)組通常是由相同種類的元素組成的唐全,即數(shù)組中的數(shù)據(jù)項(xiàng)的類型必須一致芦瘾。NumPy數(shù)組元素類型一致的好處是:由于知道數(shù)組元素的類型相同近弟,所以能輕松確定存儲(chǔ)數(shù)組所需空間的大小祷愉。同時(shí)二鳄,NumPy數(shù)組還能夠運(yùn)用向量化運(yùn)算來處理整個(gè)數(shù)組髓窜;而完成同樣的任務(wù)寄纵,Python的列表則通常必須借助循環(huán)語句便利列表程拭,并對(duì)逐個(gè)元素進(jìn)行相應(yīng)的處理恃鞋。此外恤浪,NumPy使用了優(yōu)化過的CAPI资锰,所以運(yùn)算速度格外快绷杜。
NumPy數(shù)組的索引方法和Python類似鞭盟,下標(biāo)從0開始齿诉。
我們來創(chuàng)建一個(gè)數(shù)組試一下,查看它的數(shù)據(jù)類型和形狀
import numpy as np
a = np.arange(5)
print(a.dtype)
print(a)
print(a.shape)
輸出結(jié)果為:
int32
[0 1 2 3 4]
(5,)
因?yàn)槲业腜ython是32位版本抵恋,所以得到的結(jié)果是int32弧关;如你所見世囊,該向量有5個(gè)元素株憾,它們的值分別是0到4嗤瞎。該數(shù)組的shape屬性是一個(gè)元組猫胁,這是一個(gè)單元素?cái)?shù)組弃秆,所以存放的是每一個(gè)數(shù)組在每一個(gè)維度的長度菠赚。
2.2創(chuàng)建多維數(shù)組
import numpy as np
from numpy import array
m = array([np.arange(2), np.arange(2)])
print(m)
print(m.shape)
運(yùn)行結(jié)果:
[[0 1]
[0 1]]
(2, 2)
注意這里需要從numpy中Import array包衡查。
在這里拌牲,我們直接用np.arrange()創(chuàng)建了2 X 2的數(shù)組拍埠,利用array()函數(shù)創(chuàng)建數(shù)組時(shí)枣购,需要傳遞給它一個(gè)對(duì)象棉圈,而且這個(gè)對(duì)象必須是數(shù)組類型的分瘾,如Python列表。
2.3選擇NumPy數(shù)組元素
import numpy as np
from numpy import array
a = array([[1,2], [3,4]])
print(a)
print(a[0, 0])
print(a[0, 1])
print(a[1, 0])
print(a[1, 1])
運(yùn)行結(jié)果:
[[1 2]
[3 4]]
1
2
3
4
上面的矩陣是通過向array()函數(shù)傳遞一個(gè)由列表組成的列表得到的氏捞,然后通過逐個(gè)選擇矩陣的各個(gè)元素液茎,記住下標(biāo)是從0開始的捆等。
選擇數(shù)組是一件非常簡(jiǎn)單的事,對(duì)于數(shù)組a明郭,只要通過a[m, n]的形式薯定,就能訪問數(shù)組內(nèi)的元素话侄,其中m和n分別為數(shù)組元素的下標(biāo)吞杭。
2.4NumPy的數(shù)值類型
Python自身雖然支持整型篇亭、浮點(diǎn)型和復(fù)數(shù)型,但是對(duì)于科學(xué)計(jì)算來說谊却,還遠(yuǎn)遠(yuǎn)不夠,我們需要更多的數(shù)據(jù)類型碴萧,來滿足精度和存儲(chǔ)大小方面的各種不同要求破喻。為此曹质,NumPy提供了更加豐富的數(shù)據(jù)類型。而每一種數(shù)據(jù)類型都具有相應(yīng)的轉(zhuǎn)換函數(shù):
print(float(42))
print(int(42.0))
print(bool(42))
print(bool(0))
print(float(True))
print(float(False))
運(yùn)行結(jié)果:
42.0
42
True
False
1.0
0.0
許多函數(shù)都帶有一個(gè)制定數(shù)據(jù)類型的參數(shù)宅静,這個(gè)參數(shù)通常是可選的:
import numpy as np
from numpy import array
np.arange(7, dtype = np.uint16)
輸出結(jié)果:
array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)
注意纤垂,這里的dtype類型中的數(shù)據(jù)類型也要指定偉np.uint洒忧。
謹(jǐn)記:不允許把復(fù)數(shù)類型轉(zhuǎn)化為整型熙侍。同樣,也不允許把復(fù)數(shù)轉(zhuǎn)化為浮點(diǎn)數(shù)巷送,此外笑跛,復(fù)數(shù)的分量j是其虛部的系數(shù),允許把浮點(diǎn)數(shù)轉(zhuǎn)化為復(fù)數(shù)陈哑,如complex(1, 0)是合法的惊窖,復(fù)數(shù)的實(shí)部和虛部分別使用real()函數(shù)和imag()函數(shù)提取界酒。
2.4.1數(shù)據(jù)類型對(duì)象
數(shù)據(jù)類型對(duì)象是numpy.dtype類的實(shí)例。數(shù)組是一種數(shù)據(jù)類型署辉。嚴(yán)格來講哭尝,NumPy數(shù)組中的每個(gè)元素都要具有相同的數(shù)據(jù)類型剖煌。數(shù)據(jù)類型表明了數(shù)據(jù)占用的字節(jié)數(shù)材鹦,所以占用字節(jié)的具體數(shù)目一般存放在類dtype的itemsize屬性中逝淹。
a.dtype.itemsize
輸出結(jié)果:
4
2.4.2字符碼
啥是字符碼,我的理解就是用一個(gè)代碼表示數(shù)據(jù)類型桶唐,這樣可以簡(jiǎn)化程序栅葡,比如:
import numpy as np
from numpy import array
a = np.arange(7, dtype = 'f')
b = np.arange(7, dtype = "D")
print(a, b)
輸出結(jié)果:
[0. 1. 2. 3. 4. 5. 6.] [0.+0.j 1.+0.j 2.+0.j 3.+0.j 4.+0.j 5.+0.j 6.+0.j]
2.4.3Dtype構(gòu)造函數(shù)
創(chuàng)建數(shù)據(jù)類型時(shí),手段有很多欣簇。
- 可以使用Python自帶的常規(guī)浮點(diǎn)數(shù)型
- 可以使用字符碼規(guī)定單精度浮點(diǎn)數(shù)
- 可以用字符碼定義雙精度浮點(diǎn)數(shù)
- 可以向dtype構(gòu)造函數(shù)傳遞一個(gè)雙字符碼。其中坯约,第一個(gè)字符表示數(shù)據(jù)類型熊咽,第二個(gè)字符是一個(gè)數(shù)字,表示該類型占用的字節(jié)數(shù)闹丐。
import numpy as np
from numpy import array
print(np.dtype(np.float))
print(np.dtype('f'))
print(np.dtype('d'))
print(np.dtype('f8'))
輸出結(jié)果:
float64
float32
float64
float64
2.4.4dtype屬性
import numpy as np
t = np.dtype('Float64')
print(t.char)
print(t.type)
print(t.str)
輸出結(jié)果:
d
<class 'numpy.float64'>
<f8
其第一行返回其字符碼横殴;第二行返回其類型屬性;第三行中dtype的屬性str中保存的是一個(gè)表示數(shù)據(jù)類型的字符串卿拴,其中第一個(gè)字符描述的是數(shù)據(jù)類型衫仑,如果需要,后面會(huì)跟著字符碼和數(shù)組堕花,用來存儲(chǔ)每個(gè)數(shù)組元素所需的字節(jié)數(shù)惑畴。
2.5一維數(shù)組的切片和索引
一維NumPy數(shù)組的切片操作與Python列表的切片一樣。
import numpy as np
from numpy import array
a = np.arange(9)
print(a[3 : 7]) #指定下標(biāo)選擇數(shù)組的部分元素
print(a[:7 :2]) #制定下標(biāo)選擇元素航徙,并設(shè)定下標(biāo)每次遞增2
print(a[::-1]) #用負(fù)值下標(biāo)翻轉(zhuǎn)數(shù)組
輸出結(jié)果:
[3 4 5 6]
[0 2 4 6]
[8 7 6 5 4 3 2 1 0]
2.6處理數(shù)組形狀
前面,我們學(xué)習(xí)過reshape()函數(shù)陷虎,實(shí)際上到踏,除了數(shù)組形狀的調(diào)整外,數(shù)組的擴(kuò)充也是一個(gè)經(jīng)常碰到的乏味工作尚猿。
import numpy as np
b = np.arange(24).reshape(2, 3, 4)
print(b,"\n")
c = b.ravel()
print(c,"\n")
d = b.flatten()
print(d,"\n")
b.shape = (6, 4)
print(b,"\n")
e = b.transpose()
print(e,"\n")
b.resize((2, 12))
print(b,"\n")
輸出結(jié)果:
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
[[ 0 4 8 12 16 20]
[ 1 5 9 13 17 21]
[ 2 6 10 14 18 22]
[ 3 7 11 15 19 23]]
[[ 0 1 2 3 4 5 6 7 8 9 10 11]
[12 13 14 15 16 17 18 19 20 21 22 23]]
這里有一個(gè)細(xì)節(jié)問題:
- reshape:有返回值窝稿,所謂有返回值,即不對(duì)原始多維數(shù)組進(jìn)行修改凿掂;
- resize:無返回值伴榔,所謂有返回值,即會(huì)對(duì)原始多維數(shù)組進(jìn)行修改庄萎;
即這里resize()函數(shù)會(huì)直接修改原數(shù)組踪少,而不是輸出新的數(shù)值!
代碼中的函數(shù)都是處理對(duì)數(shù)組的形狀進(jìn)行處理:
- 拆解:ravel()函數(shù)將多維數(shù)組變成一維數(shù)組糠涛。
- 拉直:Flatten()函數(shù)功能與ravel()相同援奢,但是flatten()返回的是真實(shí)的數(shù)組,需要分配新的內(nèi)存空間忍捡;而ravel()函數(shù)返回的只是數(shù)組的視圖集漾。
- 用元組指定數(shù)組形狀:除了reshape()函數(shù)外切黔,還可以用元組來輕松定義數(shù)組的形狀
- 轉(zhuǎn)置:在線性代數(shù)中,矩陣的轉(zhuǎn)置操作非常常見具篇。轉(zhuǎn)置是一種數(shù)據(jù)變換方法纬霞,對(duì)于二維表而言,轉(zhuǎn)置就意味著行變成列驱显,列變成行诗芜。
- 調(diào)整大小,作用類似于reshape()秒紧,但是會(huì)改變所作用的數(shù)組绢陌。
2.6.1堆疊數(shù)組
從深度看,數(shù)組既可以橫向疊放熔恢,也可以豎向疊放脐湾。為此,可以使用vstack()叙淌、dstack()秤掌、hstack()、column_stack()鹰霍、row_stack()和concatenate()等函數(shù)闻鉴。
import numpy as np
a = np.arange(9).reshape(3, 3)
print(a,"\n")
b = 2 * a
print(b,"\n")
c = np.hstack((a, b)) #水平疊加
print(c,"\n")
d = np.concatenate((a, b), axis = 1) #用concatenate()函數(shù)參數(shù)axis = 1實(shí)現(xiàn)水平疊加效果
print(d,"\n")
e = np.vstack((a, b)) #垂直疊加
print(e,"\n")
f = np.concatenate((a, b), axis = 0) #用concatenate()函數(shù)參數(shù)axis = 0實(shí)現(xiàn)垂直疊加效果
print(f,"\n")
g = np.dstack((a, b)) #深度疊加
print(g, "\n")
oned = np.arange(2)
print(oned, "\n")
twice_oned = 2 * oned
print(twice_oned, "\n")
h = np.column_stack((oned, twice_oned)) #列式疊加
print(h, "\n")
i = np.column_stack((a, b)) #這種列式疊加有點(diǎn)類似于hstack水平疊加
print(i, "\n")
print(i == c,"\n")
j = np.row_stack((oned, twice_oned)) #行式疊加
print(j,"\n")
k = np.row_stack((a, b)) #這種列式疊加有點(diǎn)類似于vstack垂直疊加
print(k,"\n")
print(e == k,"\n")
輸出結(jié)果:
[[0 1 2]
[3 4 5]
[6 7 8]]
[[ 0 2 4]
[ 6 8 10]
[12 14 16]]
[[ 0 1 2 0 2 4]
[ 3 4 5 6 8 10]
[ 6 7 8 12 14 16]]
[[ 0 1 2 0 2 4]
[ 3 4 5 6 8 10]
[ 6 7 8 12 14 16]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 0 2 4]
[ 6 8 10]
[12 14 16]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 0 2 4]
[ 6 8 10]
[12 14 16]]
[[[ 0 0]
[ 1 2]
[ 2 4]]
[[ 3 6]
[ 4 8]
[ 5 10]]
[[ 6 12]
[ 7 14]
[ 8 16]]]
[0 1]
[0 2]
[[0 0]
[1 2]]
[[ 0 1 2 0 2 4]
[ 3 4 5 6 8 10]
[ 6 7 8 12 14 16]]
[[ True True True True True True]
[ True True True True True True]
[ True True True True True True]]
[[0 1]
[0 2]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 0 2 4]
[ 6 8 10]
[12 14 16]]
[[ True True True]
[ True True True]
[ True True True]
[ True True True]
[ True True True]
[ True True True]]
這里有一個(gè)細(xì)節(jié)問題:
堆疊函數(shù)的參數(shù)是一個(gè)元組的時(shí)候,要轉(zhuǎn)換兩個(gè)數(shù)組為一個(gè)元組茂洒,即用兩個(gè)括號(hào)將兩個(gè)數(shù)組括起來組成一個(gè)元組孟岛。
堆放數(shù)組的方法總結(jié)如下:
- 水平疊加
- 垂直疊加
- 深度疊加:這種方法是沿著第三個(gè)坐標(biāo)軸(縱向)的方向疊加一摞數(shù)組,可以在一個(gè)圖像數(shù)據(jù)的二維數(shù)組上疊加另一幅圖像的數(shù)據(jù)督勺。
- 列式堆疊
- 行式堆疊
2.6.2拆分NumPy數(shù)組
可以從縱向渠羞、橫向和深度方向來拆分?jǐn)?shù)組,相關(guān)函數(shù)有hsolit()智哀、vsplit()次询、dsplit()和split()。我們既可以把數(shù)組分成相同形狀的數(shù)組瓷叫,也可以從規(guī)定的位置開始切取數(shù)組屯吊。
import numpy as np
a = np.arange(9).reshape(3, 3)
print(a,"\n")
b = np.hsplit(a, 3) #橫向拆分
print(b,"\n")
c = np.split(a, 3, axis = 1) #相當(dāng)于調(diào)用參數(shù)axis = 1的split()函數(shù)
print(c,"\n")
d = np.vsplit(a, 3) #縱向拆分
print(d,"\n")
e = np.split(a, 3, axis = 0) #相當(dāng)于調(diào)用參數(shù)axis = 0的split()函數(shù)
print(e,"\n")
f = np.arange(27).reshape(3, 3, 3)
print(f,"\n")
g = np.dsplit(f, 3) #沿著深度方向分解數(shù)組,本例秩為3
print(g,"\n")
輸出結(jié)果:
[[0 1 2]
[3 4 5]
[6 7 8]]
[array([[0],
[3],
[6]]), array([[1],
[4],
[7]]), array([[2],
[5],
[8]])]
[array([[0],
[3],
[6]]), array([[1],
[4],
[7]]), array([[2],
[5],
[8]])]
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[18 19 20]
[21 22 23]
[24 25 26]]]
[array([[[ 0],
[ 3],
[ 6]],
[[ 9],
[12],
[15]],
[[18],
[21],
[24]]]), array([[[ 1],
[ 4],
[ 7]],
[[10],
[13],
[16]],
[[19],
[22],
[25]]]), array([[[ 2],
[ 5],
[ 8]],
[[11],
[14],
[17]],
[[20],
[23],
[26]]])]
2.6.3NumPy數(shù)組的屬性
除shape和dtype屬性外摹菠,ndarray類型的屬性還很多:
- ndim屬性存儲(chǔ)的是維度的數(shù)量
- size屬性用來保存元素的數(shù)量
- itemsize屬性可以返回?cái)?shù)組中各個(gè)元素所占用的字節(jié)數(shù)
- 如果想知道存儲(chǔ)整個(gè)數(shù)組所需的字節(jié)數(shù)量盒卸,可以求助于nbytes屬性,這個(gè)屬性值正好是itemsize屬性值和size屬性值之積次氨。
-T屬性的作用與transpose()函數(shù)相同 - 如果數(shù)組的秩(rank)小于2世落,那么所得只是一個(gè)數(shù)組的視圖:這里其實(shí)有個(gè)小問題,我認(rèn)為這個(gè)矩陣的秩為1,但是輸出確是2屉佳,所以這里也體現(xiàn)不了得到視圖的效果(因?yàn)橹葹?嘛)谷朝。比如:
a = np.array([[1, 2, 3, 4],
[2, 4, 6, 8]])
print(a.ndim)
輸出結(jié)果為2,這里我覺得這很明顯是秩為1的矩陣拔浠ā圆凰!
- 對(duì)于NumPy來說,復(fù)數(shù)用j表示
- real屬性將返回?cái)?shù)組的實(shí)部体箕,當(dāng)數(shù)組元素全為實(shí)數(shù)時(shí)专钉,就返回?cái)?shù)組本身
- imag屬性存放的是數(shù)組的虛部
- 如果數(shù)組含有復(fù)數(shù),那么它的數(shù)據(jù)類型將自動(dòng)變?yōu)閺?fù)數(shù)類型
- flat屬性可返回一個(gè)numpy.flatiter對(duì)象累铅,這是獲得flatiter對(duì)象的唯一方法跃须,但我們無法訪問flatiter的構(gòu)造函數(shù)⊥奘蓿可以通過flat[1, 3]獲取對(duì)象中的元素菇民,此外還可以給flat屬性賦值,不過需要注意的是投储,這個(gè)值將會(huì)覆蓋整個(gè)數(shù)組內(nèi)的所有元素的值第练。
import numpy as np
from numpy import array
a = np.arange(24).reshape(2, 12)
print(a,"\n")
print(a.ndim,"\n") #求其維度的數(shù)量
print(a.size,"\n") #求其保存元素的數(shù)量
print(a.itemsize,"\n") #返回?cái)?shù)組中各個(gè)元素所占用的字節(jié)數(shù)
print(a.nbytes,"\n") #整個(gè)數(shù)組所需的字節(jié)數(shù)量
print(a.size * a.itemsize,"\n")
a.resize(6, 4)
print(a,"\n")
print(a.T,"\n") #轉(zhuǎn)置
print(a.ndim,"\n") #這里矩陣的秩為什么是2!B贶瘛=刻汀!Q小Sの唷!?吞!V就骸!
a = np.array([1.j + 1, 2.j + 3])
print(a,"\n")
print(a.real,"\n") #返回?cái)?shù)組的實(shí)部
print(a.imag,"\n") #返回?cái)?shù)組的虛部
print(a.dtype,"\n") #返回復(fù)數(shù)的數(shù)據(jù)類型
print(a.dtype.str,"\n")
a = np.arange(4).reshape(2,2)
print(a,"\n")
b = a.flat #flat函數(shù)就像迭代器一樣讀取每個(gè)數(shù)組
print(b,"\n")
for it in b:
print(it,"\n")
print(a.flat[2],"\n")
print(a.flat[[1, 3]],"\n")
print(a,"\n")
a.flat[[1, 3]] = 7
print(a,"\n")
a.flat = 7
print(a,'\n')
輸出結(jié)果:
[[ 0 1 2 3 4 5 6 7 8 9 10 11]
[12 13 14 15 16 17 18 19 20 21 22 23]]
2
24
4
96
96
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
[[ 0 4 8 12 16 20]
[ 1 5 9 13 17 21]
[ 2 6 10 14 18 22]
[ 3 7 11 15 19 23]]
2
[1.+1.j 3.+2.j]
[1. 3.]
[1. 2.]
complex128
<c16
[[0 1]
[2 3]]
<numpy.flatiter object at 0x04AEAB70>
0
1
2
3
2
[1 3]
[[0 1]
[2 3]]
[[0 7]
[2 7]]
[[7 7]
[7 7]]
2.6.4數(shù)組的轉(zhuǎn)換
可以把NumPy數(shù)組轉(zhuǎn)換成Python列表嚼酝,使用tolist()函數(shù)。
- 轉(zhuǎn)換成列表
- astype()函數(shù)可以把數(shù)組元素轉(zhuǎn)換成制定類型
提示:當(dāng)complex類型轉(zhuǎn)換成int類型時(shí)竟坛,虛部將被丟棄闽巩,此外,還需要將數(shù)據(jù)類型的名稱以字符串的形式傳遞給astype()函數(shù)担汤。
import numpy as np
from numpy import array
a = np.array([1 + 1.j, 3 + 2.j])
b = a.astype(int)
print(b)
c = a.tolist()
print(c)
d = b.astype('complex')
print(d)
輸出結(jié)果:
[1 3]
[(1+1j), (3+2j)]
[1.+0.j 3.+0.j]
D:\Python\lib\site-packages\ipykernel_launcher.py:4: ComplexWarning: Casting complex values to real discards the imaginary part
after removing the cwd from sys.path.
2.7創(chuàng)建數(shù)組的視圖和拷貝
在NumPy的師姐中涎跨,視圖不是只讀的,因?yàn)槟悴豢赡苁刂A(chǔ)數(shù)據(jù)一動(dòng)不動(dòng)崭歧,關(guān)鍵在于要知道隅很,當(dāng)前處理的是共享的數(shù)組視圖,還是數(shù)組數(shù)據(jù)的副本率碾。舉例來說叔营,可以使用數(shù)組的一部分生成視圖屋彪。這意味著,如果先將數(shù)組的某部分賦予給一個(gè)變量绒尊,然后修改原數(shù)組中相應(yīng)位置的數(shù)據(jù)畜挥,那么這個(gè)變量的值也會(huì)隨之變化。我們可以根據(jù)著名的萊娜照片創(chuàng)建數(shù)組婴谱,然后創(chuàng)建視圖蟹但,隨后修改它。
因?yàn)槿R娜圖片已經(jīng)被scipy移除谭羔,這里用替換文件ascent代替:
import scipy.misc #從scipy中獲取圖像數(shù)組
import matplotlib.pyplot as plt #獲取畫圖matplotlib庫用于繪圖和顯示
ascent = scipy.misc.ascent() #獲取
acopy = ascent.copy()
aview = ascent.view()
plt.subplot(221)
plt.imshow(ascent)
plt.subplot(222)
plt.imshow(acopy)
plt.subplot(223)
plt.imshow(aview)
aview.flat = 0
plt.subplot(224)
plt.imshow(aview)
plt.show()
輸出結(jié)果:
哈哈這里反而產(chǎn)生了一個(gè)相悖的結(jié)論华糖,這里在程序結(jié)束部分修改視圖,同時(shí)改變了原來的圖片數(shù)組瘟裸,導(dǎo)致134圖都應(yīng)該變紫客叉,表明除了復(fù)制的數(shù)組,其他數(shù)組都被程序結(jié)尾的改變而改變景描,證明:視圖不是只讀的十办。但是這里原圖和視圖都沒變!3住向族!
2.8花式索引
花式索引是一種傳統(tǒng)的索引方法,它不使用整數(shù)或切片棠绘。這里我們利用花式索引將樓梯照片對(duì)角線上的值全部置0件相,相當(dāng)于沿著兩條交叉的對(duì)象線畫兩條黑線。
import scipy.misc
import matplotlib.pyplot as plt
ascent = scipy.misc.ascent()
xmax = ascent.shape[0]
ymax = ascent.shape[1]
ascent[range(xmax), range(ymax)] = 0 #給x和y值規(guī)定兩個(gè)不同的范圍
ascent[range(xmax-1, -1, -1), range(ymax)] = 0 #規(guī)定兩個(gè)不同的取值范圍氧苍,但是規(guī)則不變
plt.imshow(ascent)
plt.show()
輸出結(jié)果:
我們給x和y規(guī)定了兩個(gè)不同的取值范圍夜矗,這些范圍來索引圖片∪门埃花式索引是在一個(gè)內(nèi)部的NumPy迭代器對(duì)象的基礎(chǔ)上實(shí)現(xiàn)的紊撕,分3步完成。
(1)創(chuàng)建迭代器對(duì)象
(2)將迭代器對(duì)象綁定到數(shù)組
(3)經(jīng)由迭代器訪問數(shù)組元素赡突,利用位置列表進(jìn)行索引对扶。
我的解釋:把圖片轉(zhuǎn)換為數(shù)組后,定義max(512:黑色)惭缰,然后利用range()函數(shù)將對(duì)角線設(shè)置為黑色浪南。
2.9基于位置列表的索引方法
import scipy.misc
import matplotlib.pyplot as plt
import numpy as np
ascent = scipy.misc.ascent()
xmax = ascent.shape[0]
ymax = ascent.shape[1]
def shuffle_indices(size):
arr = np.arange(size)
np.random.shuffle(arr) #shuffle()函數(shù)將數(shù)組中的元素按隨機(jī)的索引號(hào)重新排列
return arr
xindices = shuffle_indices(xmax)
np.testing.assert_equal(len(xindices), xmax)
yindices = shuffle_indices(ymax)
np.testing.assert_equal(len(yindices), ymax)
plt.imshow(ascent[np.ix_(xindices, yindices)]) #畫出打亂后的索引
plt.show()
運(yùn)行結(jié)果:
這里解釋兩個(gè)函數(shù):
- shuffle函數(shù):
import random
list = [20, 16, 10, 5];
random.shuffle(list)
print(list)
random.shuffle(list)
print(list)
運(yùn)行結(jié)果:
[20, 16, 5, 10]
[10, 5, 16, 20]
- ix_()函數(shù)
這個(gè)函數(shù)可以根據(jù)多個(gè)序列生成一個(gè)網(wǎng)格,他需要一個(gè)一維序列作為參數(shù)漱受,并返回一個(gè)由NumPy數(shù)組構(gòu)成的元組络凿。
import numpy as np
np.ix_([0, 1], [2, 3])
運(yùn)行結(jié)果:
(array([[0],
[1]]), array([[2, 3]]))
2.10用布爾型變量索引NumPy數(shù)組
布爾型索引是根據(jù)布爾型數(shù)組來索引元素的方法,屬于花式索引系列。
import scipy.misc
import matplotlib.pyplot as plt
import numpy as np
ascent = scipy.misc.ascent()
def get_indices(size):
arr = np.arange(size)
return arr % 4 == 0
ascent = ascent.copy()
xindices = get_indices(ascent.shape[0])
yindices = get_indices(ascent.shape[1])
ascent[xindices, yindices] = 0
plt.subplot(211)
plt.imshow(ascent)
ascent2 = ascent.copy()
ascent2[((ascent > ascent.max()/4) & (ascent < 3 * ascent.max()/4))] = 0
plt.subplot(212)
plt.imshow(ascent2)
plt.show()
運(yùn)行結(jié)果:
1.定義函數(shù)絮记,在對(duì)角線上畫點(diǎn)摔踱,選擇的是照片對(duì)角線上可以被4整除的那些位置上的點(diǎn),然后僅繪出選定的那些點(diǎn)到千。
2.根據(jù)元素值的情況置0昌渤。選擇數(shù)組值結(jié)余最大值的1/4到3/4的那些元素將其置0.
這里有個(gè)小問題就是書中源代碼是會(huì)報(bào)錯(cuò)的,報(bào)錯(cuò)信息如下:
TypeError: ufunc 'bitwise_and' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
這是因?yàn)榈?8行的運(yùn)算優(yōu)先級(jí)問題憔四,在上述兩種情況下都加上()就沒問題了膀息。
2.11NumPy數(shù)組的廣播
當(dāng)操作對(duì)象的形狀不一樣時(shí),NumPy會(huì)盡力進(jìn)行處理了赵。
例如潜支,假設(shè)一個(gè)數(shù)組要跟一個(gè)標(biāo)量想乘,這時(shí)標(biāo)量需要根據(jù)數(shù)組的形狀進(jìn)行擴(kuò)展柿汛,然后才可以執(zhí)行乘法運(yùn)算冗酿,這個(gè)擴(kuò)展過程叫做廣播。
import scipy.io.wavfile
import matplotlib.pyplot as plot
import urllib.request
import numpy as np
response = urllib.request.urlopen('http://www.thesoundarchive.com/austinpowers/smashingbaby.wav')
print(response.info)
WAV_FILE = 'smashingbaby.wav'
filehandle = open(WAV_FILE, 'wb+')
filehandle.write(response.read())
filehandle.close()
sample_rate, data = scipy.io.wavfile.read(WAV_FILE)
print("Data type", data.dtype, "Shape", data.shape)
plt.subplot(2, 1, 1)
plt.title("Original")
plt.plot(data)
newdata = data * 0.2
newdata = newdata.astype(np.uint8)
print("Data type", newdata.dtype, "shape", newdata.shape)
scipy.io.wavfile.write("quiet.wav",
sample_rate, newdata)
plt.subplot(2, 1, 2)
plt.title("Quiet")
plt.plot(newdata)
plt.show()
輸出結(jié)果:
<bound method HTTPResponse.info of <http.client.HTTPResponse object at 0x0E290D10>>
Data type uint8 Shape (43584,)
Data type uint8 shape (43584,)
這個(gè)程序下載一個(gè)音頻文件络断,然后以此為基礎(chǔ)裁替,生成一個(gè)新的靜音版本。
1.讀取WAV文件
哈哈這里幸虧已經(jīng)看了爬蟲貌笨,也說明了數(shù)據(jù)獲取的重要性弱判,雖然這一章應(yīng)該focus在數(shù)據(jù)處理上,書中的代碼應(yīng)該修改urrlib2偉urrlib2.request锥惋,這是python3區(qū)別之前的地方之一昌腰,此外,書中的代碼對(duì)于寫入音頻文件如果用w模式會(huì)報(bào)錯(cuò):
TypeError: write() argument must be str, not bytes
這是因?yàn)椋?/p>
可能又是版本變化問題吧膀跌!這里通過爬蟲的形式從電影《王牌大間諜》中下載狂嚎式的歌曲遭商,Scipy中有一個(gè)wavfile子程序包,用來加載音頻數(shù)據(jù)捅伤,或者生成WAV格式的文件劫流。可以使用read()函數(shù)直接讀取文件丛忆,它返回一個(gè)數(shù)據(jù)陣列及采樣率祠汇。
2.回執(zhí)WAV原始數(shù)據(jù)
3.新建一個(gè)數(shù)組
現(xiàn)在,用NumPy生成一段寂靜的聲音蘸际,實(shí)際上就是將原數(shù)組乘以一個(gè)常數(shù),從而得到一個(gè)新數(shù)組徒扶,因?yàn)檫@個(gè)新數(shù)組的元素值肯定是變小了粮彤,這就是廣播術(shù)的用武之地。最后,我們要確保新數(shù)組和原數(shù)組的類型一致导坟。即WAV格式屿良。
4.寫入一個(gè)WAV文件中
5.繪制出新的WAV數(shù)據(jù)
6.展示原始的WAV文件中的數(shù)值圖像,以及數(shù)值變小后的新數(shù)組的圖像惫周。
可以聽一下效果尘惧!哈哈真的消音了。
2.12小結(jié)
本章递递,學(xué)習(xí)了NumPy的基礎(chǔ)知識(shí):數(shù)據(jù)類型和數(shù)組喷橙。數(shù)組有很多屬性,這些屬性都是用來描述該數(shù)組的特性的登舞。
與Python標(biāo)準(zhǔn)的列表相比贰逾,NumPy數(shù)組使用的切片和索引方法更加高效,此外菠秒,NumPy數(shù)組還能夠?qū)Χ嗑S數(shù)組進(jìn)行處理疙剑。
我們可以用各種方式改變數(shù)組的形狀,如堆疊践叠、重定尺寸言缤、重塑形狀以及拆分等。
有了這些基礎(chǔ)知識(shí)后禁灼,從第三章開始管挟,就要學(xué)習(xí)如何通過常見的函數(shù)來分析數(shù)據(jù)了,這將涉及主要統(tǒng)計(jì)函數(shù)和數(shù)值函數(shù)的用法匾二。
咳咳
數(shù)組學(xué)了很多遍哮独,但是這次應(yīng)該是比較系統(tǒng)的整理了一遍,Python這個(gè)語法就是很多察藐,知道怎么用但是真的實(shí)際用就笨手笨腳皮璧,還是不能熟能生巧!
這一章中對(duì)圖片和音頻的數(shù)據(jù)處理實(shí)例說明數(shù)據(jù)處理不是簡(jiǎn)簡(jiǎn)單單的處理數(shù)據(jù)分飞,數(shù)據(jù)類型非常多悴务,通過數(shù)據(jù)轉(zhuǎn)換,可以將現(xiàn)實(shí)世界中的很多問題轉(zhuǎn)換為數(shù)學(xué)運(yùn)算的方式解決譬猫。
線性代數(shù)補(bǔ)考才過讯檐,現(xiàn)在重新需要用到了,還有點(diǎn)慌染服,哈哈别洪,秩都不會(huì)算了!
記錄可以讓我不囫圇吞棗式的看書柳刮,邊看邊記錄可能也會(huì)記的更深一點(diǎn)吧哈哈挖垛!真的喜歡簡(jiǎn)書的這種書寫方式痒钝,
?