1.列表與數組
在python的基礎語言部分,我們並沒有介紹數組類型,但是像C、Java等語言都是有數組類型的,那python中的列表和數組有何區別呢?
一維數據:都表示一組數據的有序結構
區別:
列表:數據類型可以不同,如:【3.1413,'pi',3.1404,[3.1402,2.34],'3.2376'】
數組:數據類型相同 。如【3.14,34.34,3433.3,343.23】
二維數據:二維數據由多個一維數據構成,是一維數據的集合形式!表格是典型的二維數據!
注意:表格的表頭,可以是二維數據的一部分,也可以作為二維數據以外的一部分,這取決於用戶對於二維數據的定義和使用!
多維數據:多維數據是在一維數據或者二維數據的基礎上拓展形成的!
注意:上面一個是2016年的排名表格,還有一個是2017年的一個排名表格,從這兩個表格的跨度來看,這里增加了一個時間維度,從而構成一個多維數據!如果隨着時間的發展,那么在時間維度上,數據就會繼續累積下去!
除了一維、二維、多維數據之外,還有一種多維數據!高維數據與一維、二維、多維數據不同,高維數據僅使用最基本的二元關系展示數據間的復雜結構。
如下所示:這就是一個高緯數據,這里面沒有數據的規整的組織方式,但是卻有數據之間的包含關系、數據之間的並列關系,以及數據之間的屬性關系等形成的一個數據的組織方式,這里面都是鍵值對的單元,高維數據就是有鍵值對將數據組織起來。
2.數據維度的python表示
注意:對於一維數據我們用列表和集合表示,列表是有序的,而集合是無序的。對於python中的二維或者多維數據,我們用列表表示,而列表的元素還可以是列表,這就是一種多維列表,用多維列表來對應多維元素!
對於高維數據,我們使用字典或者數據表示的格式來表示;字典類型也是由鍵值對構成的一個數據類型,它與高維數據的表達方式基本上是一致的!
我們知道現在公認的數據表達格式主要有3種: JSON,XML,YAML格式,這樣的格式可以用來組織數據,是他們之間形成數據的維度和關系。
3.NumPy的數組對象: ndarray
下面我們介紹一個numpy庫以及numpy中的ndarray數組類型!
NumPy是一個開源的Python科學計算基礎庫。它也是整個python目前科學計算和數據分析的最基礎的第三方庫!NumPy提供了很多功能,主要包含以下一些方面:
1.一個強大的N維數組對象ndarray
2.一組廣播功能函數,用來在數組之間進行計算
3.整合C/C++/Fortran等代碼的工具
4.線性代數、傅里葉變換、隨機數生成等功能!
NumPy是SciPy,Pandas等數據處理或科學計算庫的基礎。
為了更好的進行科學計算,我們首先要理解NumPy的構成原理,以及其中最關鍵的數據對象ndarray!
1.NumPy的引用:import numpy as np #注意:這里的np是引入模塊numpy的別名,盡管別名可以省略或更改,建議使用上述約定的別名。【如果我們不使用別名,而是直接使用numpy,這樣每次調用函數的時候都得是numpy.的方式,代碼較長,如果我們使用的是其它別名,那么其它程序員未必熟悉,所以這里我們建議使用的別名為np】
2.python中的數據對象ndarray![有些學員可能會有疑問,在python中我們已經有了列表類型,而列表類型可以表示一維數據、二維數據、多維數據,那么我們為什么需要一個額外的數組類型呢?這里我們給大家舉個例子,如下所示:]
如果用傳統的python語法,我們來定義:
在上述的運算方式中,我們還是將我們的關注點放在一個一個元素之間的運算上,這並不是一種科學計算的思想方式!,而NumPy使用了另外一種思路,如下所示:
這時在NumPy進行運算的時候沒有使用循環!我們的基本思想是將一維數組A和一維數組B當做兩個數據,這兩個數據在他們維度相同的時候,他們可以直接進行運算!程序幫我們把這兩個數據中的每一個元素進行了運算,而編程的程序員只需要考慮A和B只是一個數據就可以啦!這是NumPy中N維數組對象所使用的一個基本原理!
所以對N維數組對象ndarray的一些說明如下:
1.數組對象可以去掉元素間運算所需要的循環,使一維數據更向單個數據,也使得我們程序員編寫代碼處理數據的程序變得十分簡單!
2.通過設置專門的數組對象,經過優化,可以提升這類應用的運算速度,這里同學們可能還不知道,NumPy的底層實現是用C來完成的,也就是說在進行數組運算的時候,底層的C語言會提供非常高效和快速的運算,這樣會使得在進行大規模運算的時候,運算時間會比較少!
例如:觀測一個現象,每一次它的值都可能是一個整數或者浮點數,他們都是統一的!因此,數組對象采用相同的數據類型,有助於節省運算和存儲空間,因為對程序來講,當它的類型是確定的,那我可能就知道它使用的內存空間是多少,這樣在內存分配和存儲空間的使用上,就可以做預判,使得空間的使用很有效,所以呢,一方面是在編程上,NumPy使得程序員可以在批量數據處理時得到了簡化,一方面在運算性能上,NumPy可以由底層的C語言甚至更底層的運算方法來提高他的運算速度。因此Numpy成為了Python中支持科學計算和數據處理的最基礎的庫。
我們來進一步介紹ndarray這個數據類型!
數組的下標是從0開始,這點是和列表一致的!我們來看一下ndarray實例,如下所示:(這里需要注意的是,在數據處理這里,我們使用的解釋器是IPython,因此我么要熟悉IPython的交互時提示符,如由in、out、[]等組成,如下所示:
這里面展示了用戶輸入的和程序輸出的結果!對於ndarray這里有兩個基本的概念:
在軸上每個維度的數據存儲在其中,秩表示軸的數量,也就是這個數組類型有多少個維度!這兩個基本概念是描述ndarray類型的基本向量和方式!ndarray對象一共有5個基本的運算屬性:
如下為ndarray實例:
注意:上面的返回值dtype('int32'),其中的int32在基本的python數據類型中是不存在的,在ndarray中還有很多這樣的類型,如下所示:
以上整數類型是有正負之分的,還有一部分整數是沒有正負之分的,我們稱之為無符號整數,如下所示:
ndarray還支持復數類型,如下所示:
我們知道在python基礎數據類型部分,python只支持一種整形,一種浮點型,和一種復數類型,那為什么這里的ndarray支持這么多的類型呢?
我們說ndarray對象都是相同的,也就是一種同質的數組類型,事實上ndarray也可以包含非同質的元素。比如我們生成一個數組,如下所示:
注意:上面的x.shape只返回了行數,並沒有返回列數,因為是非同質的,所以列數不固定了,而且x.dtype返回的是o,也就是說是對象類型。
4.ndarray數組的創建和變換
ndarray數組的創建方法:
1.從Python中的列表、元組等類型創建ndarray數組。
2.使用NumPy中函數創建ndarray數組,如:arange,ones,zeros等。
3.從字節流(raw bytes)中創建ndarray數組。
4.從文件中讀取特定格式,創建ndarray數組。
下面我們逐一進行講解:
利用Python中的列表、元組等類型創建ndarray數組,如下所示:
x = np.array(list/tuple)
x = np.array(list,tuple,dtype = np.float32)
這里我們使用dtype來指定數組元素的數據類型,當np.array()不指定dtype時,NumPy將根據讀入數據情況關聯一個dtype類型。例如,假如讀入的數據都是整數,那么NumPy就會指定dtype為整數類型。如下:
2.創建ndarray最常用的方法是使用NumPy中函數創建ndarray數組,如下所示:
注意:python中有一個range()函數可以生成一個遞增的序列,那么同樣在ndarray中也有一個這樣的方法就是np.arange(n)方法,np.arrange(n)方法會返回一個ndarray類型,元素是從0到n-1的整數類型。
而np.ones(shape)可以根據數組的shape形狀,形成一個全1的數組。其中shape為元組類型,比如,我們希望定義一個2行3列的二維數據,那么我們就可以shape寫為(2,3)
np.zeros(shape)的用法同np.ones(shape)方法。
這里需要注意:向ones、zeros、eye()等方法生成的數組元素類型都是浮點數類型的,除非我們自己通過dtype來指定,而arrange()函數生成的數組元素是整數類型的,具體如下所示:
我們也可以使用它們生成多維數組,例如:我們可以使用np.ones生成一個(2,3,4)這樣形狀的數組,同時還可以使用x,shape返回它的形狀。
我們可以看到2,3,4分別表示的是:在最外層的元素中,有2個元素,每一個元素又有3個維度,那每個維度下又有4個元素。所以這樣的shape是由數組的最外層到最內層逐漸變化的一個數據維度的一個表示方式。
除了上述的幾個函數,還有幾個和他們很類似的幾個函數:
這三個函數在進行大規模科學計算的時候,特別重要!此外NumPy中又提供了兩個創建ndarray數組的常用方法,分別是:
對於np.linspace()也就是說:給出一個起始值和一個結束值,給出一個你想生成的數組的個數,那么通過這個函數就能生成一個數組。例如:
上面的a = np.linspace(1,10,4)表示我們想生成的數組的起始元素是1,終止元素是10,希望生成4個元素,這時候生成的數組是array([1,4,7,10])!但是使用linspace()生成的數組在不限定元素類型的時候,生成的數據元素是浮點數。在linspace()函數中有一個屬性是endpoint,這個屬性表示:最后一個元素10是否是生成的4個元素中的一個,如果是False,表示不是其中一個,如果是True表示是其中一個。如上b所示!在不使用endpoint這個參數的時候,我們看到a是使用最后一個元素10作為4個元素中的一個,這也是默認的情況,如果我們將endpoint置為False,那么10 將不作為最后一個元素出現!最后我們還可以使用concatenate()函數將這兩個數組合並起來形成一個新的數組。我們看到新數組中既包含了數組a中的元素,也包含了數組b中的元素!
這里有些學生可能會有疑問,為什么NumPy每一次都將生成的元素類型作為浮點數呢?
因為NumPy是用於科學計算的一個庫,而在科學計算中,我們往往使用的數據都是浮點數。比如我們進行兩個數運算加減乘除,必然可能會出現浮點數,我們觀察一個情況獲得的值,比如光照值,溫度值等都是浮點數。我們很難在一個應用中發現都是整數的情況,因此除了arrange()函數外,NumPy在幾乎所有的函數生成數組的時候元素都是浮點型的。
對於一個創建后的ndarray數組,我們可以改變它的維度和元素類型,如下所示:
我們看一下維度變換的一些方法,如下所示:
這里同學們要仔細體會,使用什么方法是不改變原數組的,使用什么方法是要改變原數組的,這些在科學計算中特別重要,使用的時候要特別注意!
下面我們看一個例子:我們使用np.ones()方法生成一個(2,3,4)結構的數組,同時指定元素數據類型為整型,然后把這個數組賦值給變量a!
然后使用a.reshape()將一個3維數組改為2維數組,如下所示:
大家可以看到reshape()之后數組的元素個數和reshape之前的數組的元素個數是沒有發生變化的,而且a本身沒發生變化,而只是返回值為一個新數組!如果使用a.resize()方法,如下所示:
大家可以看到a數組是發生變化的,所以大家要特別注意:a.reshape()是不改變原數組卻新生成一個新數組返回,而a.resize()是直接改變的這個數組,我們可以使用a.flatten()將(2,3,4)這樣的多維數組降維為一維數組。如下所示:當我們再使用a的時候我們發現a其實並沒有什么變化!而b是被降維之后的一維數組。
NumPy提供了一個改變ndarray數組類型的一個函數,叫astype(),它的使用方式如下所示:
例子:
上面的這種寫法要注意:在NumPy中,實際上沒有數據類型為np.int類型的,np.int代表的是整數類型這一類,那么程序會將元素解析為整數類型,但是是解析為int-32呢還是int-64呢,那么是由程序自動調節的,所以我們可以簡寫為np.int,而不必具體到int-8,int-16,int-32,所以此時的a是(2,3,4)維,元素類型為整數的一個數組。下面我們把整數類型變換成浮點數類型,如下所示:
np.float和np.int一樣可以代表一類浮點數類型。然后將b輸出可以看到b中的每一個元素都是浮點數類型。
注意,對於新數組的任何使用與原數組無關!新數組是原始數組的一個數據的拷貝,換句話說,我們可以通過astype()來做一個原始數組的拷貝!通過astype()可以改變原始數組的類型。這個在我們實際應用中,可能會帶來性能上的變化和存儲空間上的節省。
此外,ndarray數組也可以轉換成一個python中的列表,轉變方式就是使用ndarray的一個方法tolist()
也就是:
如上所示:a數組是一個(2,3,4)維度的數組,它的每一個元素都是25,並且將dtype類型定義為int32,每個元素是一個整數類型,然后看一下a的值,然后我們可以通過a.tolist()將這樣一個NumPy的數組轉換成一個列表,我們看到列表與數組的不同僅僅在於,列表是python中最原始的一種數據類型。那么這種類型中可能占用的空間和運行的速度會比NumPy慢很多,但是說與一些傳統的或者說原生的python語言語法相適應的程序中,像列表的轉換也是很常見的!
5.ndarray數組的操作
這里所說的操作是指對數組的索引和切片
注意:python的列表提供了從最左側編號0開始,向右遞增,或者從最右側-1開始,向左遞減兩種索引方式!那么這兩種方式在ndarray的數組中都可以使用!獲得一維數組的切片,我們這里使用兩個冒號的方式獲得!
Numpy中的元素是從第0個開始的!
如下所示:
這里可以看到我們先生成一個一維數組,然后將一維數組轉換成(2,3,4)維度的一個3維數組,然后我們通過a[1,2,3]來指定各個維度上元素的序號【例如這里的a[1,2,3]在第一個維度上我們指定第一個元素,在第2個維度上我們指定第2個元素,在第3個維度上我們指定第3個元素,索引我們可以看到最終a[1,2,3]取得的值為23】,從而獲取各個維度相對應的元素,因為NumPy中數組的元素是從0開始的!當然還可以和列表一樣從右向左從-1開始依次遞減的方式進行!
如下所示:我們還是使用a數組
我們在一維數組【和列表類似】中切片使用的是兩個冒號組成的這樣的邏輯,那么這樣的方法在多維數組中同樣存在,所謂的多維數組切片,也就是在每個維度上,用戶給出一個切片空間,那么將不同的切片空間組織起來形成的一個子數據集的獲取方式,如下所示:
例如上面的a[:,1,-3]表示的是不管第一個維度是什么,而第二個維度的索引要求為1,而第三個維度的索引為-3,最終就取到了【5,17】,實際上對於3位數組,我們這里還好理解,如果有更多維度的數據,那么理解起來可能就不會那么直觀了!所以每次切片的時候,同學們要慎重和小心的選擇你使用的參數,但是在每一個維度上的參數都是可以通過兩個冒號的邏輯來去確定和使用的!