NumPy快速入门指南

简介

NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵。

参考:https://docs.scipy.org/doc/numpy/user/quickstart.html
100 numpy exercises:http://www.labri.fr/perso/nrougier/teaching/numpy.100/
试验性的Numpy教程:http://reverland.org/python/2012/08/22/numpy
From Python to Numpy:http://www.labri.fr/perso/nrougier/from-python-to-numpy/

快速入门指南

# -*- coding: utf-8 -*-
import numpy as np
from numpy import pi
from numpy import newaxis

'''
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
<class 'numpy.ndarray'>
2
(3, 5)
15
int32
4
<memory at 0x000001D910BB6DC8>
'''
def numpyBasic():
    a = np.arange(15).reshape(3, 5)
    print(a)
    # 当数组包含的元素太多时, 会省略中间的元素, 只打印角落的元素
    # 如果想禁用这个行为, 强制打印所有的元素, 可以开启set_printoptions选项: np.set_printoptions(threshold=np.nan)
    # 还原成省略效果: np.set_printoptions(threshold=1000)
    # 设置打印浮点数的小数位数: np.set_printoptions(precision=4)  # 设置打印浮点数的小数位数,默认是8位
    print(type(a))
    print(a.ndim)  # 数组的轴数(即rank)
    print(a.shape)  # 数组的维度,返回的是一个元组,元组的长度值刚好是ndim
    print(a.size)  # 数组元素的个数
    print(a.dtype)  # 数组元素的类型
    print(a.itemsize)  # 数组元素的字节大小
    print(a.data)  # 数组包含的实际数据(一般情况下不会用到这个属性,都是通过索引来访问元素)

def numpyCreateArray():
    # 可以从普通的python列表或元组来创建
    a1 = np.array([2, 3, 4])
    print(a1)
    print(a1.dtype)
    a2 = np.array([1.2, 3.5, 5.1])
    print(a2.dtype)
    a3 = np.array([(1.5, 2.3), (4, 5, 6)])
    print(a3)
    print(a3.dtype)
    # 在创建数组的时候, 指定数据类型
    a4 = np.array([[1, 2], [3, 4]], dtype=complex)
    print(a4)
    # zeros函数创建初始值为0的数组
    a5 = np.zeros((3, 4))
    print(a5)
    # ones创建初始值为1的数组
    a6 = np.ones((3, 4))
    print(a6)
    # empty创建未初始化的随机数组
    a7 = np.empty((2, 5))
    print(a7)
    # 为了创建序列函数, Numpy也提供了类似range函数的方法
    a8 = np.arange(10, 30, 5)
    print(a8)
    a9 = np.arange(0, 2, 0.3)
    print(a9)
    a10 = np.linspace(0, 2, 9)
    print(a10)
    x = np.linspace(0, 2 * pi, 100)
    f = np.sin(x)

# 数组的算术运算会自动作用于每个元素,并返回一个新的数组
def numpyBaseAlgorithm():
    a = np.array([20, 30, 40, 50])
    b = np.arange(4)
    c = a - b
    print(c)
    d = b**2
    print(d)
    e = 10 * np.sin(a)
    print(e)
    f = a < 35
    print(f)

# *返回的是每个元素相乘的结果, 要实现矩阵乘法, 需要使用dot函数
def numpyMatrixAlgorithm():
    a = np.array([[1, 1],
                  [0, 1]])
    b = np.array([[2, 0],
                  [3, 4]])
    c = a * b  # 对应位置的元素相乘
    print(c)
    d = a.dot(b)  # 矩阵乘法
    print(d)
    e = np.dot(a, b)  # 另一种形式的矩阵乘法
    print(e)

# 一些操作, 如+=和*=是直接修改原有的数组, 而不是新建一个
def numpyMatrixAlgorithmSelf():
    a = np.ones((2, 3), dtype=int)
    print(a)
    b = np.random.random((2, 3))
    print(b)
    print(a.dtype)
    print(b.dtype)
    b += a
    print(b)
    # a += b
    # print(a)

# 当不同类型的数组运算操作时, 总是向精度更高的自动转换
def numpyMatrixAlgorithmPrecision():
    a = np.ones(3, dtype=np.int32)
    b = np.linspace(0, np.pi, 3)
    c = a + b
    print(c)
    print(c.dtype)
    d = np.exp(c * 1j)
    print(d)
    print(d.dtype)

# ndarray包含了很多一元运算. 如求和等
def numpyMatrixAlgorithmUnary():
    a = np.arange(15).reshape(3, 5)
    print(a)
    print(a.sum())
    print(a.min())
    print(a.max())

# 默认情况下, 数组操作都是作用于每一个元素, 而不管它的维度. 但是, 我们也可以通过axis参数来限定操作的轴
def numpyMatrixAlgorithmAxis():
    a = np.arange(12).reshape(3, 4)
    b = a.sum(axis=0)  # 计算每一列的和
    print(b)
    c = a.min(axis=1)  # 计算每一行的最小值
    print(c)
    d = a.cumsum(axis=1)  # 每一行累积和
    print(d)

# Numpy提供了很多常见的数学上的运算, 如sin, cos, exp. 在Numpy中, 我们称这些为"universal functions"(ufunc)
def numpyUniversal():
    a = np.arange(3)
    b = np.exp(a)
    print(b)
    c = np.sqrt(a)
    print(c)
    d = np.add(a, a)
    print(d)

'''
int32
[  0   1   8  27  64 125 216 343 512 729]
8
[ 8 27 64]
[ 0  8 64]
[1000    1 1000   27 1000  125  216  343  512  729]
[ 729  512  343  216  125 1000   27 1000    1 1000]
[1000    1 1000   27 1000  125  216  343  512  729]
9.999999999999998 1.0 9.999999999999998 3.0 9.999999999999998 5.0 5.999999999999999 6.999999999999999 7.999999999999999 8.999999999999998 
'''
# 一维数组的索引,切片,迭代跟普通的Python列表一样
def numpyArrayIndex():
    a = np.arange(10) ** 3
    print(a.dtype)
    print(a)
    print(a[2])
    print(a[2:5])
    print(a[:6:2])  # 等价于a[0:6:2]
    a[:6:2] = 1000
    print(a)
    print(a[::-1])  # 反转数组a
    for i in a:
        i **= (1 / 3.)
    print(a)
    for i in range(len(a)):
        print(a[i] ** (1 / 3.), end=' ')

def f(x, y):
    return 10*x + y

'''
[[ 0  1  2  3]
 [10 11 12 13]
 [20 21 22 23]
 [30 31 32 33]
 [40 41 42 43]]
23
[ 1 11 21 31 41]
[ 1 11 21 31 41]
[[10 11 12 13]
 [20 21 22 23]]
'''
def numpyArrayMatrix():
    a = np.fromfunction(f, (5, 4), dtype=int)
    print(a)
    # help(np.fromfunction)
    print(a[2, 3])
    print(a[0:5, 1])
    print(a[:, 1])
    print(a[1:3, :])
    # 当索引数少于轴数时,缺失的索引认为是全切片
    print(a[-1])  # 等价于 a[-1, :]

# 可以使用...来表示全切片,它代表补全剩下的所有索引
# x[1,2,...]等价于x[1,2,:,:,:]
# x[...,3]等价于x[:,:,:,:,3]
# x[4,...,5,:]等价于x[4,:,:,5,:]
def numpyArrayDot():
    a = np.array([[[0, 1, 2],
                  [10, 12, 13]],
                  [[100, 101, 102],
                  [110, 112, 113]]])
    print(a.shape)
    print(a[1, ...])
    print(a[..., 2])

'''
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
0 1 2 3 10 11 12 13 20 21 22 23 30 31 32 33 40 41 42 43 
'''
def numpyMatrixEnumerate():
    a = np.array([[0,  1,  2,  3],
        [10, 11, 12, 13],
        [20, 21, 22, 23],
        [30, 31, 32, 33],
        [40, 41, 42, 43]])
    # 多维数组的迭代是根据第一个轴来操作的
    for row in a:
        print(row)
    # 如果想遍历每个元素,可以使用flat属性
    for element in a.flat:
        print(element, end=' ')

'''
(3, 4)
[[0. 8. 3. 0.]
 [5. 2. 3. 5.]
 [4. 6. 2. 3.]]
[0. 8. 3. 0. 5. 2. 3. 5. 4. 6. 2. 3.]
[[0. 8.]
 [3. 0.]
 [5. 2.]
 [3. 5.]
 [4. 6.]
 [2. 3.]]
[[0. 5. 4.]
 [8. 2. 6.]
 [3. 3. 2.]
 [0. 5. 3.]]
(4, 3)
[[0. 8. 3. 0. 5. 2.]
 [3. 5. 4. 6. 2. 3.]]
[[0. 8. 3. 0.]
 [5. 2. 3. 5.]
 [4. 6. 2. 3.]]
'''
def numpyMatrixShape():
    a = np.floor(10 * np.random.random((3, 4)))
    print(a.shape)
    print(a)
    # 返回降维的数组
    print(a.ravel())
    # 直接修改shape
    print(a.reshape(6, 2))
    # 数组转置
    print(a.T)
    print(a.T.shape)
    # reshape返回修改后的数组,不改变数组本身,但是resize函数直接修改原数组
    a.resize((2, 6))
    print(a)
    # 如果一个维度为的是-1, 那么reshape函数会自动计算它的值
    print(a.reshape(3, -1))

'''
[[3. 0.]
 [3. 9.]]
[[9. 4.]
 [8. 1.]]
[[3. 0.]
 [3. 9.]
 [9. 4.]
 [8. 1.]]
[[3. 0. 9. 4.]
 [3. 9. 8. 1.]]
'''
def numpyMatrixCombine():
    # 多个数组可以根据不同的轴组合在一起
    a = np.floor(10 * np.random.random((2, 2)))
    print(a)
    b = np.floor(10 * np.random.random((2, 2)))
    print(b)
    print(np.vstack((a, b)))
    print(np.hstack((a, b)))

'''
[[1. 1. 2. 9.]
 [4. 4. 0. 3.]]
[[4. 3.]
 [2. 8.]]
[[4.]
 [2.]]
[[4. 3.]
 [2. 8.]]
[[4. 3.]
 [2. 8.]]
[1 2 3 0 4]
'''
## 数组合并
def numpyColumnStack():
    a = np.array([[1., 1.], [4., 4.]])
    b = np.array([[2., 9.], [0., 3.]])
    # 操作2维数组,等效于hstack
    print(np.column_stack((a, b)))
    a = np.array([4., 2.])
    b = np.array([3., 8.])
    # 操作1维数组,返回2维数组,a,b分别为2维数组的列
    print(np.column_stack((a, b)))
    # 将1维数组变成2维数组
    print(a[:, newaxis])
    # 都是操作二维数组,下面两个操作column_stack和hstack等效
    print(np.column_stack((a[:, newaxis], b[:, newaxis])))
    print(np.hstack((a[:, newaxis], b[:, newaxis])))
    # 另外不论什么数组,row_stack函数等效于vstack
    # 通常来说,2维以上的数组,hstack基于第2根轴做运算,vstack基于第1根轴
    # concatenate函数额外多接受一个参数,可以指定基于哪根轴做数组的合并操作
    # 另外, r_和c_函数对于在一个轴上组合数据相当实用,他们允许使用范围符号
    print(np.r_[1:4, 0, 4])

## 数组切割
def numpyMatrixSplit():
    a = np.array([[ 9.,  0.,  2.,  0.,  0.,  4.,  1.,  6.,  4.,  8.,  3.,  9.],
       [ 5.,  3.,  0.,  5.,  5.,  8.,  0.,  5.,  6.,  3.,  8.,  7.]])
    print(a)
    # 横轴切割成3个数组
    print(np.hsplit(a, 3))
    # 纵轴切割成2个数组
    # vsplit可以基于垂直轴切割,array_split可以指定基于哪个轴切割
    print(np.vsplit(a, 2))
    # 基于第3和第4列切割
    print(np.hsplit(a, (3, 4)))

def f(x):
    print(id(x))

'''
[ 0  1  2  3  4  5  6  7  8  9 10 11]
True
(12,)
(3, 4)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
2889321266432
2889321266432
- - - - - - - - - - - - - - - - - - - -
False
True
False
(3, 4)
[[   0    1    2    3 1234    5]
 [   6    7    8    9   10   11]]
[[   0    1    2    3]
 [1234    5    6    7]
 [   8    9   10   11]]
[[ 1  2]
 [ 5  6]
 [ 9 10]]
[[10 10]
 [10 10]
 [10 10]]
[[   0   10   10    3]
 [1234   10   10    7]
 [   8   10   10   11]]
- - - - - - - - - - - - - - - - - - - -
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
False
False
[[9999    1    2    3]
 [   4    5    6    7]
 [   8    9   10   11]]
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
'''
# 当进行数组运算和改变数组时,有时候数据是被复制到一个新的数组,有时候不是
def numpyCopy():
    ## 不复制
    a = np.arange(12)
    print(a)
    b = a  # 不会有新对象产生
    print(b is a)  # a和b是同一个数组
    print(b.shape)
    b.shape = 3, 4  # 改变b的shape, a也同样变化
    print(a.shape)
    print(a)
    # Python中使用可变参数时,可以看做是引用传参,因此函数调用会产生新的数组
    print(id(a))
    f(a)

    print('- - - - - - - - - - - - - - - - - - - -')

    ## 视图(View)和浅复制(Shallow Copy)
    # 不同的数组可以共享数据,view函数可以创造一个数据相同的新数组
    a = np.array([[0, 1, 2, 3],
           [4, 5, 6, 7],
           [8, 9, 10, 11]])
    c = a.view()
    print(c is a)  # c和a不是同一个数组
    print(c.base is a)  # c是a的数据的视图
    print(c.flags.owndata)
    c.shape = 2, 6  # a的不会改变
    print(a.shape)
    c[0, 4] = 1234  # a的数据发生改变
    print(c)
    print(a)
    # 一个数组的切片返回的就是它的视图
    s = a[:, 1:3]  # s是a的视图
    print(s)
    s[:] = 10  # s[:]是a的视图
    print(s)
    print(a)

    print('- - - - - - - - - - - - - - - - - - - -')

    ## 深度复制(Deep Copy)
    a = np.arange(12).reshape((3, 4))
    print(a)
    d = a.copy()
    print(d is a)
    print(d.base is a)
    d[0, 0] = 9999
    print(d)
    print(a)

## 广播机制
def numpyBroadcast():
    # 广播主要描述于numpy对于不同shape的数组如何进行算术运算。受限于一些特定约束
    # 一般都是小的数组扩展为大的数组,以便能计算
    # 通常情况下,numpy操作的数组必须是相同shape的
    a = np.array([1.0, 2.0, 3.0])
    b = np.array([2.0, 2.0, 2.0])
    print(a * b)
    # 当数组的shape满足某些特定约束时,numpy的广播机制可以使这个约束更宽松。最简单的就是广播例子就是当数组和一个标量操作时
    a = np.array([1.0, 2.0, 3.0])
    b = 2.0
    print(a * b)
    # 我们可以认为标量b被扩展为了和a同样shape的数组,b中的新元素就是原来标量的拷贝
    # 这个扩展策略仅仅是概念上的,实际上Numpy足够聪明,能自动使用标量做运算,而不需要复制任何东西
    # 所以广播运算从计算内存上来说更优秀
    # 要能满足广播,必须符合下面两条规则:
    # 1. 广播之后,输出数组的shape是输入数组shape的各个轴上的最大值,然后沿着较大shape属性的方向复制延伸
    # 2. 要进行广播机制,要么两个数组的shape属性一样,要么其中有一个数组的shape属性必须有一个等于1

'''
[  0   1   4   9  16  25  36  49  64  81 100 121]
[1 1 3 8 5]
  print(a[k])  # 等价于a[i, j]
[ 1  1  9 64 25]
[[ 9 16]
 [81 49]]
- - - - - - - - - - - - - - - - - - - -
[[[  0   0   0]
  [255   0   0]
  [  0 255   0]
  [  0   0   0]]

 [[  0   0   0]
  [  0   0 255]
  [255 255 255]
  [  0   0   0]]]
- - - - - - - - - - - - - - - - - - - -
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[ 2  5]
 [ 7 11]]
[[ 2  6]
 [ 6 10]]
(3, 2, 2)
[[[ 2  1]
  [ 3  3]]

 [[ 6  5]
  [ 7  7]]

 [[10  9]
  [11 11]]]
[array([[0, 1],
       [1, 2]]), array([[2, 1],
       [3, 3]])]
[[ 2  5]
 [ 7 11]]
[[[0 1]
  [1 2]]

 [[2 1]
  [3 3]]]
- - - - - - - - - - - - - - - - - - - -
[0 1 2 3 4]
[0 0 2 0 0]
[0 1 2 3 4]
[2 1 3 3 4]
[0 1 2 3 4]
[1 1 3 3 4]
- - - - - - - - - - - - - - - - - - - -
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[False False False False]
 [False  True  True  True]
 [ True  True  True  True]]
[ 5  6  7  8  9 10 11]
[[0 1 2 3]
 [4 0 0 0]
 [0 0 0 0]]
- - - - - - - - - - - - - - - - - - - -
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[ 4  5  6  7]
 [ 8  9 10 11]]
[[ 4  5  6  7]
 [ 8  9 10 11]]
[[ 0  2]
 [ 4  6]
 [ 8 10]]
[ 4 10]
'''
## 索引
def numpyIndices():
    # numpy除了支持普通的python方式的索引和切片之外,还支持整数数组或布尔数组索引
    a = np.arange(12) ** 2
    i = np.array([1, 1, 3, 8, 5])
    print(a)
    print(i)
    print(a[i])  # 返回a中再索引i的元素
    j = np.array([[3, 4], [9, 7]])
    print(a[j])  # 二维数组索引,返回a中再索引j的元素

    print('- - - - - - - - - - - - - - - - - - - -')

    # 当数组索引作用在多维数组时,是根据数组的第一个维度来索引的
    palette = np.array([[0, 0, 0],
                        [255, 0, 0],
                        [0, 255, 0],
                        [0, 0, 255],
                        [255, 255, 255]])
    image = np.array([[0, 1, 2, 0],
                      [0, 3, 4, 0]])
    print(palette[image])

    print('- - - - - - - - - - - - - - - - - - - -')

    # 索引同样可以是多维的,但是必须是相同的shape
    a = np.arange(12).reshape(3, 4)
    print(a)
    i = np.array([[0, 1],
                  [1, 2]])
    j = np.array([[2, 1],
                  [3, 3]])
    print(a[i, j])
    print(a[i, 2])
    b = a[:, j]  # a[0, j], a[1, j], a[2, j]
    print(b.shape)
    print(b)
    # 同样,我们可以把i和j放在一个列表里,然后用列表做索引
    k = [i, j]
    print(k)
    print(a[k])  # 等价于a[i, j]
    s = np.array([i, j])  # 三维数组
    print(s)

    print('- - - - - - - - - - - - - - - - - - - -')

    # 同样可以给数组索引赋值
    a = np.arange(5)
    print(a)
    a[[1, 3, 4]] = 0
    print(a)
    # 但是当列表包含相同的索引时,这个位置会被赋值多次,最终只保留最后一次的值
    a = np.arange(5)
    print(a)
    a[[0, 0, 2]] = [1, 2, 3]
    print(a)
    # 上面看起来很合理,但是当使用+=符号的时候,结果和我们想的可能不太一样
    a = np.arange(5)
    print(a)
    a[[0, 0, 2]] += 1  # 尽管索引中出现了两次0,但是第0个元素它只加了1次
    print(a)

    print('- - - - - - - - - - - - - - - - - - - -')

    # 布尔数组索引
    # 当使用数字数组索引时,我们提供了哪些元素要被索引的信息
    # 但是当使用布尔数组时,我们是明确哪些元素需要,哪些元素不需要
    a = np.arange(12).reshape((3, 4))
    print(a)
    b = a > 4
    print(b)
    print(a[b])
    a[b] = 0  # 所有大于4的元素都赋值为0
    print(a)

    print('- - - - - - - - - - - - - - - - - - - -')

    a = np.arange(12).reshape(3, 4)
    b1 = np.array([False, True, True])
    b2 = np.array([True, False, True, False])
    print(a)
    print(a[b1, :])  # 选择行
    print(a[b1])  # 同上
    print(a[:, b2])  # 选择列
    print(a[b1, b2])

'''
(2, 3., b'World')
[1 2]
[2. 3.]
[b'Hello' b'World']
'''
## 字符串索引
# Numpy提供了创建结构化的数组的能力,可以通过列名来操作数据
def numpyStringIndices():
    # Numpy提供了创建结构化的数组的能力,可以通过列名来操作数据
    x = np.array([(1, 2., 'Hello'), (2, 3., 'World')], dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])
    print(x[1])
    print(x['foo'])
    print(x['bar'])
    print(x['baz'])

if __name__ == '__main__':
    numpyBasic()
    # numpyCreateArray()
    # numpyBaseAlgorithm()
    # numpyMatrixAlgorithm()
    # numpyMatrixAlgorithmSelf()
    # numpyMatrixAlgorithmPrecision()
    # numpyMatrixAlgorithmUnary()
    # numpyMatrixAlgorithmAxis()
    # numpyUniversal()
    # numpyArrayIndex()
    # numpyArrayMatrix()
    # numpyArrayDot()
    # numpyMatrixEnumerate()
    # numpyMatrixShape()
    # numpyMatrixCombine()
    # numpyColumnStack()
    # numpyMatrixSplit()
    # numpyCopy()
    # numpyBroadcast()
    # numpyIndices()
    # numpyStringIndices()

函数和方法概览

如下是按照分类整理的常用函数和方法,完整的分类可以参考Routines

数组创建

  • arange
  • array
  • copy
  • empty
  • empty_like
  • eye # 创建一个对角线全是1的二维数组
  • fromfile
  • fromfunction
  • identity # 创建一个对角线全是1的方形矩阵,与eye方法差不多,只是可以接受的参数不同
  • linspace
  • logspace # 创建等比数列
  • mgrid
  • orgid
  • ones
  • ones_like
  • zeros
  • zeros_like

转换

  • ndarray.astype # 改变数组的元素格式
  • atleast_1d # 将输入转换为至少1维数组
  • atleast_2d
  • alteast_3d
  • mat # 将输入转换为矩阵

处理

  • array_split
  • column_stack
  • concatenate
  • diagonal
  • dsplit
  • dstack
  • hsplit
  • hstack
  • ndarray.item
  • newaxis
  • ravel
  • repeat
  • reshape
  • resize
  • squeeze
  • swapaxes
  • take
  • transpose
  • vsplit
  • vstack

Questions

  • all
  • any
  • nonezero
  • where

排序

  • argmax # 返回最大值的索引
  • argmin # 返回最小值的索引
  • argsort # 返回排序后的索引
  • max
  • min
  • ptp
  • searchsorted
  • sort

运算

  • choose
  • compress
  • cumprod
  • cumsum
  • inner
  • ndarray.fill
  • imag
  • prod
  • put
  • putmask
  • real
  • sum

基本统计

  • cov
  • mean
  • std
  • var

线性代数

  • cross
  • dot
  • outer
  • linalg
  • svd
  • vdot

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/04/01/numpy-quick-start-guide/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
NumPy快速入门指南
简介 NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵。 参考:https://docs.scipy.org/doc/numpy/user/quickstart.html 100 ……
<<上一篇
下一篇>>
文章目录
关闭
目 录