Numpy常用方法

Numpy常用方法

课程地址:Python数据分析与展示

NumPy 用户指南 | NumPy 中文

NumPy 参考手册 | NumPy 中文

前言

一维数据

列表:数据类型可以不同 [3.14, ‘pi’, 3.1415, [3.14,3], ‘3.14’]
数组:数据类型必须相同 [3.1412, 3.1413, 3.1414, 3.1415]

列表(有序)和集合(无序)类型

[3.1311, 3.1314, 3.1315] {3.1311, 3.1314, 3.1315}

多维数据

3.1413 3.1413
3.1414 3.1415

列表嵌套

[[3.1413, 3.1413], [3.1414, 3.1415]]

高维数据

高维数据仅利用最基本的二元关系展示数据间的复杂结构。(键值对)

字典

1
2
3
4
dict={
"firstname":"tian",
"lastname":"song",
}

json

1
2
3
4
5
6
7
8
9
10
{
"firstname":"tian"
"lastname":"song"
"address":{
"streetAddr":"中关村",
"city":"北京市",
"zipcode":"100081"
},
"prof":["Computer System","Security"]
}

还有XML,Yaml等。

Numpy的ndarray对象

import numpy as np引入模板

数组对象可以去掉元素间运算需要的循环,使移位向量更像单个数据,同时提升运算速度(底层C实现)。

ndarray对象

上述np.array()生成一个ndarray数组,在程序中的别名为array
ndarray在控制台输出为[]形式,元素由空格分割。

1
2
3
4
5
6
7
>>> a=np.array([[0,1,2,3,4],[5,6,7,8,9]])
>>> a
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
>>> print(a)
[[0 1 2 3 4]
[5 6 7 8 9]]

轴(axis):保存数据的维度

秩(rank):轴的数量

ndarray对象的属性

以上个例子为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> a=np.array([[0,1,2,3,4],[5,6,7,8,9]])
>>> a
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
>>> print(a)
[[0 1 2 3 4]
[5 6 7 8 9]]
>>> a.ndim
2
>>> a.shape
(2, 5)
>>> a.size
10
>>> a.dtype
dtype('int32') #可以无需指明int的具体类型(32,64由python自行判定)。此为手动
>>> a.itemsize
4

ndarray支持的数据类型

因为对元素类型精确定义有助于合理使用储存空间,所以尽量避免使用非同质元素类型。当元素不同时,会出现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 x=np.array([[0,1,2,3,4],[5,6,7,8]])
__main__:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
>>> x
array([list([0, 1, 2, 3, 4]), list([5, 6, 7, 8])], dtype=object)
>>> print(x)
[list([0, 1, 2, 3, 4]) list([5, 6, 7, 8])]
>>> x.shape
(2,)
>>> x.dtype
dtype('O')
>>> x.itemsize
4
>>> x.size
2

ndarray数组的创建

  • 从python的列表、元祖等类型创建ndarray数组
1
2
3
4
5
6
7
8
9
10
11
>>> x=np.array([0,1,2,3])	#从列表类型创建
>>> print(x)
[0 1 2 3]
>>> x=np.array((4,5,6,7)) #从元祖类型创建
>>> print(x)
[4 5 6 7]
>>> x=np.array([[1,2],(9,8),[0.1,0.2]]) #从列表和元祖混合创建
>>> print(x)
[[1. 2. ]
[9. 8. ]
[0.1 0.2]]
  • 从Numpy函数创建ndarray数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
>>> np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.ones((3,6))
array([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])
>>> np.zeros((3,6))
array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]])
>>> np.zeros((3,6),dtype=np.int32)
array([[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]])
>>> np.eye(5)
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
>>> x=np.ones((2,3,4),dtype=np.int32) #从按照外到内生成
>>> print(x)
[[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]

[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]]
>>> x.shape
(2, 3, 4)

1
2
3
4
5
6
7
8
9
10
>>> x.shape
(2, 3, 4)
>>> np.zeros_like(x)
array([[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],

[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]])

1
2
3
4
>>> np.linspace(1,10,4)
array([ 1., 4., 7., 10.])
>>> np.linspace(1,10,4,endpoint=False)#endpoint表示10是否算入范围
array([1. , 3.25, 5.5 , 7.75])

为了方便运算,默认创建的数组元素是浮点数。

ndarray数组的维度变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> a=np.ones((2,3,4),dtype=np.int32)        
>>> print(a.reshape((4,6)))
[[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]]
>>> print(a.flatten())
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
>>> print(a)
[[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]

[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]]
>>> a.resize(4,6)
>>> print(a)
[[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]]

ndarray数组元素类型变化

方法 说明
.astype(new_type) 不改变数组维度,返回数组元素类型改变后的数组
1
2
3
4
5
6
7
8
9
10
>>> a=np.ones((2,3,4),dtype=np.int32) 
>>> b=a.astype(np.float)
>>> b
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],

[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])

ndarray数组向列表的转换

方法 说明
.tolist() 不改变数组维度和元素类型,返回列表(运算效率可能下降)
1
2
3
4
5
6
7
8
9
10
11
12
>>> a=np.full((2,3,4),25,dtype=np.int32)
>>> a
array([[[25, 25, 25, 25],
[25, 25, 25, 25],
[25, 25, 25, 25]],

[[25, 25, 25, 25],
[25, 25, 25, 25],
[25, 25, 25, 25]]])
>>> a.tolist()
[[[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]],
[[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]]]

ndarray数组的操作

ndarray索引

  • 一维数组的索引

    1
    2
    3
    4
    5
    6
    7
    # 一维数组的索引和列表相似
    >>> a=np.array([9,8,7,6,5])
    >>> a[2]
    7
    >>> a[1:4:2]
    array([8, 6])
    >>>
  • 多维数组的索引

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    >>> a=np.arange(24).reshape((2,3,4))
    >>> a
    array([[[ 0, 1, 2, 3],
    [ 4, 5, 6, 7],
    [ 8, 9, 10, 11]],

    [[12, 13, 14, 15],
    [16, 17, 18, 19],
    [20, 21, 22, 23]]])
    >>> a[1,2,3]
    23
    >>> a[0,1,2]
    6
    >>> a[-1,-2,-3]
    17

ndarray切片

  • 一维数组的切片

    和列表的切片类似

  • 多维数组的切片

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    >>> a=np.arange(24).reshape((2,3,4))
    >>> a
    array([[[ 0, 1, 2, 3],
    [ 4, 5, 6, 7],
    [ 8, 9, 10, 11]],

    [[12, 13, 14, 15],
    [16, 17, 18, 19],
    [20, 21, 22, 23]]])
    >>> a[:,1,-3]
    array([ 5, 17])
    >>> a[:,1:3,:]
    array([[[ 4, 5, 6, 7],
    [ 8, 9, 10, 11]],

    [[16, 17, 18, 19],
    [20, 21, 22, 23]]])
    >>> a[:,:,::2] #a[0:10:2]表示0-9步长为2的切片
    array([[[ 0, 2],
    [ 4, 6],
    [ 8, 10]],

    [[12, 14],
    [16, 18],
    [20, 22]]])

ndarray数组的运算

数组与标量的运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> a=np.arange(24).reshape((2,3,4))                         
>>> a
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
>>> a.mean()
11.5
>>> a/a.mean()
array([[[0. , 0.08695652, 0.17391304, 0.26086957],
[0.34782609, 0.43478261, 0.52173913, 0.60869565],
[0.69565217, 0.7826087 , 0.86956522, 0.95652174]],

[[1.04347826, 1.13043478, 1.2173913 , 1.30434783],
[1.39130435, 1.47826087, 1.56521739, 1.65217391],
[1.73913043, 1.82608696, 1.91304348, 2. ]]])

数组与标量之间的运算作用于数组的每一个元素

数组元素运算的函数(一元函数)

元素级运算,即对数组每个元素进行运算。注意数组本身是否改变,大多数都输返回新数组,原数组不改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
>>> a=np.arange(24).reshape((2,3,4))
>>> np.square(a)
array([[[ 0, 1, 4, 9],
[ 16, 25, 36, 49],
[ 64, 81, 100, 121]],

[[144, 169, 196, 225],
[256, 289, 324, 361],
[400, 441, 484, 529]]], dtype=int32)
>>> a
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
>>> a=np.sqrt(a)
>>> a
array([[[0. , 1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974, 2.64575131],
[2.82842712, 3. , 3.16227766, 3.31662479]],

[[3.46410162, 3.60555128, 3.74165739, 3.87298335],
[4. , 4.12310563, 4.24264069, 4.35889894],
[4.47213595, 4.58257569, 4.69041576, 4.79583152]]])
>>> np.modf(a)
(array([[[0. , 0. , 0.41421356, 0.73205081],
[0. , 0.23606798, 0.44948974, 0.64575131],
[0.82842712, 0. , 0.16227766, 0.31662479]],

[[0.46410162, 0.60555128, 0.74165739, 0.87298335],
[0. , 0.12310563, 0.24264069, 0.35889894],
[0.47213595, 0.58257569, 0.69041576, 0.79583152]]]),
array([[[0., 1., 1., 1.],
[2., 2., 2., 2.],
[2., 3., 3., 3.]],

[[3., 3., 3., 3.],
[4., 4., 4., 4.],
[4., 4., 4., 4.]]]))

数组之间运算的函数(二元函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
>>> a=np.arange(24).reshape((2,3,4))
>>> b=np.sqrt(a)
>>> a
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
>>> b
array([[[0. , 1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974, 2.64575131],
[2.82842712, 3. , 3.16227766, 3.31662479]],

[[3.46410162, 3.60555128, 3.74165739, 3.87298335],
[4. , 4.12310563, 4.24264069, 4.35889894],
[4.47213595, 4.58257569, 4.69041576, 4.79583152]]])
>>> np.maximum(a,b) # 整数和浮点数比较返回的结果为浮点数
array([[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]],

[[12., 13., 14., 15.],
[16., 17., 18., 19.],
[20., 21., 22., 23.]]])
>>> a > b
array([[[False, False, True, True],
[ True, True, True, True],
[ True, True, True, True]],

[[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True]]])

Numpy的文件存储

CSV文件介绍

CSV(Comma-Separated Value,逗号分隔值)。CSV是一种常见的文件格式,用来存储批量数据。

  • 一个表格
城市 环比 同比 定基
北京 101.5 120.7 121.4
上海 101.2 127.3 127.8
广州 101.3 119.4 120.8
深圳 102.0 140.9 145.5
沈阳 100.1 101.4 101.6
  • 与之对应的CSV文件
1
2
3
4
5
6
城市,环比,同比,定基
北京,101.5,120.7,121.4
上海,101.2,127.3,127.8
广州,101.3,119.4,120.0
深圳,102.0,140.9,145.5
沈阳,100.1,101.4,101.6

CSV文件读写函数

np.savetxt() np.loadtxt()只能有效存取一维和二维数组。

  • 文件写入函数np.savetxt()

    1
    np.savetxt(frame,array,fmt='%.18e',delimiter=None)

    frame:文件,字符串或产生器,可以是.gz或.bz2的压缩文件。

    array:存入文件的数组

    fmt:写入文件的格式,例如%d,%.2f,%.18e

    delimiter:分隔字符串,默认是任何空格

    因为CSV文件格式以,分隔,所以delimiter=','

    1
    2
    3
    import numpy as np
    a=np.arange(100).reshape(5,20)
    np.savetxt("a.csv",a,fmt='%d',delimiter=',')

  • 文件读取函数np.loadtxt()

    1
    np.loadtxt(frame,dtype=np.float,delimiter=None,unpack=False)

    frame:文件,字符串或产生器,可以是.gz或.bz2的压缩文件。

    dtype:数据类型,可选

    delimiter:分隔字符串,默认是任何空格

    unpack:如果为Ture,解包,读入属性将分别写入不同的变量

    (python的read()函数读取文件的数据都是字符格式,需要进一步int()转换)

    1
    2
    3
    4
    a=np.arange(100).reshape(5,20)
    np.savetxt("a.csv",a,fmt='%.1f',delimiter=',')
    b=np.loadtxt("a.csv",delimiter=',')
    print("读取到的a的值为:\n",b)

多维文件读取函数

  • 文件写入函数ndarray.tofile()

    1
    ndarray.tofile(frame,sep='',format='%s')

    frame;文件,字符串

    sep:数据风格字符串,如果是空串,写入文件为二进制

    format:写入数据的格式

    1
    2
    3
    import numpy as np
    a=np.arange(100).reshape(2,5,10)
    a.tofile("b.dat",sep=',',format='%d')

    b.dat不包含任何维度信息。如果sep=','未设置,b.dat将是一个二进制文件。

  • 文件读取函数np.fromfile()

    1
    np.fromfile(frame,dtype=float,count=-1,sep='')

    frame:文件,字符串

    dtype:读取的数据类型

    count:读入元素个数,-1表示读入整个文件

    sep:数据分割字符串,如果是空串,写入文件为二进制

    1
    2
    3
    4
    a=np.arange(100).reshape(2,5,10)
    a.tofile("b.dat",sep=',',format='%d')
    c = np.fromfile("b.dat",dtype=np.int,sep=',').reshape(5,10,2)
    print(c)

多维文件的元数据处理

利用上述ndarray.tofile()np.fromfile()函数时,我们看到文件存储的数据只有纯内容,缺乏维度信息。对于这类元数据,一般的处理方法是另建一个配置文件写明元数据信息。同时,Numpy提供了一个便捷的文件存储办法。

  • np.save(或者np.savez

    1
    2
    np.save(fname,array)
    np.savez(frame,array)

    frame:文件名,以.npy为扩展名,压缩扩展名为.npz

    array:数组变量

  • np.load

    1
    np.load(fname)

    frame:文件名,以.npy为扩展名,压缩扩展名为.npz

1
2
3
4
5
import numpy as np
a=np.arange(100).reshape(2,5,10)
np.save("a.npy",a)
b=np.load("a.npy")
print("从a.npy中读取信息:\n",b)

文件写入

文件读取

Numpy的随机函数子库

从零随机生成数据的函数

  • np.rand(d0,d1,...,dn)从[0-1]随机生成符合维度参数的数组,满足(0-1)均匀分布

    1
    2
    3
    4
    5
    6
    7
    8
    >>> np.random.rand(2,3,4)
    array([[[0.20259939, 0.00962878, 0.56450046, 0.71235863],
    [0.01549391, 0.49664883, 0.16570365, 0.11222922],
    [0.93839936, 0.65121818, 0.35750042, 0.84551314]],

    [[0.56703213, 0.45897042, 0.21583654, 0.6436646 ],
    [0.73612895, 0.80503486, 0.93915543, 0.33008223],
    [0.86046784, 0.36052457, 0.33578919, 0.16510733]]])
  • np.randn(d0,d1,...,dn)随机生成符合维度参数的数组,满足标准正态分布

    1
    2
    3
    4
    5
    6
    7
    8
    >>> np.random.randn(2,3,4)
    array([[[ 1.55199709, 1.41594185, -0.1622146 , 0.48272732],
    [-0.70775139, 2.38247535, 1.52048942, -0.95379195],
    [ 0.72480865, 0.19713822, 0.5858833 , -0.3099266 ]],

    [[ 1.06940348, 0.47979532, 0.98184603, 0.64469512],
    [-3.09162702, -0.78907275, 0.32596385, 1.5061127 ],
    [ 0.28365334, 0.08427444, 0.67566961, 2.54296885]]])
  • np.randint(low,high,shape)从[100,200)随机生成整数

    1
    2
    3
    4
    >>> np.random.randint(100,200,(3,4))
    array([[156, 100, 152, 180],
    [104, 168, 165, 167],
    [192, 137, 194, 163]])
  • np.seed(num)按照种子生成随机数,通过设定seed,可以产生同一个数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> np.random.seed(10)                    
    >>> np.random.randint(100,200,(3,4))
    array([[109, 115, 164, 128],
    [189, 193, 129, 108],
    [173, 100, 140, 136]])
    >>> np.random.seed(10) #再次设置seed为10,产生一样的数组
    >>> np.random.randint(100,200,(3,4))
    array([[109, 115, 164, 128],
    [189, 193, 129, 108],
    [173, 100, 140, 136]])

从已有数组抽取或重排的函数

  • np.random.shuffle(array)将数组a的第一层随机排列,内层跟随第一层进行改变

    1
    2
    3
    4
    5
    6
    7
    8
    >>> a=np.random.randint(100,200,(2,3))     
    >>> a
    array([[116, 111, 154],
    [188, 162, 133]])
    >>> np.random.shuffle(a)
    >>> a
    array([[188, 162, 133],
    [116, 111, 154]])
  • np.random.permutation(array)相当于shuffle()带返回值的版本,不改变原数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> a=np.random.randint(100,200,(2,3))
    >>> a
    array([[178, 149, 151],
    [154, 177, 169]])
    >>> np.randim.permutation(a)
    array([[154, 177, 169],
    [178, 149, 151]])
    >>> a
    array([[178, 149, 151],
    [154, 177, 169]])
  • np.random.choice(array,shape,replace,p)以概率p抽取元素,返回新数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    >>> a=np.random.randint(100,200,8)
    >>> a
    array([112, 165, 131, 157, 136, 127, 118, 193])
    >>> np.random.choice(a,(3,2))
    array([[112, 193],
    [127, 112],
    [193, 127]])
    >>> np.random.choice(a,(3,2),replace=False)
    array([[193, 127],
    [118, 157],
    [165, 112]])
    >>> np.random.choice(a,(3,2),p=a/np.sum(a)) # 元素越大,抽取率越高
    array([[193, 157],
    [112, 193],
    [131, 136]])

按照数学分布生成数据的函数

  • np.random.uniform.uniform(low,high,size)产生具有均匀分布的数组

    1
    2
    3
    4
    >>> np.random.uniform(0,10,(3,4)) #从(0,10)等概率抽取
    array([[4.90554679, 0.29179556, 5.9486095 , 2.05845476],
    [2.02802974, 8.44125875, 0.61566377, 4.99230689],
    [2.48466979, 3.27144028, 0.02916088, 2.95442135]])
  • np.random.normal(loc,scale,size)产生具有正态分布的数组

    1
    2
    3
    4
    >>> np.random.normal(10,5,(3,4)) #均值是10,方差是5
    array([[12.87109037, 14.66311162, 10.45457509, 2.63002415],
    [10.55279029, 11.26839975, 11.32440894, 13.62386089],
    [ 7.32322561, 9.04697536, 7.64661696, 8.1869246 ]])
  • np.random.poisson(lam,size)产生具有泊松分布的数组

Numpy的统计函数

1
2
3
4
5
6
7
8
9
>>> a=np.arange(18).reshape(2,3,3)
>>> a
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],

[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]])
  • np.sum(array,axis=None)

    1
    2
    >>> np.sum(a)
    153
  • np.mean(array,axis=None)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> np.mean(a,axis=0) # 最外层
    array([[ 4.5, 5.5, 6.5], # 4.5=(0+9)/2
    [ 7.5, 8.5, 9.5], # 8.5=(4+13)/2
    [10.5, 11.5, 12.5]]) # 12.5=(8+17)/2
    >>> np.mean(a,axis=1) # 第二层
    array([[ 3., 4., 5.], # 3.=(0+6)/2
    [12., 13., 14.]]) # 13.=(10+16)/2
    >>> np.mean(a,axis=2) # 第三层
    array([[ 1., 4., 7.], # 1.=(0+2)/2
    [10., 13., 16.]]) # 13.=(12+14)/2
  • np.average(array,axis=None,weights=None)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> np.average(a,axis=0,weights=[1,2]) # 最外层
    array([[ 6., 7., 8.], # 6.=(0*1+9*2)/(1+2)
    [ 9., 10., 11.], # 10.=(4*1+13*2)/(1+2)
    [12., 13., 14.]]) # 14.=(8*1+17*2)/(1+2)
    >>> np.average(a,axis=1,weights=[1,2,3]) # 第二层
    array([[ 4., 5., 6.], # 4.=(0*1+3*2+6*3)/(1+2+3)
    [13., 14., 15.]]) # 14.=(10*1+13*2+16*3)/(1+2+3)
    >>> np.average(a,axis=2,weights=[1,2,3]) # 第三层
    array([[ 1.33333333, 4.33333333, 7.33333333], # 1.33333=(0*1+2*2+2*3)/(1+2+3)
    [10.33333333, 13.33333333, 16.33333333]]) # 13.33333=(12*1+13*2+14*3)/(1+2+3)
  • np.std(array,axis=None)

    1
    2
    >>> np.std(a) # a的标准差
    5.188127472091127

    np.var(a,axis=None)

    1
    2
    >>> np.var(a) # a的方差
    26.916666666666668

1
2
3
4
5
6
7
8
9
>>> a=np.arange(18).reshape(2,3,3)
>>> a
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],

[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]])
  • np.max(array)

    1
    2
    >>> np.max(a) # 取得数组的最大值
    17
  • np.argmax(array)

    1
    2
    >>> np.argmax(a) # 将数组压缩为一维数组,找到最大值,返回其在一维数组中对应的下标
    17
  • np.unravel_index(index,shape)

    1
    2
    >>> np.unravel_index(np.argmax(a),a.shape) 
    (1, 2, 2) # 将一维下标index转换为,对应a.shape形状下的多维下标
  • np.ptp(array)

    1
    2
    >>> np.ptp(a) # 取得数组a中最大值和最小值的差
    17
  • np.median(array)

    1
    2
    >>> np.median(a) # 将数组a压缩为一维数组,重排列,返回一维数组的中位数
    8.5

Numpy的梯度函数

函数 说明
np.gradient(array) 计算数组array中元素的梯度,当f为多维时,返回每个维度梯度

梯度:连续值之间的变化率,即斜率

例如:XY坐标轴连续三个X坐标对应的Y轴值:a,b,c,其中,b的梯度为:(c-a)/2

多用于图像和音频的处理

一维梯度

1
2
3
4
5
6
>>> a=np.random.randint(0,20,(5))
>>> a
array([14, 16, 9, 0, 16])
>>> np.gradient(a)
array([ 2. , -2.5, -8. , 3.5, 16. ])
# 2.=(16-14)/1 , -2.5=(9-14)/2 , 16.=(16-0)/1

多维梯度

1
2
3
4
5
6
7
8
9
10
11
12
>>> a=np.random.randint(0,50,(3,5))
>>> a
array([[ 6, 46, 1, 18, 23],
[13, 26, 27, 17, 0],
[24, 28, 11, 46, 49]])
>>> np.gradient(a)
[array([[ 7., -20., 26., -1., -23.], # 最外层维度的梯度
[ 9., -9., 5., 14., 13.], # -9=(28-46)/2
[ 11., 2., -16., 29., 49.]]), # 49.=(49-0)/1
array([[ 40. , -2.5, -14. , 11. , 5. ], # 第二层维度的梯度
[ 13. , 7. , -4.5, -13.5, -17. ], # 7.=(27-13)/2
[ 4. , -6.5, 9. , 19. , 3. ]])] # 3.=(49-46)/1

图像变换

图像是一个由像素组成的二维矩阵,每个元素是一个RGB值。

用numpy打开后,图像是一个三维数组,维度分别是高度、宽度和像素RGB值。

RGB(255,255,255)可以用来改改改。

PIL库

安装pip install pillow

引入from PIL import Image Image代表图像的对象。

1
2
from PIL import Image
import numpy as np

原图

1
2
3
4
5
6
im=np.array(Image.open("1.jpg"))
print("图像的矩阵大小是",im.shape,"\n图像的元素类型是",im.dtype)
# 图像的矩阵大小是 (469, 565, 3) 图像的元素类型是 uint8
inv_im=[255,255,255]-im # 色彩反转
out_im=Image.fromarray(inv_im.astype('uint8'))
out_im.save("1_inv.jpg")

色彩反转

1
2
3
im=np.array(Image.open("1.jpg").convert('L')) # 取灰度值
out_im = Image.fromarray(im.astype('uint8'))
out_im.save("1_gray.jpg")

灰度值

1
2
3
4
im = np.array(Image.open("1.jpg").convert('L')) 
change1_im=(100/255)*im+150 # 进行一个乱七八糟的区间变化
out_im = Image.fromarray(change1_im.astype('uint8'))
out_im.save("1_change1.jpg")

区间变化1

1
2
3
change2_im = 255*(im*255)**2  # 进行第二个乱七八糟的区间变化
out_im = Image.fromarray(change2_im.astype('uint8'))
out_im.save("1_change2.jpg")

区间变化2

手绘图像

手绘风格图片特点:

  • 黑白灰
  • 边界线条较重
  • 相同或相近色彩趋于白色
  • 略有光源效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from PIL import Image
import numpy as np

a = np.asarray(Image.open('1.jpg').convert('L')).astype('float')

depth = 10. # (0-100)
grad = np.gradient(a) # 取图像灰度的梯度值
grad_x, grad_y = grad # 分别取横纵图像梯度值
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
A = np.sqrt(grad_x**2 + grad_y**2 + 1.)
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A

vec_el = np.pi/2.2 # 光源的俯视角度,弧度值
vec_az = np.pi/4. # 光源的方位角度,弧度值
dx = np.cos(vec_el)*np.cos(vec_az) # 光源对x 轴的影响
dy = np.cos(vec_el)*np.sin(vec_az) # 光源对y 轴的影响
dz = np.sin(vec_el) # 光源对z 轴的影响

b = 255*(dx*uni_x + dy*uni_y + dz*uni_z) # 光源归一化
b = b.clip(0, 255)

im = Image.fromarray(b.astype('uint8')) # 重构图像
im.save('1_draw.jpg')

手绘