numpy - baibing0716/python GitHub Wiki

一、 numpy

1.1 numpy简介

numpy 提供了一种数组类型,主要是针对多维数组处理;

numpy 其中元素的数据类型是一致的,基本针对int 或 float数据处理(强一致性)   【array中数据类型不一致,强制统一数据类型 优先级顺序 str > float > int】

最原始类型: numpy.array(list)

1.2 numpy的基础操作

numpy 创建

numpy 属性:     

numpy 索引和切片 详见1.5

numpy 常用操作

numpy 广播原则: 必须要保证参与运算的两个数组形状一致                                           # (1)缺失维度补1     (2)用已有的值填充

numpy 聚合运算: 指的是numpy提供的聚合函数

numpy 排序方式: np.sort() 与 np.partition()

1.3 numpy创建

常见参数:
# object通常指List对象 dtype指np.array对象元素类型
# copy 是否作副本拷贝 【order='K' 指的是内存序列而非排序】
# subok 针对继承类是否可见 
# ndmin表示np.array维度

(1) numpy.arrary 创建 [(1)强制数据类型统一 (2)适合一维数组]

    np.arrary([1, 2, 3, 4, 5])                      # 格式1

    np.array([1, 3.14, 'hello'], dtype='<U32')      # 格式2 里面内容为字符串类型

    np.arrary([1, 2, 3], [4,5,7])

(2) np.ones(shape, dtype=None, order='C')  [创建多维数组 1填充] 最后一个参数为内存序不需要设置

    shape = (m, n)                                  # m行n列的二维数组
    shape = (m, 1)                                  # m行1列的二维数组   [1], [2], [3](/baibing0716/python/wiki/1],-[2],-[3)
    shape = (1, m)                                  # 1行m列的二维数组   [1, 2, 3](/baibing0716/python/wiki/1,-2,-3)
    shape = (m,)                                    # m个元素的一维数组  [1, 2, 3]
    shape = (m)                                     # m个元素的一维数组

    array1 = np.ones(shape=(5, 3), dtype="float")   // 5 行 3列的二维数组 默认 1.0填充
    array2 = np.ones(shape=(6,), dtype="int")       // 6 个元素的一维数组 1 填充

(3) np.zeros(shape, dtype=None, order='C') [创建多维数组 0填充]

    array4 = np.zeros(shape=(3,))                  # 一维数组(3个元素)[0. 0. 0.]
    array5 = np.zeros(shape=(3,1))                 # [[0.]        3行1列二维数组
                                                     [0.]
                                                     [0.]]
    array6 = np.zeros(shape=(1,3))                 # [0. 0. 0.](/baibing0716/python/wiki/0.-0.-0.) 1行3列二维数组

    array7 = np.zeros(shape=(2,3,4),dtype='int')   # 三维数组的表示

(4) np.full(shape, fill_value, dtype=None, order='C') [创建多维数组 自定义值填充]

    用法同上
(5) np.eye(N, M=None, k = 0, dtype=float) [生成单位矩阵:对角线为1的矩阵]

    因为是矩阵 通常情况下N == M,M控制生成矩阵的里面元素个数

    k > 0 对角线向右移动 k;       k < 0 对角线向左移动 k;

(6) np.linspace(start, end, num=50, endPoint=True, retstep=False,dtype=None) [构造等差数列---指定个数]

    start 数列的第一项  end 数列的最后一项  num 生成的等差数列元素的个数

    endPoint 构造的等差数列的时候是否包含end

    retstep 是否返回指定的步长

    arr = np.linspace(0, 10, 10, endpoint=False)

(7) np.arange([start,] stop, [step,] dtype=None) [构造等差数列---指定公差]

    arr = np.arange(0, 5050, step = 10)

(8) np.random.randint(low, high=None, size=None, dtype=None)    [生成随机数]

    low 随机数的起始值  high 随机数的最大值  size 随机数的矩阵格式  区间格式: [0, 100)

    r = np.random.randint(0, 100, size=(3, 5))

(9) np.random.randn(d0, d1, d2, ..., dn)          [生成符合标准正态分布的数]

    np.random.normal(loc, scale, size)            [生成普通正态分布的数]
        loc 表示期望值  scale 方差  size 生成的矩阵的图形

    r1 = np.random.randn(100)                     [随机生成100数,这些数满足正态分布]
    r2 = np.random.randn(3, 5)                    [随机生成3行5列的矩阵,这些数满足正态分布]

    r3 = np.random.normal(loc=170, scale=5, size=(5,5))

(10) np.random.random(size)                       [生成的0-1范围内的随机数]

    r4 = np.random.random(100)                    [生成100个0-1范围内的随机数 1维]

    r4 = np.random.random(size=(5,5))             [生成25个0-1范围内的随机数  2维 5行5列]

(11) np.random.permutation(num)                   [生成随机索引--里面元素不重复]

    r5 = np.random.permutation(10)

    r6 = np.random.permutation(size=(5,5))         XXXXXXXX 不支持

1.4 numpy属性

numpy数组的四个属性 ndim   shape    size   dtype
                  维度   矩阵形状  元素个数 元素类型

arr = np.random.randomint(0, 100, size(5, 4, 3));

print(arr.ndim)                                        # 输出 3  np.array为3维

print(arr.shape)                                       # 输出 (5, 4, 3)  np.array最终形状

print(arr.size)                                        # 输出 60  np.array总共有多少个元素

print(arr.dtype)                                       # 输出 dtype='int32'  np.array的【元素类型】而非对象类型  type(arr) = numpy.ndarray

1.5 numpy的索引和切片

索引访问元素: arr[m, n, ...]

索引访问行: arr[行索引]

索引访问列: arr[:, 列索引]

高级访问方式:使用list方式作为索引(索引列表、BOOL列表)
------------------------------------------------------
切片:在每一个维度上指定切片范围

            arr[1:3, 1:3]           最外层 选择第2、3   最外层 - 1层 选择 2、3
-----------------------------------------------------------------------------------------------------------------------------------------
列表访问方式
一维: data = [1, 2, 3, 4]            # data[0] = 1                    

二维: data = [1, 2, 3], [4, 5, 6](/baibing0716/python/wiki/1,-2,-3],-[4,-5,-6)  # data[0] = [1, 2, 3]     data[0][0] = 1


一维list的切片: data = [1, 2, 3, 4]  # data[0:3] = [0, 1, 2]   切片的区间左闭右开

二维list的切片: data = [[45 39 60 90  5 96]                   # 切前两行  data[0:2]       行切片(默认 列的维度上不切分)
                        [60 82 39 72 34 63]                   # 切前两列  data[:, 0:2]    列切片(行的维度上不切分 所有行保留所以:,保留了所有行)
                        [73 33 18 76 93 60]                   
                        [61 63 92 62 92 92]                   # 切第三行  data[2:3]      切第3、4行 data[2:4]
                        [33 57  8 18 34 24]]                  # 切第三列  data[:, 2:3]   切第3、4列 data[:, 2:4]
-----------------------------------------------------------------------------------------------------------------------------------------
ndarray的Index是从0开始的

一维的数组: 
    a = np.arrange(10)                # 0 1 2 3 4 5 6 7 8 9         切片函数 a[slice(2, 7, 2)] = [2, 4, 6]      start, end, step 2 7 2    

    a[2]                              # 值为2

    a[2:]                             # 值为2 3 4 5 6 7 8 9

    a[2:7]                            # 值为2 3 4 5 6 

    a[2:7:2]                          # 值为2, 4, 6

二维的数组:

    a = np.array([1,2,3,33,44],[3,4,5,66,99],[4,5,6,111,555](/baibing0716/python/wiki/1,2,3,33,44],[3,4,5,66,99],[4,5,6,111,555))    # shape = 3 * 5

    a[1]                                                           # 输出[3,4,5,66,99]     取的是某一行a[n]

    a[1:]                                                          # 输出[[3,4,5,66,99]     取的是从某一行开始直至最后一行的a[n:]
                                                                         [4,5,6,111,555]]

    a[..., 3]                                                      # 输出[33  66 111]      取的是某一列    ,分割维度

    a[..., 3:]                                                     # 输出[[ 33  44]        取的是从第3列开始到最后
                                                                          [ 66  99]
                                                                          [111 555]]

    a[:, 3]                                                        # 同上[33  66 111]      取的是某一列

    a[:, 3:]                                                       # 同上[[ 33  44]        取的是从第3列开始到最后
                                                                          [ 66  99]
                                                                          [111 555]]

    a[1, 1]                                                        # 等价于 a[1][1] = 4 (列表访问方式)a[1, 1] (numpy访问方式)

三维数组: arr3 =np.random.randint(0, 20, size=(5, 4, 3))

[[[ 6 12  6]         
  [ 2 16 12]
  [16  2 11]
  [ 8  9  8]]

 [[ 2  8  6]                            # 访问 [ 2  8  6]      arr3[1, 0]           1 表示最外层维度  0 表示最外层 -1 维度
  [ 6  0 13]                            # 访问 13              arr3[1, 1, 2]
  [14  9 14]
  [ 9  6 18]]

 [[12  8  3]                            # 切 a[2:3] 就可以得出第3块 
  [ 3  4  2]                            # 切 a[2:3, 1:2] 就可以得出第3块的第2行 a[2:3, 1:2, 2] 表示的元素即2
  [ 9 11 16]                            # 切 a[2:3, :, 1:3] 切第3块的最后两列
  [ 4  1  3]]

 [[17  1 19]                            # 切 a[:, :, 1,3] 所有的最后两列
  [14  6 12]
  [10 17 16]                            
  [18  4  6]]

 [[10  9  6]
  [15 19 11]
  [11 16 10]
  [10  4  4]]]

numpy高级访问方法
(1) arr([1, 2, 3, 4, 5])                                         # arr[0, 1, 2, 0, 1, 2](/baibing0716/python/wiki/0,-1,-2,-0,-1,-2) = [1, 2, 3, 1, 2, 3]       使用int型list对原arr重组

(2) arr([1, 2, 3, 4, 5])                                         # arr[True, False, True, False, True](/baibing0716/python/wiki/True,-False,-True,-False,-True) = [1, 3, 5]  使用bool型可以去除arr中不想要元素

                                                                   # arr[arr > 3] 提取原本List中大于3的元素  结果 【4, 5】

总结:
    (1)numpy[m, n, ...]中m, n都是描述的是从最外层--->最后维度的索引

    (2)numpy访问的高级索引方式: (a)以int类型的list作为index进行访问   (2)以bool类型的list作为index进行访问

     (3) 不论多少维,【每一个维度的切片范围都是用 “:” 表示】,【维度与维度之间递进关系用,分割】

    (4)一维数据的反转  arr([1, 2, 3, 4, 5])  ========   arr[::-1];   start  end  step = -1 就会将整个一维数组进行反转
         
         二维数据的反转: 行反转   arr[::-1]
                         列反转   arr[:, ::-1]
                            

1.6 numpy的常用操作

(1) reshape 变形------标准写法:传入参数类型应该是一个元组

arr = np.random.randint(0, 100, size=(20));               # 一维的随机数 20个

arr.reshape((4, 5))                                       # reshape前后数据元素的个数必须保证一致 

输出:
[70 31 41 27 66 25 14 51 52 70 38 53 19 49 65 81 59 48 76 98]

[[70 31 41 27 66]
 [25 14 51 52 70]
 [38 53 19 49 65]
 [81 59 48 76 98]]

(2) concatenate级联

注意点:(a)级联函数的参数类型是List,且List的外部必须加()或[]

        (b)级联的两个np.array的ndim维度必须相同

        (c)级联的两个np.array的shape形状必须相同
     
        (d)级联的方向控制 通过axis参数改变

        (e)默认级联方向:shape位于某个tuple中的第一个值所代表的维度

arr1 = np.random.randint(0, 10, size=(3,3))
arr2 = np.random.randint(0, 20, size=(3,3))
res1= np.concatenate((arr1, arr2))                      # 默认纵向级联   等价写法       res1 = np.vstack((arr1, arr2));       

arr1              arr2                     res1
[[6 6 8]         [[ 8  1  6]              [[ 6  6  8]
 [3 2 5]          [ 0 17 15]               [ 3  2  5]
 [6 3 8]]         [ 4 14  5]]              [ 6  3  8]
                                           [ 8  1  6]
                                           [ 0 17 15]
                                           [ 4 14  5]]

res2= np.concatenate((arr1, arr2), axis=1)             # 设置为横向级联   等价写法       res2 = np.hstack((arr1, arr2));     
arr1              arr2                     res2
[[6 6 8]         [[ 8  1  6]              [[ 6  6  8  8  1  6]
 [3 2 5]          [ 0 17 15]               [ 3  2  5  0  17 15]
 [6 3 8]]         [ 4 14  5]]              [ 6  3  8  4  14 5]]

(3) split操作
arr = np.random.randint(0, 50, size=(6,6))

part1, part2 = np.split(arr, indices_or_sections=2)           # 将原np.array切分成两份      等价于   np.hsplit(arr, indices_or_sections=2)

       arr                                  part1                           part2
[[48 28  6  8 20 19]                 [[48 28  6  8 20 19]               [[20 11  0 19 18 25]
 [ 8 34 28  6 13 43]                  [ 8 34 28  6 13 43]                [24 13 23 36 34  1]
 [30 13 28 42  4 45]                  [30 13 28 42  4 45]]               [ 7 21 46 17 27 44]]
 [20 11  0 19 18 25]
 [24 13 23 36 34  1]
 [ 7 21 46 17 27 44]]

p1, p2, p3 = np.split(part1, indices_or_sections=[2, 4], axis = 1)      # indices_or_sections列表切分含义: 切分 [0:2) [2,4) [4,尾) 成这样的三份

      part1                              p1               p2             p3
[[48 28  6  8 20 19]                 [[48 28]            [[6  8]       [[20 19] 
[ 8 34  28  6 13 43]                  [ 8 34]             [28 6]        [13 43]
[30 13  28  42 4 45]]                 [30 13]]            [28 42]]      [4 45]] 

part1, part2 = np.split(arr, indices_or_sections=2,  axis=1)   # indices_or_sections指定切分之后的份数  axis指定切分方向  等价于 np.vsplit(arr, indices_or_sections=2)
 arr                                  part1                        part2
[[48 28  6  8 20 19]                 [[48 28  6]                 [[8 20 19]
 [ 8 34 28  6 13 43]                  [ 8 34 28]                  [6 13 43]
 [30 13 28 42  4 45]                  [30 13 28]                  [42  4 45]
 [20 11  0 19 18 25]                  [20 11  0]                  [19 18 25]
 [24 13 23 36 34  1]                  [24 13 23]                  [36 34  1]
 [ 7 21 46 17 27 44]]                 [ 7 21 46]]                 [17 27 44]]   

(4) copy操作 生成一个np.array的副本

l1 = [1, 3, 5]

arr = np.array(l1)

copyobj = arr.copy(arr)                 # 生成一个arr的拷贝对象副本  修改copyobj不会影响其arr的改变

1.7 numpy聚合函数

arr = np.random.randint(0, 50, size=(10))

[25 20 20 26 37  2 34 42  8 30]
---------------------------------------------------------------------------------------------
np.sum                         # 求np.array对象中所有元素的【和】                arr.sum()        

np.mean                        # 求np.array对象中所有元素的【平均值】            arr.mean()

np.prod                        # 求np.array对象中所有元素的【乘积结果】          arr.prod()

np.std                         # 求np.array对象中所有元素的【标准方差】          arr.std()            

np.var                         # 求np.array对象中所有元素的【方差】              arr.var()                                  

np.min                         # 求np.array对象中所有元素的【最小值】            arr.min()

np.max                         # 求np.array对象中所有元素的【最大值】            arr.max()        

np.argmin                      # 求np.array对象中所有元素的【最小值索引】        arr.argmin()

np.argmax                      # 求np.array对象中所有元素的【最大值索引】        arr.argmax()

np.median                      # 求np.array对象中所有元素的【中位数】            arr.median()

np.percentile                  # 求np.array对象中所有元素的【百分位数】          看下面示例 主要用于异常值检测 然后清理离散点 

np.power                       # 幂运算

np.any                         # 是否存在NAN(空值),至少存在一个则返回True     boollist = arr > arr.mean();   arr[boollist]表示过滤arr中所有 > 平均值的元素

np.all                         # 是否全为NAN(空值),全部都是NAN则返回True      

重要: (arr > 10).any()       arr中是否存在 > 10的数
---------------------------------------------------------------------------------------------
方差: ((e1 - 平均值)**2 + (e2 - 平均值)**2 + ... + (en - 平均值)**2) / n  

标准方差: sqrt(方差)

示例:  
arr = np.arange(0, 11, step=1)                                    
 
res = np.percentile(arr, [0.25, 0.5, 0.75])           

print(res)                                            # 输出 [0.025 0.05  0.075]

1.8 numpy广播机制

广播机制原则: (1)为缺失的维度补1      (2) 假定缺失元素用已有的元素进行补充

一维广播:
arr = [1, 3, 4]
a = np.array(arr)
a + 3                               # 输出 [4, 6, 7]                              
 
a + 3本质:
[1, 3, 4]
[3, 3, 3]                           # 用已有的值补充对齐

二维广播:
m = np.ones((2, 3))                 
n = np.arange(3)
m + n                               # 输出 [[1, 2, 3],              
                                            [1, 2, 3]]
m + n本质

   m                 n         广播机制n按已有值补全    n  
[[1, 1, 1]        [0, 1, 2]                         [0, 1, 2]    
[1, 1, 1]]                                          [0, 1, 2]

特殊形式广播:
a = np.arange(3).reshape(3,1)            # 3行1列
b = np.arange(3)                         # 1行3列
a + b;

 
[[0],         [0, 1, 2]   === 广播机制===   [[0], [0], [0],             [[0, 1, 2]                                         
[1],                                        [1], [1], [1]               [0, 1, 2]     
[2]]                                        [2], [2], [2]]              [0, 1, 2]]


乘法广播: arr * 4  指的是每个元素乘以4的结果

          np.dot(arr1, arr2)  指的数学意义上的两个同阶矩阵乘法运算

1.9 numpy的排序

(1) sort排序
arr = np.array([7, 3, 6, 5, 8, 2])

arr.sort()                          # 方式 并不会改变原始对象 arr内部元素的顺序

np.sort(arr)                        # 会改变原始对象 arr内部元素的顺序 

(2)partition排序
格式: np.partition(nparray对象, k)     # k > 0 得到nparray对象中最小的k个数      k < 0  得到nparray对象中最大的k个数

示例: arr = np.random.permutation(10000);
        
       np.partition(arr, 4)[:4]         # 找出10000个随机数中前4个最小的数 返回List的形式

       np.partition(arr, -4)[-4:]       # 找出10000个随机数中后4个最大的数 返回List的形式