Numpy基础教程

Numpy数组---Array

Numpy的主要对象是多维数组。它是一个由元素(通常是数字)构成的表,所有元素的类型相同。维度的数量称为数组的阶(rank),数组的大小是一个由整型数构成的元组,可以描述数组不同维度上的大小。

Numpy的数组类叫做ndarray,别名是array。先来举一个例子,涉及的具体函数后面我们都会讲到。

import numpy as np         

a = np.array([0, 1, 2, 3])  # 创建一个一维数组
print(type(a))              # 打印 "<class 'numpy.ndarray'>"

数组的属性

  • ndarray.ndim:数组的维度数
  • ndarray.shape:数组每个维度的大小
  • ndarray.size:数组中元素的总个数
  • ndarray.dtype: 数组中元素的类型
  • ndarray.itemsize: 数组中每个元素所占的字节数
  • ndarray.data: 包含真实数组元素的缓冲区

再举一个例子。

import numpy as np

a = np.array([[0., 1., 2.],
              [3., 4., 5.]])          # 创建一个2维数组
print(a)                              # 打印 "[[ 0.  1.  2.]
                                      #        [ 3.  4.  5.]]"
print(a.ndim)                         # 打印 "2"
print(a.shape)                        # 打印 "(2, 3)"
print(a.size)                         # 打印 "6"
print(a.dtype)                        # 打印 "float64"
print(a.itemsize)                     # 打印 "8"  (64/8=8)
print(a.data)                         # 打印 "<memory at 0x7f18400ae3a8>"

创建数组

手动创建数组

可以利用array函数从python的列表或元组创建一个数组。

  • 1维数组
import numpy as np    # 导入Numpy的推荐方式

a = np.array([0, 1, 2, 3])   # 创建一维数组
print(a)                     # 打印 "[1 2 3 4]"
print(a.ndim)                # 打印 "1"
print(a.shape)               # 打印 "(4,)"
print(len(a))                # 打印 "4"
  • 2维及多维数组
import numpy as np

b = np.array([[0, 1, 2], [3, 4, 5]])   # 创建2维数组
print(b)                               # 打印 "[[0 1 2]
                                       #        [3 4 5]]"
print(b.ndim)                          # 打印 "2"
print(b.shape)                         # 打印 "(2, 3)"
print(b.shape[0], b.shape[1])          # 打印 “2 3”
print(len(b))                          # 打印 "2"

c = np.array([[[1], [2]], [[3], [4]]])  # 创建3维数组
print(c)                                # 打印 "[[[1]
                                        #         [2]]
                                        #                (注意,打印时这里有一个空行)
                                        #        [[3]
                                        #         [4]]]"
print(c.shape)                          # 打印 "(2, 2, 1)"

注意:当你打印数组时,Numpy和嵌套列表以相似的方式显示,但是具有结构:

  • 最后一维从左到右打印
  • 倒数第二维从上到下打印
  • 其余的维度也是从上到下打印,每一项之间都会有一个空行。

用函数创建数组

Numpy还提供了很多用函数创建数组的方法:

  • arange:等间距分布的数组
import numpy as np

a = np.arange(10)             # 0,1,..n-1
print(a)                      # 打印 "[0 1 2 3 4 5 6 7 8 9]"
b = np.arange(1, 9, 2)        # start, end(不包含),step
print(b)                      # 打印 "[1 3 5 7]"
c = np.arange(0, 2.5, 0.4)    # 参数可以是浮点数
print(c)                      # 打印 "[ 0.   0.4  0.8  1.2  1.6  2.   2.4]"
  • linspace:指定数量(长度)的数组:
import numpy as np

d = np.linspace(0, 1, 6)                    # start,end, num-points
print(d)                                    # 打印 "[ 0.   0.2  0.4  0.6  0.8  1. ]"
e = np.linspace(0, 1, 5, endpoint=False)    # 可以显示的指定不包括最后一个点
print(d)        
  • 常用数组
import numpy as np

a = np.ones((1,2))                 # 创建元素全为1的数组
print(a)                           # 打印 "[[ 1.  1.]]"

b = np.zeros((2,2))                # 创建元素全为0的数组
print(b)                           # 打印 "[[ 0.  0.]
                                   #        [ 0.  0.]]"

c = np.full((2,2), 7)              # 创建一个用固定值填充的数组
print(c)                           # 打印 "[[ 7.  7.]
                                   #        [ 7.  7.]]"

d = np.eye(2)                      # 创建对角线为1,其它元素为0的2维数组
print(d)                           # 打印 "[[ 1.  0.]
                                   #        [ 0.  1.]]"

e = np.diag(np.array([1,2,3]))     # 从2维数组提取对角线,或从一维数组构建对角线矩阵
print(e)                           # 打印 "[[1 0 0]
                                   #        [0 2 0]
                                   #        [0 0 3]]"

f = np.empty((2,2))                # 创建随机初始的数组
print(f)                           #  打印 "[[  4.94065646e-324   9.88131292e-324]
                                   #         [  1.48219694e-323   1.97626258e-323]]"
  • np.random: 随机数数组
import numpy as np

a = np.random.rand(3)         # [0, 1)均匀分布随机值
print(a)                      # 可能打印 "[ 0.14662351  0.9235998   0.80878827]"

b = np.random.randn(2,2)      # 标准正态分布随机值
print(b)                      # 可能打印 "[[ 1.03371837  0.26109287]
                              #            [ 1.33813718 -0.85320254]]"

np.random.seed(1234)          # 设定随机数种子,产生可重复的结果

基本数据类型

你可能注意到,某些数组元素后面会跟着一个小数点 (比如 2. vs 2)。这是由于不同的数据类型所致。Numpy可以从输入自动推导出结果的数据类型:

import numpy as np

a = np.array([1, 2, 3, 4])
print(a.dtype)                    # 打印 "int64"

b = np.array([1., 2., 3., 4.])    # 打印 "float64"
print(b.dtype)

你也可以显式的指定你想得到的数据类型:

c = np.array([1, 2, 3], dtype=float)
print(c.dtype)                                # 打印 "float64"

d = np.array([1.,2.,3.]).astype('int64')
print(d.dtype)                                # 打印 "int64"

默认的数据类型是浮点数

e = np.ones((3, 3))
print(e.dtype)              # 打印 "float64"

Numpy还有一些其它的数据类型

e = np.array([1+2j, 3+4j, 5+6j])            # 复数
print(e.dtype)                              # 打印 "complex128"

f = np.array([True, False, False, True])    # 布尔值
print(f.dtype)                              # 打印 "bool"

g = np.array(['Bonjour', 'Hello', 'Hallo']) # 字符串
print(g.dtype)                              # 打印 "<U7"

索引、切片和迭代

索引

数组中的每一项可以像python的序列类型(如list)一样被访问和赋值

import numpy as np

# 创建一个一维数组 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
a = np.arange(10)
print(a[0], a[2], a[-1])      # 打印:0 2 9
print(a[::-1])                # 打印 [9 8 7 6 5 4 3 2 1 0]  (python中逆转序列依旧适用)

# 创建一个二维数组
# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]
b = np.arange(1,10).reshape(3,3)
print(b[1,1], b[2,1])          # 打印 "5 8"

# 当提供的索引数小于维度数时,缺失的索引表示全部切片
print(b[1])                    # 打印 "[4 5 6]"
print(b[1][2])                 # 打印 "6"

切片

和Python列表类似,numpy数组可以使用切片语法。因为数组可以是多维的,所以你必须为每个维度指定好切片。

import numpy as np

a = np.arange(10)        # 创建数组 [0 1 2 3 4 5 6 7 8 9]
print(a[2:9:3])          # 打印 [2 5 8]
print(a[1:4])            # 打印 [1 2 3]  (不包括最后一个索引)

# 切片的三个参数都不是必须的,start默认是0,end默认是最后,step默认是1
print(a[::2])            # 打印 [0 2 4 6 8]
print(a[3:])             # 打印 [3 4 5 6 7 8 9]                

# 创建如下二维数组,shape=(3, 4)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
b = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])

# 使用切片操作得到一个由a的前两行和列1和列2组成的子数组c
# 数组c如下所示,shape=(2, 2)
# [[2 3]
#  [6 7]]
c = b[:2, 1:3]

# 数组的一个切片是相同数据上的一个视图,共享内存内存地址,
# 因此修改切片数组会改变原始数组
print(b[0, 1])   # 打印 "2"
c[0, 0] = 77     # b[0, 0]与a[0, 1]代表同一个数据
print(b[0, 1])   # 打印 "77"
# 这种行为看起来很奇怪,但是可以帮助节省内存和时间开销。

你可以同时使用整型和切片语法来访问数组。但是,这样做会产生一个比原数组低阶的新数组。需要注意的是,这里和MATLAB中的情况是不同的:

import numpy as np

# 创建一个二维数组,shape=(3, 4)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])

# 访问数组中间行数据的两种方式
# 混合使用整数索引和切片产生一个低阶的数组
# 只使用切片产生和原始数组相同阶的数组
row_r1 = a[1, :]             # a第二行的1维视图 
row_r2 = a[1:2, :]           # a第二行的2维视图
print(row_r1, row_r1.shape)  # 打印 "[5 6 7 8] (4,)"
print(row_r2, row_r2.shape)  # 打印 "[[5 6 7 8]] (1, 4)"

# 当访问数组的列时也会产生同样的差别
col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print(col_r1, col_r1.shape)  # 打印 "[ 2 6 10] (3,)"
print(col_r2, col_r2.shape)  # 打印 "[[ 2]
                             #        [ 6]
                             #        [10]] (3, 1)"

下图是一个切片和索引操作的图解。

你也可以将赋值和切片结合起来

import numpy as np

a = np.arange(10)       # 创建数组 [0 1 2 3 4 5 6 7 8 9]
a[5:] = 10
print(a)                # 打印 "[ 0  1  2  3  4 10 10 10 10 10]"

b = np.arange(5)        # 创建数组 [0 1 2 3 4]
a[5:] = b[::-1]         
print(a)                # 打印 "[0 1 2 3 4 4 3 2 1 0]"

Fancy indexing

Numpy提供了比常规python序列更多的索引方式。除了可以使用整数和切片索引,也可以使用布尔数组或者整数数组索引,这种方法叫做fancy indexing。它创建拷贝而不是视图。

整型数组访问:当我们使用切片语法访问数组时,得到的总是原数组的一个子集。整型数组访问允许我们利用其它数组的数据构建一个新的数组。当一个新数组是由整数数组索引创建的,新数组与这个整数数组的shape相同。

  • 被索引数组是一维数组
import numpy as np

a = np.arange(0, 100, 10)             # 创建一维数组 [0 10 20 30 40 50 60 70 80 90]

# 索引是一维数组,返回的数组shape=(5,),与索引数组i相同
i = np.array([1,1,3,8,5])             # 同一个索引值可以重复多次
print(a[i])                           # 打印 "[10 10 30 80 50]"

# 索引也可以是列表
print(a[[1,1,3,8,5]])                 # 打印 "[10 10 30 80 50]" 

# 索引是二维数组。返回数组的shape=(2, 2),与索引数组j的shape相同。
j = np.array([ [ 3, 4], [ 9, 7 ] ])   # shape = (2, 2)
print(a[j])                           # 打印 "[[30 40]
                                               [90 70]]"
  • 被索引数组是多维数组
import numpy as np

# 创建二维数组,shape=(3, 2)
#   [[1 2]
#    [3 4]
#    [5 6]]
a = np.array([[1,2], [3, 4], [5, 6]])

# 当被索引数组是多维的时,单独的一个索引数组代表源数组的第一个维度
idx = np.array([0,1])
print(a[idx])                       # 打印 "[[1 2]
                                             [3 4]]"             

# 我们可以给定多于一个索引数组
# 为每一维指定的索引数组的shape要相同
print(a[[0, 1, 2], [0, 1, 0]])      # 打印 "[1 4 5]"

# 上面整数数组的索引的例子与下面等价:
print(np.array([a[0, 0], a[1, 1], a[2, 0]]))  # 打印 "[1 4 5]"

idx1 = np.array([[0,1],[1,2]])
idx2 = np.array([[1,0],[0,1]])
print(a[idx1,idx2])                  # 打印 "[[2 3]
                                     #        [3 6]]"

整型数组访问语法还有个有用的技巧,可以用来选择或者更改矩阵中每行中的一个元素:

import numpy as np

a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
print(a) # prints "array([[ 1,  2,  3],
         #                [ 4,  5,  6],
         #                [ 7,  8,  9],
         #                [10, 11, 12]])"

# 创建整数数组索引
b = np.array([0, 2, 0, 1])

# 使用b中的索引值从每一列中选择一个元素
print(a[np.arange(4), b])  # Prints "[ 1  6  7 11]"

# 索引b从每行中选择的元素都加上10
a[np.arange(4), b] += 10

print(a)    # 打印 "array([[11,  2,  3],
            #              [ 4,  5, 16],
            #              [17,  8,  9],
            #              [10, 21, 12]])

布尔型数组访问

布尔型数组访问可以让你选择数组中任意元素。

import numpy as np
#******************Example 1*****************************
#通常,这种访问方式用于选取数组中满足某些条件的元素:
a = np.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2)  # 找到比2大的所有元素;
                    # 这会返回一个与a形状相同的布尔数组;
                    # 每一个位置的布尔值代表原数组中该位置的元素是否大于2

print(bool_idx)     # 打印   "[[False False]
                    #          [ True  True]
                    #          [ True  True]]"

# 我们可以使用布尔数组索引构建一个1维数组,包含bool_idx中True对应的元素。
print(a[bool_idx])  # 打印 "[3 4 5 6]"

# 我们可以使用一条简明的语句完成以上所有操作
print(a[a > 2])     # 打印 "[3 4 5 6]"

# 我们也可以使用布尔数组索引对bool_idx中True对应的元素赋值
a[a>2] = 2
print(a)           # 打印 "[[1 2]
                            [2 2]
                            [2 2]]"

#**********************Example 2************************
#创建一个2维数组,shape=(3, 4)
#  [[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
a = np.arange(12).reshape(3,4)

b1 = np.array([True, True, False])         # 第一维的选择
b2 = np.array([True, False, True, False])  # 第二维的选择

print(a[b1, :])        # 打印 "[[0 1 2 3]
                       #        [4 5 6 7]]"
print(a[:, b2])        # 打印 "[[ 0  2]
                       #        [ 4  6]
                       #        [ 8 10]]"
print(a[b1, b2])       # 打印 "[0 6]"

为了教程的简介,有很多数组访问的细节我们没有详细说明,可以查看文档

 

拷贝和视图

当操作数组时,有时它们的数据会拷贝到一个新的数组,有时则不会。主要有以下几种情况

没有拷贝

简单的赋值操作不会对数组对象或者它们的数据产生拷贝:

import numpy as np

a = np.arange(12)
b = a                                # 一个新的对象被创建
# a和b是同一个ndarray对象的2个名字
print(b is a)                        # 打印 "True"
# 改变a的shape, b的shape自然也会改变
b.shape = 3,4                      
print(a.shape)                       # 打印 "(3, 4)"

视图或者浅拷贝

不同的array对象可以共享相同的数据。view方法创建了一个共享相同数据的新数组对象。

c = a.view()               # 用view方法创建数组c
print(c is a)              # 打印 "False"
print(c.base is a)         # 打印 "True"   
print(c.flags.owndata)     # 打印 "False"

c.shape = 2,6              # a的shape不改变
print(a.shape)             # 打印 "(3, 4)"

c[0,4] = 1234              # a的数据会改变
print(a)                   # 打印 "[[   0    1    2    3]
                           #        [1234    5    6    7]
                           #        [   8    9   10   11]]"

深拷贝

d = a.copy()               # 创建一个拥有新数据的新数组,d和a不共享任何东西
print(d is a)              # 打印 "False"
print(d.base is a)         # 打印 "False"

d[0,0] = 9999              # a的数据不会改变
print(a)                   # 打印 "[[   0    1    2    3]
                                    [1234    5    6    7]
                                    [   8    9   10   11]]"

基本运算

基本数学计算函数会对数组中元素逐个进行计算,既可以利用操作符重载,也可以使用函数方式:

import numpy as np

x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)

# 逐元素加法;都产生以下数组
# [[ 6.0  8.0]
#  [10.0 12.0]]
print(x + y)
print(np.add(x, y))

# 逐元素减法;都产生以下数组
# [[-4.0 -4.0]
#  [-4.0 -4.0]]
print(x - y)
print(np.subtract(x, y))

# 逐元素乘法;都产生以下数组
# [[ 5.0 12.0]
#  [21.0 32.0]]
print(x * y)
print(np.multiply(x, y))

# 逐元素除法;都产生以下数组
# [[ 0.2         0.33333333]
#  [ 0.42857143  0.5       ]]
print(x / y)
print(np.divide(x, y))

# 逐元素求平方根;产生以下数组
# [[ 1.          1.41421356]
#  [ 1.73205081  2.        ]]
print(np.sqrt(x))

# 逻辑运算
a = np.array([1, 1, 0, 0], dtype=bool)
b = np.array([1, 0, 1, 0], dtype=bool)

# 逐元素求逻辑与;都产生以下数组
# [ True False False False]
print(a & b)
print(np.logical_and(a,b))

# 逐元素求逻辑或;都产生以下数组
# [ True  True  True False]
print(a | b)
print(np.logical_or(a, b))

注意:*是数组乘法并非矩阵乘法。在Numpy中使用dot来进行矩阵乘法:

import numpy as np

x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])

v = np.array([9,10])
w = np.array([11, 12])

# 向量的内积;结果都是219
print(v.dot(w))
print(np.dot(v, w))

# 矩阵和向量的矩阵乘法;结果都是是1维数组[29 67]
print(x.dot(v))
print(np.dot(x, v))

# 矩阵和矩阵的矩阵乘法;结果是2维数组
# [[19 22]
#  [43 50]]
print(x.dot(y))
print(np.dot(x, y))

一些操作,如+=*=,会原地更改一个已经存在的数组而不会创建一个新的数组。

一些操作,如+=*=,会原地更改一个已经存在的数组而不会创建一个新的数组。

import numpy as np

a = np.ones((2,3), dtype=int)
a *= 3                           # 原地操作
print(a)                         # 打印 "[[3 3 3]
                                 #        [3 3 3]]"

操作不同数据类型的数组时,结果数组的类型会与更精确的数组的类型一致。

import numpy as np

a = np.ones(3, dtype=np.int32)   # dtype = int32
b = np.linspace(0,3,3)

print(b.dtype)                   # float64
c = a + b
print(c.dtype)                   # float64

 超越函数

import numpy as np

x = np.array([[1,2],[3,4]], dtype=np.float64)

# 逐元素求对数;产生以下数组
# [[ 0.          0.69314718]
#  [ 1.09861229  1.38629436]]
print(np.log(x))

# 逐元素求指数;产生以下数组
# [[  2.71828183   7.3890561 ]
#  [ 20.08553692  54.59815003]]
print(np.exp(x))

# 逐元素求sin;产生以下数组
# [[ 0.84147098  0.90929743]
   [ 0.14112001 -0.7568025 ]]
print(np.sin(x))

比较操作

import numpy as np

a = np.array([1, 2 ,3, 4])
b = np.array([4, 2 ,2, 4])
c = np.array([1, 2, 3, 4])

# 逐元素比较
print(a == b)                  # 打印 "[False  True False  True]"
print(a > b)                   # 打印 "[False False  True False]"

# 数组整体比较
print(np.array_equal(a, b))    # 打印 "False"
print(np.array_equal(a, c))    # 打印 "True"

Basic reductions

默认情况下,这些操作会忽略数组的shape,将数组看做一个整体。然而,我们可以指定axis参数,你可以指定某个axis执行一个操作。

求和、求平均

import numpy as np

x = np.array([[1,2],[3,4]])

# 计算所有元素的和; 结果都是 "10"
print(np.sum(x))          
print(x.sum())

# 计算每一列的和; 结果都是 "[4 6]"
print(np.sum(x, axis=0))  
print(x.sum(axis=0))

# 计算每一行的和; 结果都是
# " [[3]
#    [7]]"
print(np.sum(x, axis=1,keepdims=True)) 
print(x.sum(axis=1,keepdims=True))

# mean的用法和sum类似
# 计算整个数组平均值;结果是 "2.5"
print(x.mean())

求极值

格式与求和运算类似

import numpy as np

x = np.array([[1,2],[3,4]])

print(x.max())             # 计算所有元素的最大值;结果是"4"
print(x.min())             # 计算所有元素的最小值;结果是"1"
print(x.argmax())          # 返回最大值索引;结果是"3"
print(x.argmin())          # 返回最小值索引;结果是"0"

逻辑运算

import numpy as np
print(np.all([True, True, False]))  # 打印 "False"
print(np.any([True, True, False]))  # 打印 "True"

截断操作

import numpy as np

a = np.arange(1,13).reshape(3,4)
# 将数组a中元素都截断在[2,9]的范围内
# "[2 2 3 4]
#  [5 6 7 8]
#  [9 9 9 9]]
print(np.clip(a,2,9))              

广播

NumPy 数组的基本操作(比如加法)都是逐元素的(elementwise)。这当然要求进行运算的两个数组大小(shape)相同。然而 ,不同大小(shape)的数组之间也可能进行运算。广播是一种强有力的机制,它让Numpy可以让不同大小的矩阵在一起进行数学计算

最简单的一种情况是一个数组和一个标量的操作

import numpy as np

# 两个shape相同的数组相乘
a = np.array([1.0, 2.0, 3.0])
b = np.array([2.0, 2.0, 2.0])
print(a * b)      # 打印 "[ 2.  4.  6.]"

# 一个数组和一个标量相乘
a = np.array([1., 2., 3.])
b = 2.0
print(a*b)        # 打印 "[ 2.  4.  6.]"

'''
这个结果和前面b是数组的例子的结果相同。我们可以认为b在运算中被扩展成了和a尺寸相同的数组,
b中新元素就是原来元素的拷贝。当然这个关于扩展的类别只是概念上的。Numpy是非常智能的,
可以只使用一个标量而不用拷贝来完成这个操作。所以广播操作的内存和计算效率都是很高的。
第二个例子比第一个例子更高效,因为广播在进行乘法操作时移动更少的内存。
'''

一般的广播规则

  1. 如果数组的秩不同,使用1来将秩较小的数组进行扩展,直到两个数组的尺寸的长度都一样。
  2. 如果两个数组在某个维度上的长度是一样的,或者其中一个数组在该维度上长度为1,那么我们就说这两个数组在该维度上是相容的。
  3. 如果两个数组在所有维度上都是相容的,他们就能使用广播。
  4. 如果两个输入数组的尺寸不同,那么注意其中较大的那个尺寸。因为广播之后,两个数组的尺寸将和那个较大的尺寸一样。
  5. 在任何一个维度上,如果一个数组的长度为1,另一个数组长度大于1,那么在该维度上,就好像是对第一个数组进行了复制。

如果上述解释看不明白,可以读一读文档

import numpy as np

# 计算向量外积
v = np.array([1,2,3])  # v的shape= (3,)
w = np.array([4,5])    # w的shape= (2,)

# 为了计算外积,我们先把v变成(3,1)的列向量;
# 结果如下
# [[ 4  5]
#  [ 8 10]
#  [12 15]]
print np.reshape(v, (3, 1)) * w

# 把向量加到矩阵的每一行
x = np.array([[1,2,3], [4,5,6]])
print x + v    # 打印 "[[2 4 6]
               #        [5 7 9]]"

数组形状操作

Flattening

import numpy as np

a = np.array([[1,2,3],[4,5,6]])
# 以下两个函数都将多维数组变成一维数组
# 区别是 ravel 返回视图;flatten 返回拷贝。
# 结果都是 "[1 2 3 4 5 6]"
print(a.ravel())           
print(a.flatten())

Reshaping

import numpy as np

a = np.array([1,2,3,4,5,6])
print(b.reshape(2,3))       # 打印 "[[1 2 3]
                            #        [4 5 6]]"

添加维度

使用np.newaxis对象允许我们为数组添加一个维度

import numpy as np

z = np.array([1, 2, 3])

# 数组 shape= (3, 1)
# 结果 "[[1]
#        [2]       
#        [3]]"
print(z[:,np.newaxis])

# 数组 shape = (1, 3)
# 结果 " [[1 2 3]]"
pirnt(z[np.newaxis,:]) 

Dimension shuffling

import numpy as np

a = np.arange(4*3*2).reshape(4,3,2)
print(a.shape)                        # 打印 "(4, 3, 2)"

# 将数组a的维度次序改变得到b
# 后两个维度移到前两个维度,第一个维度移到最后
b = a.transpose(1,2,0)                # transpose得到的数组b是数组a的视图
print(b.shape)                        # 打印 "(3, 2, 4)"
print(a[0,2,1] == b[2,1,0])           # 打印 "True"

合并

import numpy as np

A = np.array([1,1,1])
B = np.array([2,2,2])

# 在竖直方向上叠加数组A,B
# 结果如下
# [[1 1 1]
#  [2 2 2]]
print(np.vstack((A,B)))

# 在水平方向上叠加数组A,B
# 结果如下
# [1 1 1 2 2 2]
print(np.hstack((A,B)))

# 在不存在的维度上组合数组
print(np.stack((A,B),axis=0))  # shape = (2, 3)
                               # [[1 1 1]
                               #  [2 2 2]]

print(np.stack((A,B),axis=1))  # shape = (3, 2)
                               # [[1 2]
                               #  [1 2]
                               #  [1 2]]

# 在存在的维度上组合数组
A = A[np.newaxis,:]          # shape = (1,3)
B = B[np.newaxis,:]          # shape = (1,3)
print(np.concatenate((A,B),axis=0))   # shape = (2, 3)
                                      # [[1 1 1]
                                      #  [2 2 2]]
print(np.concatenate((A,B),axis=1))   # shape = (1, 6)
                                      # [[1 1 1 2 2 2]]

分割

split的第二个参数可以是整数或者一维数组。

  • 如果是整数。数组将被分为N个相等的数组。如果无法分成相等的数组,将会报错。
  • 如果是一维数组。数组的每一个元素表明了在哪个位置分割数组。举个例子:

[2, 3] ,当axis=0时,结果为:

- ary[:2]
- ary[2:3]
- ary[3:]

import numpy as np

# 创建数组,shape = (3, 4)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
A = np.arange(12).reshape((3, 4))

# 纵向分割
# 结果如下
#  [array([[0, 1],
#         [4, 5],
#         [8, 9]]), array([[ 2,  3],
#         [ 6,  7],
#         [10, 11]])]
print(np.split(A,2,axis=1))

# 横向分割
# 结果如下
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]
print(np.split(A,3,axis=0))

# split不均等分割
# 结果如下
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]
print(np.split(A,[1,2],axis=0))

# array_split进行不等量分割
# array_split和split唯一的区别是:
# array_split允许indices_or_sections是一个将数组不等分的整数
# 结果如下
# [array([[0, 1, 2, 3],
#        [4, 5, 6, 7]]), array([[ 8,  9, 10, 11]])]
print(np.array_split(A, 2, axis=0))

数据排序

import numpy as np

# 创建2维数组,shape = (2, 3)
# [[4 3 5]
#  [1 2 1]]
a = np.array([[4, 3, 5], [1, 2, 1]])

# 可以在数组的某一维排序
# 结果如下
#  [[3 4 5]
#   [1 1 2]]
print(np.sort(a, axis=1))      

# 原地(in-place)排序
# a本身会被排序,打印a结果如下
#  [[3 4 5]
#   [1 1 2]]
a.sort(axis=1)
print(a)

# 排序与数组索引技巧结合:
b = np.array([4, 3, 1, 2])
j = np.argsort(a)
print(j)                   # 打印 "[2 3 1 0]" 对应排序后元素原来的索引
print(b[j])                # 打印 "[1 2 3 4]" 用数组j索引得到排序后的数组

# 找出极大、极小值对应的元素索引
c = np.array([3, 4, 1, 2])
j_max = np.argmax(b)
j_min = np.argmin(b)
print(j_max)               # 最大值索引 "1"
print(j_min)               # 最小值索引 "2"

Numpy文档

这篇教程涉及了你需要了解的numpy中的一些重要内容,但是numpy远不止如此。可以查阅官方文档来学习更多。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值