python數據分析(二) python numpy--數組和矢量運算--數組對象


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')

 


 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM