Python Numpy 快速入门指导 (一) 基础

    本文乃Numpy Quickstart tutorial的翻译版本(并非完全翻译,翻译君为本人),英语能力足够的童鞋请阅读原文~,如果您觉得本文对您有帮助的话不要忘记点个赞哦!


一 预先准备    

  在阅读本文之前,请先确保您已经有了一些python基础,如果没有的话,请看Python Tutorial,安装在此跳过。


二 基础

    numpy的操作对象通常是齐次的多维数组,数组的每一个元素的类型应当一致(比如全为int,float等等),numpy中,多维数组的维度被称为轴(比如三维数组之于XYZ),轴上以循秩(rank)访问。

    譬如在三维空间中一个点[1,2,1],该点的坐标可以看做是一个rank为1的数组(一维数组),数组长度3

    而下列所示为rank=2(二维数组),第一个维度长度为2,第二个维度长度为3

[[ 1., 0., 0.],
 [ 0., 1., 2.]]

    Numpy的数组类称为ndarray,注意numpy.array和python标准库中的array并不一样,后者只提供一维数组及其操作。下面列出numpy的一些重要接口:

    ndarray.ndim
    数组的维度,也称数组的轴(axes)的数量。
    ndarray.shape
   数组的尺寸。返回一个整数元组,表示数组中每个维度上,数组含有多少元素。对于具有n行m列的矩阵,形状将是(n,m)。显然这个元组的长度是数组的维度ndarray.ndim
    ndarray.size
    数组元素的总数。等于数组尺寸中所有值的乘积,对于具有n行m列的矩阵,就是n*m
    ndarray.dtype
    数组中元素的类型。可以使用标准的Python中定义的类型创建,或指定其他的dtype类型。此外,NumPy提供了一些它自己的类型。譬如: numpy.int32,numpy.int16,numpy.float64
    ndarray.itemsize
    数组中每个元素的字节大小。例如,float64类型的元素大小为8(= 64/8),而complex32类型中的项目大小为4(= 32/8)。相当于ndarray.dtype.itemsize。
    ndarray.data

    该缓冲区包含数组的实际元素。通常,我们不需要使用它,因为我们将使用循秩访问访问数组中的元素。

例子:

>>> import numpy as np
>>> a = np.arange(15).reshape(3, 5)
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
>>> a.shape
(3, 5)
>>> a.ndim
2
>>> a.dtype.name
'int64'
>>> a.itemsize
8
>>> a.size
15
>>> type(a)
<type 'numpy.ndarray'>
>>> b = np.array([6, 7, 8])
>>> b
array([6, 7, 8])
>>> type(b)
<type 'numpy.ndarray'>


三 数组的创建

    下面我们就来介绍如何创建数组。

    方法一:使用python 列表或者元组创建,array的dtype将会取决于您输入元素的类型。如果您输入的数字都为int或者都为float,那么array的类型也将是这个。

>>> import numpy as np
>>> a = np.array([2,3,4])
>>> a
array([2, 3, 4])
>>> a.dtype
dtype('int64')
>>> b = np.array([1.2, 3.5, 5.1])
>>> b.dtype
dtype('float64')

    请注意:创建array时请使用[],切勿省略。

>>> a = np.array(1,2,3,4)    # WRONG
>>> a = np.array([1,2,3,4])  # RIGHT

    可以将array转换成二维数组,形似[array(),array(),array().........]。以同样的方法可以创建三维,乃至更多维度的数组

>>> b = np.array([(1.5,2,3), (4,5,6)])  # 注意到这里混用了int和float,最终全部转换成了float
>>> b
array([[ 1.5,  2. ,  3. ],
       [ 4. ,  5. ,  6. ]])

    在创建时,可以指定元素类型,比如复数类型

>>> c = np.array( [ [1,2], [3,4] ], dtype=complex )
>>> c
array([[ 1.+0.j,  2.+0.j],
       [ 3.+0.j,  4.+0.j]])

    array的初始化:创建完成后数组内部元素是未知的,尽量应当初始化它。下面介绍几个用于初始化的函数

    1.zeros,创建一个一定大小的,内部元素全部填充为0的数组

    2.ones,创建一个一定大小的,内部元素全部填充为1的数组

    3.empty,创建一个一定大小的,内部元素全部为随机数的数组,默认类型为float64

>>> np.zeros( (3,4) )
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])
>>> np.ones( (2,3,4), dtype=np.int16 )                # dtype can also be specified
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]]], dtype=int16)
>>> np.empty( (2,3) )                                 # uninitialized, output may vary
array([[  3.73603959e-262,   6.02658058e-154,   6.55490914e-260],
       [  5.30498948e-313,   3.14673309e-307,   1.00000000e+000]])

    numpy同样提供了可以返回范围的函数,

np.arange( lo, hi, delta )  # 从lo开始直到hi(不包括hi),每隔delta给一个数

>>> np.arange( 10, 30, 5 )
array([10, 15, 20, 25])
>>> np.arange( 0, 2, 0.3 )                 # it accepts float arguments
array([ 0. ,  0.3,  0.6,  0.9,  1.2,  1.5,  1.8])

    numpy也提供了相似功能的函数,这个函数可以规定将lo到hi平分为多少步走完。

>>> np.linspace( 0, 2, 9 )                 # 9 numbers from 0 to 2
array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ,  1.25,  1.5 ,  1.75,  2.  ])

    这一函数可以很简便地用于绘函数图,并规定精度,代码如下:

>>> from numpy import pi
>>> x = np.linspace( 0, 2*pi, 100 )        # useful to evaluate function at lots of points
>>> f = np.sin(x)


四 数组的打印

    如果您要打印多维数组,numpy将以如下规则进行:

    1.从左到右打印最后一个维度的元素

    2.从上到下打印倒数第二个轴的元素

    3.剩下的维度一样从上到下,只不过每一个矩阵都和下一个分开打印

    总之,一维数组打印为一行,二维数组打印为一个矩阵,三维数组打印为矩阵列表

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

    注意:如果数组过于巨大,比如上万行,上万列等等。numpy将自动打印边角的元素

>>> print(np.arange(10000))
[   0    1    2 ..., 9997 9998 9999]
>>>
>>> print(np.arange(10000).reshape(100,100))
[[   0    1    2 ...,   97   98   99]
 [ 100  101  102 ...,  197  198  199]
 [ 200  201  202 ...,  297  298  299]
 ...,
 [9700 9701 9702 ..., 9797 9798 9799]
 [9800 9801 9802 ..., 9897 9898 9899]
 [9900 9901 9902 ..., 9997 9998 9999]]

    要禁止numpy这么做,强制打印整个数组,可以输入下列内容以禁止打印角点。

>>> np.set_printoptions(threshold='nan')


五 基础操作    

     1.数组的运算。当进行数组的运算时,将会创建一个新的数组来保存运算结果。

    相同大小的数组之间可以进行:

        (1)加减操作,每个元素都被加减;

        (2)平方(写作**),sin()等函数操作,其中的每个元素都进行该运算,并填入结果中

        (3)bool运算,每个元素都进行这样的判断,在结果中填入T/F

>>> a = np.array( [20,30,40,50] )
>>> b = np.arange( 4 )
>>> b
array([0, 1, 2, 3])
>>> c = a-b
>>> c
array([20, 29, 38, 47])
>>> b**2
array([0, 1, 4, 9])
>>> 10*np.sin(a)
array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854])
>>> a<35
array([ True, True, False, False], dtype=bool)

    numpy中,*表示数组对应位置的元素相乘,矩阵乘法要使用.dot()方法

>>> A = np.array( [[1,1],
...             [0,1]] )
>>> B = np.array( [[2,0],
...             [3,4]] )
>>> A*B                         # elementwise product 元素乘法,对应位置相乘
array([[2, 0],
       [0, 4]])
>>> A.dot(B)                    # matrix product 矩阵乘法
array([[5, 4],
       [3, 4]])
>>> np.dot(A, B)                # another matrix product 另一种进行矩阵乘法的方式
array([[5, 4],
       [3, 4]])

    比如+=,-=,*=,/=的操作,将会在原来的数组上进行,并不会创建一个新的数组保存结果,因此不能将两种不同类型的元素相操作。

>>> a = np.ones((2,3), dtype=int)
>>> b = np.random.random((2,3))
>>> a *= 3
>>> a
array([[3, 3, 3],
       [3, 3, 3]])
>>> b += a
>>> b
array([[ 3.417022  ,  3.72032449,  3.00011437],
       [ 3.30233257,  3.14675589,  3.09233859]])
>>> a += b                  # b is not automatically converted to integer type
Traceback (most recent call last):
  ...
TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

    对于那些创建新的数组来保存结果的运算,当两种不同类型的元素运算时,结果自动变成两种中更精确那种类型,比如float+complex->complex

>>> a = np.ones(3, dtype=np.int32)
>>> b = np.linspace(0,pi,3)
>>> b.dtype.name
'float64'
>>> c = a+b
>>> c
array([ 1.        ,  2.57079633,  4.14159265])
>>> c.dtype.name
'float64'
>>> d = np.exp(c*1j)
>>> d
array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j,
       -0.54030231-0.84147098j])
>>> d.dtype.name
'complex128'

    numpy提供求所有元素的sum(),min(),max(),mean()等一元运算,这些都需要调用numpy,这些操作默认是对数组的一切元素进行,不论数组的形状,维度

>>> a = np.random.random((2,3))
>>> a
array([[ 0.18626021,  0.34556073,  0.39676747],
       [ 0.53881673,  0.41919451,  0.6852195 ]])
>>> a.sum()
2.5718191614547998
>>> a.min()
0.1862602113776709
>>> a.max()
0.6852195003967595
>>> a = np.array([[1, 2], [3, 4]])
>>> np.mean(a)
2.5

    如果要对特定的维度上进行上述操作,请指定维度,即sum(axis= ),注意轴的序列是列axis=0,行axis=1。

>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> b.sum(axis=0)                            # sum of each column
array([12, 15, 18, 21])
>>>
>>> b.min(axis=1)                            # min of each row
array([0, 4, 8])
>>>
>>> b.cumsum(axis=1)                         # cumulative sum along each row
array([[ 0,  1,  3,  6],
       [ 4,  9, 15, 22],
       [ 8, 17, 27, 38]])
>>> a = np.array([[1, 2], [3, 4]])
>>> np.mean(a)
2.5
>>> np.mean(a, axis=0)
array([ 2.,  3.])
>>> np.mean(a, axis=1)
array([ 1.5,  3.5])

    其他操作:numpy还支持sin cos exp sqrt等常规函数,这些函数对数组里的所有元素进行操作

>>> B = np.arange(3)
>>> B
array([0, 1, 2])
>>> np.exp(B)
array([ 1.        ,  2.71828183,  7.3890561 ])
>>> np.sqrt(B)
array([ 0.        ,  1.        ,  1.41421356])
>>> C = np.array([2., -1., 4.])
>>> np.add(B, C)
array([ 2.,  0.,  6.])

六 对数组的切片,循秩访问,和迭代

    一维数组可以被切片,循秩访问,迭代,这和python的list相似

>>> a = np.arange(10)**3
>>> a
array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729])
>>> a[2]
8
>>> a[2:5]
array([ 8, 27, 64])
>>> a[:6:2] = -1000    # equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -1000
>>> a
array([-1000,     1, -1000,    27, -1000,   125,   216,   343,   512,   729])
>>> a[ : :-1]                                 # reversed a
array([  729,   512,   343,   216,   125, -1000,    27, -1000,     1, -1000])
>>> for i in a:
...     print(i**(1/3.))
...
nan
1.0
nan
3.0
nan
5.0
6.0
7.0
8.0
9.0
    多维数组的元素具有一个多维的索引,通过元组[a,b],(a行b列,ab均为0-index)可以访问之,切片也是一样

>>> def f(x,y):
...     return 10*x+y
...
>>> b = np.fromfunction(f,(5,4),dtype=int)
>>> b
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23],
       [30, 31, 32, 33],
       [40, 41, 42, 43]])
>>> b[2,3]
23
>>> b[0:5, 1]                       # each row in the second column of b
array([ 1, 11, 21, 31, 41])
>>> b[ : ,1]                        # equivalent to the previous example
array([ 1, 11, 21, 31, 41])
>>> b[1:3, : ]                      # each column in the second and third row of b
array([[10, 11, 12, 13],
       [20, 21, 22, 23]])

    如果输入的引索值不够,则剩下的默认为所有(:)

>>> b[-1]                                  # the last row. Equivalent to b[-1,:]   
#  维度取值应当为0-n的值,但是python允许超过这个范围,并且取出mod n 的秩 ,-1表示最后一行
array([40, 41, 42, 43])

    如果觉得太多的:,:,:麻烦,可以用...(三个点)代替,其中的维度将使用尽量多的:,代替。

    比如B[1,...],则代表第一片矩阵的全部。

>>> c = np.array( [[[  0,  1,  2],               # a 3D array (two stacked 2D arrays)
...                 [ 10, 12, 13]],
...                [[100,101,102],
...                 [110,112,113]]])
>>> c.shape
(2, 2, 3)
>>> c[1,...]                                   # same as c[1,:,:] or c[1]
array([[100, 101, 102],
       [110, 112, 113]])
>>> c[...,2]                                   # same as c[:,:,2]
array([[  2,  13],
       [102, 113]])

    多维数组可以进行迭代,但是是对第一个维度进行

>>> for row in b:
...     print(row)
...
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]

    如果想要对多维数组的全部元素进行迭代,可以使用flat

>>> for element in b.flat:
...     print(element)
...
0
1
2
3
10
11
12
13
20
21
22
23
30
31
32
33
40
41
42
43

    第一部分到此结束,如果觉得这一部分对您有帮助的话,请点赞。如果我的翻译哪里不妥,还请指出。

                                                                                                                 2018/3/23


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值