Numpy
numpy是數值計算最重要的基礎包,幾乎所有的科學運算的模塊底層所用的都是numpy數組。
Numpy本身沒有提供多么高級的數據分析功能,他所提供的功能主要是:
1.具有矢量算術運算(用數組表達式代替循環的做法通常稱為矢量化),矢量化計算因為不使用循環,因此速度會快1到兩個數量級
2.廣播。(不同大小的數組之間的運算)
3.提供了對整組數據進行快速運算的標准函數。
4.用於讀寫磁盤數據的工具以及操作內存映射文件的工具(將數組保存及讀取為文件,mmap系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間后,進程可以像訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作)
5.線性代數,隨機數生成,以及傅里葉變換的功能。
Numpy 和pandas的dataframe
NumPy是Python語言的一個擴充程序庫。支持高級大量的維度數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫。
Pandas是基於NumPy 的一種工具,該工具是為了解決數據分析任務而創建的。Pandas 納入了大量庫和一些標准的數據模型,提供了高效地操作大型數據集所需的工具。Pandas提供了大量能使我們快速便捷地處理數據的函數和方法。
Numpy本身沒有提供多少數據分析功能,但是理解Numpy數組以及面向數組的計算會有助於更加高效的使用pandas等科學計算和數據分析工具。
Numpy數組
本篇我們將主要討論數組對象ndarray以及如何創建一個數組對象。
(1)ndarray對象
numpy當中的數組是一個ndarray對象,ndarray對象是用於存放同類型元素的多維數組,是numpy中的基本對象之一,另一個是func對象。ndarray 中的每個元素在內存中都有相同存儲大小的區域,而且
Numpy 就是 C 的邏輯, 創建存儲容器 “Array” 的時候是尋找內存上的一連串區域來存放, 而 Python 存放的時候則是不連續的區域, 這使得 Python 在索引這個容器里的數據時不是那么有效率。
以下是一個例子,比較含有100萬的整數的list和array全部乘以2的時間
In [7]: import numpy as np In [8]: my_arr = np.arange(1000000) In [9]: my_list = list(range(1000000))
list對象和array數組對象中的元素全部乘以2.
In [10]: %time for _ in range(10): my_arr2 = my_arr * 2 CPU times: user 20 ms, sys: 50 ms, total: 70 ms Wall time: 72.4 ms In [11]: %time for _ in range(10): my_list2 = [x * 2 for x in my _list] CPU times: user 760 ms, sys: 290 ms, total: 1.05 s Wall time: 1.05 s
ndarray 內部由以下內容組成:
-
一個指向數據(內存或內存映射文件中的一塊數據)的指針。
-
數據類型或 dtype,描述在數組中的固定大小值的格子。
-
一個表示數組形狀(shape)的元組,表示各維度大小的元組。
-
一個跨度元組(stride),其中的整數指的是為了前進到當前維度下一個元素需要"跨過"的字節數,默認創建array是以row即order=C方式創建,所以此處的跨度元組默認指的是每一行的字節數。
a = np.array([[0,1,2],[3,4,5],[6,7,8]], dtype=np.float32)

數據存儲區域保存着數組中所有元素的二進制數據,dtype對象則知道如何將元素的二進制數據轉換為可用的值。數組的維數、大小等信息都保存在ndarray數組對象的數據結構中。
strides中保存的是當每個軸的下標增加1時,數據存儲區中的指針所增加的字節數。例如圖中的strides為12,4,即第0軸的下標增加1時,數據的地址增加12個字節:即a[1,0]的地址比a[0,0]的地址要高12個字節,正好是3個單精度浮點數的總字節數;第1軸下標增加1時,數據的地址增加4個字節,正好是單精度浮點數的字節數
(2)創建ndarray
創建一個 ndarray 只需調用 NumPy 的 array 函數即可:
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

特別需要解釋的是order,在我們看來的 2D Array, 如果追溯到計算機內存里, 它其實是儲存在一個連續空間上的. 而對於這個連續空間, 我們如果創建 Array 的方式不同, 在這個連續空間上的排列順序也有不同. 這將影響之后所有的事情! 我們后面會用 Python 進行運算時間測試.
在 Numpy 中, 創建 2D Array 的默認方式是 “C-type” 以 row 為主在內存中排列, 而如果是 “Fortran” 的方式創建的, 就是以 column 為主在內存中排列
a = np.zeros((200, 200), order='C') b = np.zeros((200, 200), order='F') N = 9999 def f1(a): for _ in range(N): np.concatenate((a, a), axis=0) def f2(b): for _ in range(N): np.concatenate((b, b), axis=0) t0 = time.time() f1(a) t1 = time.time() f2(b) t2 = time.time() print((t1-t0)/N) # 0.000040 print((t2-t1)/N) # 0.000070
row 為主的存儲方式, 如果在 row 的方向上合並矩陣, 將會更快. 因為只要我們將思維放在 1D array 那, 直接再加一個 row 放在1D array 后面就好了, 所以在上面的測試中, f1
速度要更快. 但是在以 column 為主的系統中, 往 1D array 后面加 row 的規則變復雜了, 消耗的時間也變長. 如果以 axis=1
的方式合並, “F” 方式的 f2
將會比 “C” 方式的 f1
更好。
創建數組的其他方式:
np.zeros,np.empty,np.ones 都可以分別用來創建全為0的數組,為空的數組(只分配內存空間不賦值),全為一的數組等。
In [29]: np.zeros(10) Out[29]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. ]) In [30]: np.zeros((3, 6)) Out[30]: array([[ 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0.]]) In [31]: np.empty((2, 3, 2)) Out[31]: array([[[ 0., 0.], [ 0., 0.], [ 0., 0.]], [[ 0., 0.], [ 0., 0.], [ 0., 0.]]])
下表列出了其他的一些用於創建數組的函數
NumPy 數據類型
numpy 支持的數據類型比 Python 內置的類型要多很多,基本上可以和 C 語言的數據類型對應上,其中部分類型對應為 Python 內置的類型。下表列舉了常用 NumPy 基本類型。

對於narray對象的dtype定義有兩種方式,一種是在創建時,第二種是使用astype函數進行修改,當你創建numpy的數組對象且沒有指定dtype,np.arrary會嘗試為這個新建的數組推斷出一個合適的類型,因為ndarray面向的是數值運算,默認創建的類型都是float64(浮點數)。
使用astype方法進行轉換:
In [37]: arr = np.array([1, 2, 3, 4, 5]) In [38]: arr.dtype Out[38]: dtype('int64') In [39]: float_arr = arr.astype(np.float64) In [40]: float_arr.dtype Out[40]: dtype('float64')