Numpy学习(基础)

来源:互联网 发布:更改mac地址的手机软件 编辑:程序博客网 时间:2024/06/15 15:00

1、numpy简介

    numpy 是Python中科学计算的核心库。它提供一个高性能多维数据对象,以及操作这个对象的工具。如果你已经熟悉了MATLAB,你会发现本教程对于numpy起步很有用。numpy数组是一个多维矩阵,所有类型都是一样的,是一个被索引的非负实数的元组。数组的维度大小是数组的rank,数组的shape是一个整型的元组,包含元组的大小和有几个这样的元组。

    NumPy的主要对象是同种元素的多维数组。这是一个所有的元素都是一种类型、通过一个正整数元组索引的元素表格(通常是元素是数字)。在NumPy中维度(dimensions)叫做轴(axes),轴的个数叫做秩(rank)。秩大小即为维度大小。
   例如,在3D空间一个点的坐标 [1, 2, 3] 是一个秩为1的数组,因为它只有一个轴。那个轴长度为3.又例如,在以下例子中,数组的秩为2(它有两个维度).第一个维度长度为2,第二个维度长度为3.
    [[ 1., 0., 0.], [ 0., 1., 2.]]


2、数组的属性

    NumPy的数组类被称作 ndarray 。通常被称作数组。注意numpy.array和标准Python库类array.array并不相同,后者只处理一维数组和提供少量功能。更多重要ndarray对象属性有:
    1)ndarray.ndim:  数组轴的个数,在python的世界中,轴的个数被称作秩;
    2)ndarray.shape:  数组的维度。这是一个指示数组在每个维度上大小的整数元组。例如一个2排3列的矩阵,它的shape属性将是(2,3),这个元组的长度显然是秩,即维度或者ndim属性;
    3)ndarray.size:  数组元素的总个数,等于shape属性中元组元素的乘积,上例的size为2X3=6;
    4)ndarray.dtype:  一个用来描述数组中元素类型的对象,可以通过创造或指定dtype使用标准Python类型。另外NumPy提供它自己的数据类型;
    5)ndarray.itemsize:  数组中每个元素的字节大小。例如,一个元素类型为float64的数组itemsiz属性值为8(=64/8),又如,一个元素类型为complex32的数组item属性为4(=32/8);
    6)ndarray.data:  包含实际数组元素的缓冲区,通常我们不需要使用这个属性,因为我们总是通过索引来使用数组中的元素;


3、创建数组

  1)你可以使用array函数从常规的Python列表和元组创造数组,所创建的数组类型由原序列中的元素类型推导而来。array和asarray都可以将结构数据转化为ndarray,但是主要区别就是当数据源是ndarray时,array仍然会copy出一个副本,占用新的内存,但asarray不会。
>>> from numpy  import *
>>> a = array( [2,3,4] )
   *  一个常见的错误包括用多个数值参数调用`array`而不是提供一个由数值组成的列表作为一个参数。
>>> a = array(1,2,3,4)    # WRONG
>>> a = array([1,2,3,4])  # RIGHT
   *  数组将序列包含序列转化成二维的数组,序列包含序列包含序列转化成三维数组等等。
>>> b = array( [ (1.5,2,3), (4,5,6) ] )
   *  数组类型可以在创建时显示指定
>>>c = array( [ [1,2], [3,4] ], dtype=complex )
>>> c
array([[ 1.+0.j,  2.+0.j],
          [ 3.+0.j,  4.+0.j]])

   * array和asarray的区别:
>>> import numpy as np
>>> a1=np.ones((3,3))
>>> a2=np.array(a1)
>>> a3=np.asarray(a1)
>>> a1[1]=2
>>> a1
array([[ 1.,  1.,  1.],
          [ 2.,  2.,  2.],
          [ 1.,  1.,  1.]])
>>> a2
array([[ 1.,  1.,  1.],
          [ 1.,  1.,  1.],
          [ 1.,  1.,  1.]])
>>> a3
array([[ 1.,  1.,  1.],
          [ 2.,  2.,  2.],
          [ 1.,  1.,  1.]])
  2)函数zeros创建一个全是0的数组,函数ones创建一个全1的数组,函数 empty 创建一个内容随机并且依赖与内存状态的数组。默认创建的数组类型(dtype)都是float64。
empty( (2,3) )
array([[  3.73603959e-262,   6.02658058e-154,   6.55490914e-260],
       [  5.30498948e-313,   3.14673309e-307,   1.00000000e+000]])
>>> zeros( (3,4) )
array([[0.,  0.,  0.,  0.],
          [0.,  0.,  0.,  0.],
          [0.,  0.,  0.,  0.]])
>>> ones( (2,3,4), dtype=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)
  3)为了创建一个数列,NumPy提供一个类似arange的函数返回数组而不是列表:
>>> arange( 10, 30, 5 )        #参数分别代表起始位置,终点位置,步长
array([10, 15, 20, 25])

>>> b = arange( 4 )
>>> b
array([0, 1, 2, 3])

  4)使用random函数

>>> from numpy import random
>>> a = random.random((2,3))          # 产生的每一个元素在0-1之间
>>> a
array([[ 0.6903007 ,  0.39168346,  0.16524769],
          [ 0.48819875,  0.77188505,  0.94792155]])

  5)使用linspace函数

>>> b = linspace(0,pi,3)    #参数分别代表起始位置,终点位置,步长

array([ 0. ,  1.57079633,  3.14159265])
    其它函数array, zeros, zeros_like, ones, ones_like, empty, empty_like, arange, linspace, rand, randn, fromfunction, fromfile
参考:NumPy示例


4、打印数组

当你打印一个数组,NumPy以类似嵌套列表的形式显示它,但是呈以下布局:
  - 最后的轴从左到右打印
  - 次后的轴从顶向下打印
  - 剩下的轴从顶向下打印,每个切片通过一个空行与下一个隔开
  1)一维数组被打印成行,二维数组成矩阵,三维数组成矩阵列表。
>>> a = arange(6)                         # 1d array
>>> print a
[0 1 2 3 4 5]
>>> b = arange(12).reshape(4,3)           # 2d array
>>> print b
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
>>> c = 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]]]
查看形状操作一节获得有关reshape的更多细节

  2)如果一个数组用来打印太大了,NumPy自动省略中间部分而只打印角落:
>>> print arange(10000)
[   0    1    2 ..., 9997 9998 9999]
>>> print 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的这种行为并强制打印整个数组,你可以设置printoptions参数来更改打印选项。

>>> set_printoptions(threshold='nan')


5、基本运算

  1)数组的算术运算是按元素的。新的数组被创建并且被结果填充。

array([20, 29, 38, 47])
>>> b**2
array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854])
>>> a<35
array([True, True, False, False], dtype=bool)
  2)不像许多矩阵语言,NumPy中的乘法运算符 * 指示按元素计算,矩阵乘法可以使用 dot 函数实现
>>> A = array( [[1,1],
                [0,1]])
>>> B = array( [[2,0],
                [3,4]]) 
>>> A*B                         # elementwise product
array([[2, 0],
       [0, 4]])
>>> dot(A,B)                    # matrix product
array([[5, 4],
       [3, 4]])
  3)有些操作符像 *= 被用来更改已存在数组而不创建一个新的数组。
>>> a = ones((2,3), dtype=int)
>>> a *= 3
>>> a
array([[3, 3, 3],
       [3, 3, 3]])
  4)当运算的是不同类型的数组时,结果数组转换为更精确的的类型
>>> a = ones(3, dtype=int32)
>>> b = linspace(0,pi,3)
>>> b.dtype.name
'float64'
>>> c = a+b
>>> c
array([ 1.        ,  2.57079633,  4.14159265])
>>> c.dtype.name
'float64'
>>> from numpy import random
>>> a = random.random((2,3))
>>> a
array([[ 0.6903007 ,  0.39168346,  0.16524769],
       [ 0.48819875,  0.77188505,  0.94792155]])
>>> a.sum()
3.4552372100521485
>>> a.min()
0.16524768654743593
>>> a.max()
0.9479215542670073
  5)指定 axis 参数你可以吧运算应用到数组指定的轴上:
>>> b = 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]])

  6)通用函数

    NumPy提供常见的数学函数如sin,cos和exp。在NumPy中,这些叫作“通用函数”(ufunc)。在NumPy里这些函数作用按数组的元素运算,产生一个数组作为输出。
>>> B = arange(3)
>>> B
array([0, 1, 2])
>>> exp(B)
array([ 1 ,  2.71828183,  7.3890561 ])
>>> sqrt(B)
array([ 0.,  1.,  1.41421356])
>>> C = array([2., -1., 4.])
>>> add(B, C)
array([ 2.,  0.,  6.])
    更多函数all, alltrue, any, apply along axis, argmax, argmin, argsort, average, bincount, ceil, clip, conj, conjugate, corrcoef, cov, cross, cumprod, cumsum, diff, dot, floor, inner, inv, lexsort, max, maximum, mean, median, min, minimum, nonzero, outer, prod, re, round, sometrue, sort, std, sum, trace, transpose, var, vdot, vectorize, where 参见NumPy示例。


6、索引,切片和迭代
  1)一维数组可以被索引、切片和迭代,就像列表和其它Python序列。
>>> a = arange(10)**3
>>> a
array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729])
>>> 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])
  2)多维数组可以每个轴有一个索引。这些索引由一个逗号分割的元组给出。
>>> from numpy import *
>>> def f(x,y):
       return 10*x+y
...
>>> b = 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[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]])
  3)当少于轴数的索引被提供时,缺失的索引被认为是整个切片:
>>> b[-1]                                  # the last row. Equivalent to b[-1,:]
array([40, 41, 42, 43])
点 (…)代表许多产生一个完整的索引元组必要的分号。如果x是秩为5的数组(即它有5个轴),那么:
    x[1,2,…] 等同于 x[1,2,:,:,:],
    x[…,3] 等同于 x[:,:,:,:,3]
    x[4,…,5,:] 等同 x[4,:,:,5,:].
  4)然而,如果一个人想对每个数组中元素进行运算,我们可以使用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
更多[], …, newaxis, ndenumerate, indices, index exp 参考NumPy示例


7、形状操作

  1)数组形状修改
>>> a = floor(10*random.random((3,4)))
>>> a
array([[ 7.,  5.,  9.,  3.],
       [ 7.,  2.,  7.,  8.],
       [ 6.,  8.,  3.,  2.]])
>>> a.shape
(3, 4)
一个数组的形状可以被多种命令修改:
>>> a.ravel()       # 展平一个矩阵返回,并不改变原来的矩阵
array([ 7.,  5.,  9.,  3.,  7.,  2.,  7.,  8.,  6.,  8.,  3.,  2.])

>>> a.reshape(6,2)  # 不更改矩阵自身,只是变换形状后返回
array([[ 7.,  4.],
       [ 3.,  3.],
       [ 4.,  8.],
       [ 4.,  3.],
       [ 0.,  2.],
       [ 0.,  6.]])
>>> a.shape = (6, 2)  # 改变数组自身形状
>>> a.transpose()   # 矩阵转置并返回,并不改变数组自身
array([[ 7.,  9.,  7.,  7.,  6.,  3.],
       [ 5.,  3.,  2.,  8.,  8.,  2.]])
>>> a.resize((6,2))    # resize函数改变数组自身
>>> a
array([[ 7.,  6.],
       [ 1.,  5.],
       [ 9.,  7.],
       [ 7.,  7.],
       [ 9.,  8.],
       [ 5.,  8.]])
更多shape, reshape, resize, ravel 参考NumPy示例

  2)组合(stack)不同的数组
>>> a = floor(10*random.random((2,2)))
>>> a
array([[ 1.,  1.],
          [ 5.,  8.]])
>>> b = floor(10*random.random((2,2)))
>>> b
array([[ 3.,  3.],
          [ 6.,  0.]])
>>> vstack((a,b))
array([[ 1.,  1.],
          [ 5.,  8.],
          [ 3.,  3.],
          [ 6.,  0.]])
>>> hstack((a,b))
array([[ 1.,  1.,  3.,  3.],
       [ 5.,  8.,  6.,  0.]])
>>> column_stack((a,b))   # With 2D arrays
array([[ 1.,  1.,  3.,  3.],
          [ 5.,  8.,  6.,  0.]])
>>> a=array([4.,2.])
>>> b=array([2.,8.])
>>> a[:,newaxis]    # This allows to have a 2D columns vector
array([[ 4.],
           [ 2.]])
>>> column_stack((a[:,newaxis],b[:,newaxis]))
array([[ 4.,  2.],
          [ 2.,  8.]])
>>> vstack((a[:,newaxis],b[:,newaxis])) # The behavior of vstack is different
array([[ 4.],
          [ 2.],
          [ 2.],
          [ 8.]])

  3)数组分割(split)成几个小数组:

    使用hsplit你能将数组沿着它的水平轴分割,或者指定返回相同形状数组的个数,或者指定在哪些列后发生分割,vsplit沿着纵向的轴分割。
>>> a = floor(10*random.random((2,12)))
>>> a
array([[ 8.,  8.,  3.,  9.,  0.,  4.,  3.,  0.,  0.,  6.,  4.,  4.],
          [ 0.,  3.,  2.,  9.,  6.,  0.,  4.,  5.,  7.,  5.,  1.,  4.]])
>>> hsplit(a,3)    # 分为三个形状相同的数组
[array([[ 8.,  8.,  3.,  9.],
           [ 0.,  3.,  2.,  9.]]), 

  array([[ 0.,  4.,  3.,  0.],
            [ 6.,  0.,  4.,  5.]]), 

  array([[ 0.,  6.,  4.,  4.],
            [ 7.,  5.,  1.,  4.]])]
>>> hsplit(a,(3,4))   # Split a after the third and the fourth column
[ array([[ 8.,  8.,  3.],
            [ 0.,  3.,  2.]]), 

  array([[ 9.],[ 9.]]), 

  array([[ 0.,  4.,  3.,  0.,  0.,  6.,  4.,  4.],
            [ 6.,  0.,  4.,  5.,  7.,  5.,  1.,  4.]])]


8、复制和视图

  1)完全不拷贝,简单的赋值不拷贝数组对象或它们的数据。
>>> a = arange(12)
>>> b = a            # no new object is created
>>> b is a           # a and b are two names for the same ndarray object
True
>>> b.shape = 3,4    # changes the shape of a
>>> a.shape
(3, 4)
Python函数调用不拷贝数组

>>> def f(x):
...     print id(x)
...
>>> id(a)                           # id is a unique identifier of an object
148293216
>>> f(a)
148293216
  2)视图(view)和浅复制,不同的数组对象分享同一个数据。视图方法创造一个新的数组对象指向同一数据。
>>> c = a.view()
>>> c is a
False
>>> c.base is a                        # c is a view of the data owned by a
True
>>> c.flags.owndata
False
>>> c.shape =(2,6)                      #c的形状改变后不影响a的形状
>>> a.shape
(3,4)
>>> c[0,4] = 1234                      # c的数据改变后会影响a的形状,因为c和a共享数据
>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])
切片数组返回它的一个视图:
>>> s = a[ : , 1:3]     # spaces added for clarity; could also be written "s = a[:,1:3]"
>>> s[:] = 10           # s[:] is a view of s. Note the difference between s=10 and s[:]=10
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])
  3)深复制,这个复制方法完全复制数组和它的数据。
>>> d = a.copy()                          # a new array object with new data is created
>>> d is a
False
>>> d.base is a                           # d doesn't share anything with a
False
>>> d[0,0] = 9999
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])


本文转载自http://reverland.org/python/2012/08/22/numpy/#fn:3

原创粉丝点击