NumPy之:NumPy简介教程
文章目錄
- 簡介
- 安裝NumPy
- Array和List
- 創建Array
- Array操作
- sort
- concatenate
- 統計信息
- reshape
- 增加維度
- index和切片
- 從現有數據中創建Array
- 算數運算
- 其他有用操作
- 矩陣
- 生成隨機數
- unique
- 矩陣變換
- 反轉數組
- flatten 和 ravel
- save 和 load
- CSV
簡介
NumPy是一個開源的Python庫,主要用在數據分析和科學計算,基本上可以把NumPy看做是Python數據計算的基礎,因為很多非常優秀的數據分析和機器學習框架底層使用的都是NumPy。比如:Pandas, SciPy, Matplotlib, scikit-learn, scikit-image 等。
NumPy庫主要包含多維數組和矩陣數據結構。 它為ndarray(一個n維數組對象)提供了對其進行有效操作的方法。 NumPy可以用于對數組執行各種數學運算。 并且提供了可在這些數組和矩陣上運行的龐大的高級數學函數庫。
安裝NumPy
有很多方式可以按照NumPy:
pip install numpy如果你使用的是conda,那么可以:
conda install numpy或者直接使用Anaconda. 它是一系列數據分析包的集合。
Array和List
Python中有一個數據類型叫做List,list中可以存儲不同種類的對象。在應用程序中這樣做沒有什么問題,但是如果是在科學計算中,我們希望一個數組中的元素類型必須是一致的,所以有了NumPy中的Array。
NumPy可以快速的創建Array,并且對其中的數據進行操作。
NumPy中的Array要比Python中的List要快得多,并且占用更少的內存空間。
看下兩者之間的性能差異:
In [1]: import numpy as np...: my_arr = np.arange(1000000)...: my_list = list(range(1000000))...: %time for _ in range(10): my_arr2 = my_arr * 2...: %time for _ in range(10): my_list2 = [x * 2 for x in my_list]...: CPU times: user 12.3 ms, sys: 7.88 ms, total: 20.2 ms Wall time: 21.4 ms CPU times: user 580 ms, sys: 172 ms, total: 752 ms Wall time: 780 ms上面的例子對一個包含一百萬的數據進行乘2操作,可以看到,使用NumPy的效率是Python的幾十倍,如果在大型數據項目中這個效率會造成非常大的性能影響。
創建Array
上面的例子中,我們已經創建了一個array,使用的是np.arange方法。
我們還可以通過List來創建Array,List可以是一維列表,也可以是多維列表:
>>> a = np.array([1, 2, 3, 4, 5, 6])>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])和List一樣,Array也可以通過index來訪問:
>>> print(a[0]) [1 2 3 4]接下來我們介紹幾個常用的名詞:
- vector — 表示的是一維數組
- matrix — 表示的是二維數組
- tensor — 表示的是三維或者更高維度的數組
在NumPy中維度也被稱之為 axes 。
下面我們來看下其他幾種創建Array的方法:
最簡單的就是np.array,之前的例子中我們已經提到過了。
如果要快速的創建都是0 的數組,我們可以使用zeros:
>>> np.zeros(2) array([0., 0.])或者都填充為1:
>>> np.ones(2) array([1., 1.])還可以創建空的數組:
In [2]: np.empty(2) Out[2]: array([0. , 2.00389455])注意,empty方法中的內容并不一定是空的,而是隨機填充數據,所以我們在使用empty創建數組之后,一定要記得覆蓋其中的內容。使用empty的好處就是創建的速度比較快。
還可以在range范圍內填充數組:
In [3]: np.arange(10) Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])可以指定間隔:
In [4]: np.arange(1,10,2) Out[4]: array([1, 3, 5, 7, 9])使用linspace可以創建等分的數組:
In [5]: np.linspace(0, 10, num=5) Out[5]: array([ 0. , 2.5, 5. , 7.5, 10. ])默認情況下創建的數組內容類型是np.float64,我們還可以將其切換成整數:np.int64
In [6]: x = np.ones(2, dtype=np.int64)In [7]: x Out[7]: array([1, 1])Array操作
sort
我們可以使用sort對數組進行排序:
In [8]: arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])In [10]: np.sort(arr) Out[10]: array([1, 2, 3, 4, 5, 6, 7, 8])sort是對Array中的元素進行排序, 除了sort之外還有其他的一些排序的方法。
還可以使用argsort,argsort是一種間接排序的方法,他返回的是排序好的原數組的index:
In [11]: x = np.array([10, 5, 6])In [12]: np.argsort(x) Out[12]: array([1, 2, 0])上面我們對array進行argsort,排序之后應該返回,5,6,10。 5的index是1,6 的index是2,10的index是0,所以返回1,2,0。
lexsort和argsort一樣都是間接排序法,返回的都是排序過后的index,不同是lexsort 可以進行多key的排序。
surnames = ('Hertz', 'Galilei', 'Hertz') first_names = ('Heinrich', 'Galileo', 'Gustav') ind = np.lexsort((first_names, surnames)) ind array([1, 2, 0])上面的lexsort是先按照surnames排序,然后再按照first_names進行排序。
lexsort 的排序順序是從后到前。也就是最后一個傳入的key最先排序。
searchsorted用來查找要插入元素的index值,舉個例子:
np.searchsorted([1,2,3,4,5], 3) 2 np.searchsorted([1,2,3,4,5], 3, side='right') 3 np.searchsorted([1,2,3,4,5], [-10, 10, 2, 3]) array([0, 5, 1, 2])partition是對要排序的數據進行分割,舉個例子:
a = np.array([3, 4, 2, 1]) np.partition(a, 3) array([2, 1, 3, 4])第一個參數是一個Array,第二個參數是要分隔的基準元素,這個基準元素的位置和排序過后的位置是一樣的,其他的元素比基準元素小的放在前面,比基準元素大的放在后面。
還可以按照多個元素進行分割:
np.partition(a, (1, 3)) array([1, 2, 3, 4])concatenate
concatenate用來連接多個數組。
>>> a = np.array([1, 2, 3, 4]) >>> b = np.array([5, 6, 7, 8])>>> np.concatenate((a, b)) array([1, 2, 3, 4, 5, 6, 7, 8])還可以連接多維數組:
>>> x = np.array([[1, 2], [3, 4]]) >>> y = np.array([[5, 6]]) >>> np.concatenate((x, y), axis=0) array([[1, 2],[3, 4],[5, 6]])統計信息
ndarray.ndim 用來統計數組的維數:
>>> array_example = np.array([[[0, 1, 2, 3], ... [4, 5, 6, 7]], ... ... [[0, 1, 2, 3], ... [4, 5, 6, 7]], ... ... [[0 ,1 ,2, 3], ... [4, 5, 6, 7]]]) >>> array_example.ndim 3ndarray.size 用來統計數組中的元素個數:
>>> array_example.size 24ndarray.shape 輸出數組的形狀:
>>> array_example.shape (3, 2, 4)說明上面的數組是一個3 * 2 * 4 的數組。
reshape
使用reshape可以重新構造一個數組。
>>> a = np.arange(6) >>> print(a) [0 1 2 3 4 5]>>> b = a.reshape(3, 2) >>> print(b) [[0 1][2 3][4 5]]上面我們將一個一維的數組轉成了一個3* 2 的數組。
reshape還可以接受多個參數:
>>> numpy.reshape(a, newshape=(1, 6), order='C') array([[0, 1, 2, 3, 4, 5]])第一個參數是要重構的數組,第二個參數新的shape,order可以取三個值,C,F或者A。
C表示按照C的index方式進行排序,F表示按照Fortran的index方式進行排序。A表示自動選擇。
在Fortran中,當移動存儲在內存中的二維數組的元素時,第一個索引是變化最快的索引。 當第一個索引更改時移動到下一行時,矩陣一次存儲一列。另一方面,在C中,最后一個索引變化最快。
增加維度
np.newaxis可以給現有的數組增加一個維度:
>>> a = np.array([1, 2, 3, 4, 5, 6]) >>> a.shape (6,)>>> a2 = a[np.newaxis, :] >>> a2.shape (1, 6)>>> col_vector = a[:, np.newaxis] >>> col_vector.shape (6, 1)還可以使用expand_dims來指定axis的位置:
>>> b = np.expand_dims(a, axis=1) >>> b.shape (6, 1)>>> c = np.expand_dims(a, axis=0) >>> c.shape (1, 6)index和切片
數組的index和切片跟Python中的list是類似的:
>>> data = np.array([1, 2, 3])>>> data[1] 2 >>> data[0:2] array([1, 2]) >>> data[1:] array([2, 3]) >>> data[-2:] array([2, 3])除此之外,數組還支持更多更強大的index操作:
>>> a = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])>>> print(a[a < 5]) [1 2 3 4]上面我們找出了a中所有元素小于5的值。
In [20]: a<5 Out[20]: array([[ True, True, True, True],[False, False, False, False],[False, False, False, False]])可以看到a< 5 其實返回的也是一個數組,這個數組的元素shape和原數組是一樣的,只不過里面的值是true和false,表示是否應該被選擇出來。
同樣的,我們可以挑出所有大于5的元素:
>>> five_up = (a >= 5) >>> print(a[five_up]) [ 5 6 7 8 9 10 11 12]選出所有可以被2整除的數:
>>> divisible_by_2 = a[a%2==0] >>> print(divisible_by_2) [ 2 4 6 8 10 12]還可以使用 & 和 | 運算符:
>>> c = a[(a > 2) & (a < 11)] >>> print(c) [ 3 4 5 6 7 8 9 10]還可以使用nonzero來打印出滿足條件的index信息:
In [23]: a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])In [24]: b = np.nonzero(a < 5)In [25]: b Out[25]: (array([0, 0, 0, 0]), array([0, 1, 2, 3]))>>> print(a[b]) [1 2 3 4]上面返回的元組中,第一個值表示的是行號,第二個值表示的是列。
從現有數據中創建Array
我們可以使用 slicing , indexing,np.vstack(),np.hstack(),np.hsplit(),.view(),copy() 來從現有數據中創建Array。
前面的例子中,我們看到可以使用List和切片來創建新的數組:
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) >>> arr1 = a[3:8] >>> arr1 array([4, 5, 6, 7, 8])兩個現有的數組可以進行垂直或者水平堆疊:
>>> a1 = np.array([[1, 1], ... [2, 2]])>>> a2 = np.array([[3, 3], ... [4, 4]])>>> np.vstack((a1, a2)) array([[1, 1],[2, 2],[3, 3],[4, 4]])>>> np.hstack((a1, a2)) array([[1, 1, 3, 3],[2, 2, 4, 4]])使用hsplit 可以將大的數組分割成為幾個小的數組:
>>> x = np.arange(1, 25).reshape(2, 12) >>> x array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],[13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]])>>> np.hsplit(x, 3) [array([[1, 2, 3, 4],[13, 14, 15, 16]]), array([[ 5, 6, 7, 8],[17, 18, 19, 20]]), array([[ 9, 10, 11, 12],[21, 22, 23, 24]])]算數運算
array的加法:
>>> data = np.array([1, 2]) >>> ones = np.ones(2, dtype=int) >>> data + ones array([2, 3])其他的運算:
>>> data - ones array([0, 1]) >>> data * data array([1, 4]) >>> data / data array([1., 1.])array求和:
>>> a = np.array([1, 2, 3, 4])>>> a.sum() 10如果是求和多維數組的話,需要指定維度:
>>> b = np.array([[1, 1], [2, 2]]) >>> b.sum(axis=0) array([3, 3])>>> b.sum(axis=1) array([2, 4])其他有用操作
這里列出了其他的有用操作:
>>> data.max() 2.0 >>> data.min() 1.0 >>> data.sum() 3.0對于二維數組來說,sum默認會求和所有的元素,min也會從所有元素中查找最小的:
>>> a = np.array([[0.45053314, 0.17296777, 0.34376245, 0.5510652], ... [0.54627315, 0.05093587, 0.40067661, 0.55645993], ... [0.12697628, 0.82485143, 0.26590556, 0.56917101]])>>> a.sum() 4.8595784>>> a.min() 0.05093587我們還可以指定維度:
>>> a.min(axis=0) array([0.12697628, 0.05093587, 0.26590556, 0.5510652 ])矩陣
矩陣就是 2 * 2 的數組:
>>> data = np.array([[1, 2], [3, 4]]) >>> data array([[1, 2],[3, 4]])矩陣同樣可以進行統計操作:
>>> data.max() 4 >>> data.min() 1 >>> data.sum() 10默認情況是累加所有的元素,我們也可以指定特定的累加維度:
>>> data.max(axis=0) array([3, 4]) >>> data.max(axis=1) array([2, 4])矩陣的運算:
>>> data = np.array([[1, 2], [3, 4]]) >>> ones = np.array([[1, 1], [1, 1]]) >>> data + ones array([[2, 3],[4, 5]])如果是多維的和低維的進行運算,那么將會使用內置的broadcast機制,將低維的進行廣播:
>>> data = np.array([[1, 2], [3, 4], [5, 6]]) >>> ones_row = np.array([[1, 1]]) >>> data + ones_row array([[2, 3],[4, 5],[6, 7]])生成隨機數
在機器學習中,生成隨機數是一個非常重要的功能。我們看下如何在Numpy中生成隨機數。
>>> rng = np.random.default_rng(0) >>> rng.random(3) array([0.63696169, 0.26978671, 0.04097352])>>> rng.random((3, 2)) array([[0.01652764, 0.81327024],[0.91275558, 0.60663578],[0.72949656, 0.54362499]]) # may vary>>> rng.integers(5, size=(2, 4)) array([[2, 1, 1, 0],[0, 0, 0, 4]]) # may varyunique
np.unique可以統計數組的唯一值:
>>> a = np.array([11, 11, 12, 13, 14, 15, 16, 17, 12, 13, 11, 14, 18, 19, 20])>>> unique_values = np.unique(a) >>> print(unique_values) [11 12 13 14 15 16 17 18 19 20]還可以返回index或者count:
>>> unique_values, indices_list = np.unique(a, return_index=True) >>> print(indices_list) [ 0 2 3 4 5 6 7 12 13 14] >>> unique_values, occurrence_count = np.unique(a, return_counts=True) >>> print(occurrence_count) [3 2 2 2 1 1 1 1 1 1]對矩陣也適用:
>>> a_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]])>>> unique_values = np.unique(a_2d) >>> print(unique_values) [ 1 2 3 4 5 6 7 8 9 10 11 12]如果想得到唯一的行或者列,可以傳入axis參數:
>>> unique_rows = np.unique(a_2d, axis=0) >>> print(unique_rows) [[ 1 2 3 4][ 5 6 7 8][ 9 10 11 12]]矩陣變換
我們可以使用transpose來把矩陣的行和列進行調換:
>>> arr = np.arange(6).reshape((2, 3)) >>> arr array([[0, 1, 2],[3, 4, 5]])>>> arr.transpose() array([[0, 3],[1, 4],[2, 5]])反轉數組
使用flip可以反轉數組:
>>> arr = np.array([1, 2, 3, 4, 5, 6, 7, 8]) >>> reversed_arr = np.flip(arr) >>> print('Reversed Array: ', reversed_arr) Reversed Array: [8 7 6 5 4 3 2 1]如果是2維的數組:
>>> arr_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])>>> reversed_arr = np.flip(arr_2d) >>> print(reversed_arr) [[12 11 10 9][ 8 7 6 5][ 4 3 2 1]]默認會反轉行和列,我們也可以只反轉行或者列:
>>> reversed_arr_rows = np.flip(arr_2d, axis=0) >>> print(reversed_arr_rows) [[ 9 10 11 12][ 5 6 7 8][ 1 2 3 4]]>>> reversed_arr_columns = np.flip(arr_2d, axis=1) >>> print(reversed_arr_columns) [[ 4 3 2 1][ 8 7 6 5][12 11 10 9]]還可以只反轉一行或者一列:
>>> arr_2d[1] = np.flip(arr_2d[1]) >>> print(arr_2d) [[ 1 2 3 4][ 8 7 6 5][ 9 10 11 12]]>>> arr_2d[:,1] = np.flip(arr_2d[:,1]) >>> print(arr_2d) [[ 1 10 3 4][ 8 7 6 5][ 9 2 11 12]]flatten 和 ravel
flatten 可以將數組變成一維的:
>>> x = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])>>> x.flatten() array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])flatten之后的數組和原數組是無關的,我們修改flatten之后的數組不會改變之前的數組內容:
>>> a1 = x.flatten() >>> a1[0] = 99 >>> print(x) # Original array [[ 1 2 3 4][ 5 6 7 8][ 9 10 11 12]] >>> print(a1) # New array [99 2 3 4 5 6 7 8 9 10 11 12]但是如果使用ravel,對新數組的修改同樣也會改變原始數組:
>>> a2 = x.ravel() >>> a2[0] = 98 >>> print(x) # Original array [[98 2 3 4][ 5 6 7 8][ 9 10 11 12]] >>> print(a2) # New array [98 2 3 4 5 6 7 8 9 10 11 12]save 和 load
NumPy 的對象可以通過save和load存放到文件和從文件中加載:
>>> a = np.array([1, 2, 3, 4, 5, 6])>>> np.save('filename', a)>>> b = np.load('filename.npy')如果想以文本的方式來存儲,那么可以使用np.savetxt:
>>> csv_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])>>> np.savetxt('new_file.csv', csv_arr)>>> np.loadtxt('new_file.csv') array([1., 2., 3., 4., 5., 6., 7., 8.])CSV
NumPy有專門的方法來對CSV文件進行操作:
>>> import pandas as pd>>> # If all of your columns are the same type: >>> x = pd.read_csv('music.csv', header=0).values >>> print(x) [['Billie Holiday' 'Jazz' 1300000 27000000]['Jimmie Hendrix' 'Rock' 2700000 70000000]['Miles Davis' 'Jazz' 1500000 48000000]['SIA' 'Pop' 2000000 74000000]]>>> # You can also simply select the columns you need: >>> x = pd.read_csv('music.csv', usecols=['Artist', 'Plays']).values >>> print(x) [['Billie Holiday' 27000000]['Jimmie Hendrix' 70000000]['Miles Davis' 48000000]['SIA' 74000000]]本文已收錄于 http://www.flydean.com/01-python-numpy-basic/
最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的NumPy之:NumPy简介教程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用gradle插件发布项目到nexus
- 下一篇: NumPy之:数据类型