简介
NumPy是一个开源的Python库,次要用在数据分析和科学计算,基本上能够把NumPy看做是Python数据计算的根底,因为很多十分优良的数据分析和机器学习框架底层应用的都是NumPy。比方:Pandas, SciPy, Matplotlib, scikit-learn, scikit-image 等。
NumPy库次要蕴含多维数组和矩阵数据结构。 它为ndarray(一个n维数组对象)提供了对其进行无效操作的办法。 NumPy能够用于对数组执行各种数学运算。 并且提供了可在这些数组和矩阵上运行的宏大的高级数学函数库。
装置NumPy
有很多形式能够依照NumPy:
<code class="pyton">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能够创立等分的数组:
<code class="Python">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对数组进行排序:
<code class="Python">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值,举个例子:
<code class="Python">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 3
ndarray.size
用来统计数组中的元素个数:
>>> array_example.size 24
ndarray.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是相似的:
<code class="Python">>>> 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 vary
unique
np.unique
能够统计数组的惟一值:
<code class="Python">>>> 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维的数组:
<code class="Python">>>> 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 能够将数组变成一维的:
<code class="Python">>>> 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之后的数组不会扭转之前的数组内容:
<code class="Python">>>> 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:
<code class="Python">>>> 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/
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢迎关注搞代码gaodaima网的公众号:「程序那些事」,懂技术,更懂你!