NumPy之:NumPy简介教程

简介: NumPy之:NumPy简介教程

目录



简介


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
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是类似的:


>>> 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可以统计数组的唯一值:


>>> 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]]
相关文章
|
3月前
|
Python
NumPy 教程 之 NumPy 矩阵库(Matrix) 4
矩阵是由行和列构成的矩形数组,其元素可以是数字、符号或数学表达式。
36 4
|
3月前
|
Python
NumPy 教程 之 NumPy 矩阵库(Matrix) 2
不同于ndarray,matlib函数生成的是矩阵形式。教程中详细解释了矩阵的概念,并介绍了转置矩阵的实现方式,使用T属性或函数实现。此外,还展示了如何利用`matlib.empty()`创建指定形状的新矩阵,并可选择数据类型及顺序。最后通过示例演示了矩阵填充随机数据的方法。
40 3
|
3月前
|
数据可视化 Python
NumPy 教程 之 NumPy Matplotlib 7
使用Python的绘图库Matplotlib与NumPy结合进行数据可视化,提供Matplotlib作为MatLab开源替代方案的有效方法,以及如何利用plt()函数将数据转换成直观的直方图示例。
44 11
|
3月前
|
Python
NumPy 教程 之 NumPy Matplotlib 6
Matplotlib 是一个强大的 Python 绘图库,能与 NumPy 协同工作,提供类似 MatLab 的开源替代方案,并支持 PyQt 和 wxPython 等图形工具包。通过 `numpy.histogram()` 函数示例,展示了如何创建数据频率分布图,该函数接受输入数组和 bin 参数,生成对应频率的直方图。示例代码及输出清晰展示了 bin 的边界与对应频率的关系。
36 11
|
3月前
|
Python
NumPy 教程 之 NumPy Matplotlib 4
使用 Python 的绘图库 Matplotlib,结合 NumPy,生成各种图形,作为 MatLab 的开源替代方案。您将学习到如何用 matplotlib 和 NumPy 包来创建正弦波图形,以及如何在同一图中利用 subplot() 函数组织和展示不同的子图,例如同时绘制正弦和余弦曲线。通过实际代码示例,加深对这些功能的理解。
48 12
|
3月前
|
Python
NumPy 教程 之 NumPy Matplotlib 3
使用Python的绘图库Matplotlib与NumPy结合,创建有效的MatLab开源替代方案。它还支持与PyQt和wxPython等图形工具包搭配使用。通过向`plot()`函数添加特定格式字符串,可以展示离散值而非线性图。提供了多种线型和标记选项,例如实线`-`、虚线`--`、点标记`.`等,以及颜色缩写如蓝色`b`、绿色`g`等。示例代码展示了如何用圆点表示数据点而非线条。
42 10
|
3月前
|
Python
NumPy 教程 之 NumPy Matplotlib 5
Matplotlib 是 Python 的绘图库,配合 NumPy 可作为 MatLab 的开源替代方案,并能与 PyQt 和 wxPython 等图形工具包共同使用。本教程重点讲解 `bar()` 函数用于生成条形图的方法,并通过实例展示了如何创建并显示两组数据的条形图。
40 7
|
3月前
|
存储 Python
NumPy 教程 之 NumPy IO 1
NumPy IO 教程介绍了如何使用 NumPy 读写文本及二进制数据。教程覆盖了 `.npy` 和 `.npz` 格式的文件操作,其中 `save()` 和 `load()` 函数用于单个数组的存取,而 `savez()` 则可以保存多个数组。文本文件处理则由 `loadtxt()` 和 `savetxt()` 完成。通过示例展示了 `numpy.save()` 函数的具体用法,并解释了其参数含义,如文件名、数组对象以及序列化选项等。
46 10
|
3月前
|
Serverless Python
NumPy 教程 之 NumPy 线性代数 7
NumPy 的 `linalg` 库提供了丰富的线性代数功能,如点积、矩阵乘法、求解线性方程等。`numpy.linalg.inv()` 用于计算矩阵的乘法逆矩阵,即找到满足 `AB=BA=E` 的矩阵 `B`,其中 `E` 是单位矩阵。示例展示了如何对矩阵 `A` 计算其逆矩阵 `A^(-1)` 并求解线性方程 `A^(-1)B`,得到向量 `[5, 3, -2]` 作为解。
59 10
|
3月前
|
索引 Python
NumPy 教程 之 NumPy 线性代数 4
NumPy 的线性代数库 `linalg` 提供了丰富的线性代数功能,如点积(`dot`)、向量点积(`vdot`)、内积(`inner`)、矩阵积(`matmul`)、行列式(`determinant`)、求解线性方程(`solve`)和矩阵逆(`inv`)。其中,`numpy.matmul` 用于计算两个数组的矩阵乘积,支持多维数组操作。
39 11

相关实验场景

更多