人工智能之Numpy与Pandas培训文档
创建时间:2018-09-09  访问量:3186  4  0

人工智能之Numpy与Pandas培训文档

NDArray介绍

一个ndarray其实就是一个多维数组,多维数组中的元素类型相同,同一维度长度相等。数组中的元素是通过shape属性来确定多维数组的维度,每个维度是由N个正整数组成的元组来表示多维数组的形状,即shape属性。数组中元素的类型是由dtype属性指定的。与Python中的其他容器对象一样,可以通过索引或切片数组(例如,使用N个整数)以及通过ndarray的方法和属性来访问和修改ndarray的内容。

可以通过不同的ndarray来共享同一组数据,修改其中一个ndarray中内容也会影响与其共享底层数据的内容。因此其中一个ndarray可以称为其它ndarray的视图,也可以是Python字符串或实现缓冲区或数组接口对象所拥有的内存视图。

 

创建NDArray

例:创建一个2x3的二维整型数组

>>> x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
>>> type(x)
<type 'numpy.ndarray'>
>>> x.shape
(2, 3)
>>> x.dtype
dtype('int32')
>>> x.size
6

Numpy通过array方法创建一个多维数组,并将对象赋给x变量,array方法是在numpy库中的,我们之前是通过import numpy as np方法导入的numpy,因此要通过np.xxx的方法调用numpy库中的函数。array方法第一个参数是python的列表(即将python列表转成numpy数组),第二个参数是元素数据类型(用numpy库中定义的类型np.int32,32位整型)。也可以写成dtype=np.int32。

通过内建函数type()来查看numpy ndarray中元素的类型,type(x),结果是numpy.ndarray,即numpy的ndarray类型,通过对象的shape属性可以查看ndarray形态,它是一个元组(2,3),表示2行3列。如果创建的是一维ndarray,np.array([1,2,3],dtype=np.int32),那么它的shape属性输出是(3,),因为shape是元组,所以3后面是有一个逗号的。

通过ndarray对象的dtype属性可以查看元素的类型,x.dtype输入dtype('int32')。通过size属性可以查看数组元素的个数。

 

NDArray的索引与切片

可以像Python列表那个索引NDArray

>>> # 获取第2行第3列的元素值
>>> x[1, 2]

切片可以创建NDarray的视图:

>>> y = x[:,1] # 第一维:号表示所示元素,第二维是1,表示第2列,因y是x中的第2列组成的ndarray
>>> y
array([2, 5]) # x中的第二列元素是[2,5]
>>> y[0] = 9 # 这个操作也会改x中对应的第1行第2列的值
>>> y
array([9, 5])
>>> x # 查看x的第1行第2列的值确实被改
array([[1, 9, 3],
       [4, 5, 6]])

例:创建一个三维浮点型数组

>>> x = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]],dtype=np.float32)
>>> x # 这是一个形状是(2,2,3)的数组
array([[[ 1.,  2.,  3.],
        [ 4.,  5.,  6.]],

       [[ 7.,  8.,  9.],
        [10., 11., 12.]]], dtype=float32)
>>> x[1,0,1] # 访问1,0,1处的元素值
8.0

 

ndarray 常见的创建方式
  • 通过array函数来创建,接收一个普通的Python序列。
  • zeros 函数,创建指定长度和形状的全0数组。
  • ones 函数,创建指定长度和形状的全1数组。
  • empty 函数,创建一个没有任何具体值的数组(随机值)。
>>> np.zeros([2,3]) #全0数组
array([[0., 0., 0.],
       [0., 0., 0.]])
>>> np.ones([2,3,4]) #全1数组
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.]]])
>>> np.empty([5,3]) # 随机数组
array([[3.89012112e-316, 3.04043334e-316, 9.49241552e+213],
       [5.26616474e-090, 7.48269334e+247, 1.76827909e+233],
       [1.78743824e+161, 2.34247115e+166, 6.20089493e-268],
       [3.06836125e+257, 8.73990015e+245, 1.67264719e-298],
       [9.55906205e-299, 1.66994701e+243, 9.75029630e+199]])

>>> x = np.empty([5,3],dtype=np.float32)
>>> x
array([[4.4606165e-36, 0.0000000e+00, 4.4606509e-36],
       [0.0000000e+00, 4.4606854e-36, 0.0000000e+00],
       [4.4607198e-36, 0.0000000e+00, 4.4607543e-36],
       [0.0000000e+00, 4.4607887e-36, 0.0000000e+00],
       [4.4608231e-36, 0.0000000e+00, 1.5916957e-38]], dtype=float32)
>>> np.ones(5) # 只有一维可以不用列表,也可以用
array([1., 1., 1., 1., 1.])
>>> np.ones([5])
array([1., 1., 1., 1., 1.])
>>> np.ones((5,4)) # 维度也可以是元组的形式指定
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])
>>>

以上创建函数中,没有指定类型,黙认为np.float64,可以通过dtype查看。创建数组时形状以python序列的形式提供。

 

通过np.arange函数创建ndarray

我们先来help一下:help(np.arange)

>>> help(np.arange)
Help on built-in function arange in module numpy.core.multiarray:

arange(...)
    arange([start,] stop[, step,], dtype=None)

    Return evenly spaced values within a given interval.

    Values are generated within the half-open interval ``[start, stop)``
    (in other words, the interval including `start` but excluding `stop`).
    For integer arguments the function is equivalent to the Python built-in
    `range <http://docs.python.org/lib/built-in-funcs.html>`_ function,
    but returns an ndarray rather than a list.

    When using a non-integer step, such as 0.1, the results will often not
    be consistent.  It is better to use ``linspace`` for these cases.

    Parameters
    ----------
    start : number, optional
        Start of interval.  The interval includes this value.  The default
        start value is 0.
    stop : number
        End of interval.  The interval does not include this value, except
        in some cases where `step` is not an integer and floating point
        round-off affects the length of `out`.
    step : number, optional
        Spacing between values.  For any output `out`, this is the distance
        between two adjacent values, ``out[i+1] - out[i]``.  The default
        step size is 1.  If `step` is specified as a position argument,
        `start` must also be given.
    dtype : dtype
        The type of the output array.  If `dtype` is not given, infer the data
        type from the other input arguments.

    Returns
    -------
    arange : ndarray

np.arange方法接收4个可选参数,第1个参数是开始值,第2个参数是停止值(不包含,not include),第3个参数是步长,第4个参数是要创建数组元素的类型。

例:使用np.arange创建一个一维的ndarray,从1到20,步长为2(如果不写步长黙认为1)。

>>> x = np.arange(1,20,2)
>>> x
array([ 1,  3,  5,  7,  9, 11, 13, 15, 17, 19])
>>> x.dtype # 如果不指定元素类型,黙认为numpy的int32类型
dtype('int32')
>>> x = np.arange(1,20,2,dtype=np.float32) # 创建时可以指定类型为float32
>>> x
array([ 1.,  3.,  5.,  7.,  9., 11., 13., 15., 17., 19.], dtype=float32)
>>> x.dtype
dtype('float32')

numpy的arange方法与python的range方法的区别,举例表示:

>>> range(1,10,3) # python range                      
[1, 4, 7]                               
>>> np.arange(1,10,3,dtype=np.float64) # numpy arange
array([1., 4., 7.])                     

python的range不可指定元素类型,元素只能是整型,返回的的对象为Python列表;numpy的arange的元素可以是浮点型,返回的是numpy的ndarray数据结构。

 

使用np.linspace函数创建等差数列

看官要学会自己查看帮助,这里我就不help了,我把help的结果说一下,函数的调用参数如下:

linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

start:起始值;stop:终止值(黙认包括,如果endpoint=True,否则不包括);num为生成元素的个数;endpoint:控制是否包含终止值,True则包含;retstep:黙认只返回样本即ndarray数组,如果为True就返回包含步长的元组,咦~,虽然步长没有指定,但是可以返回;dtype:指定元素类型,不指定或为None就是float64。

举例:

>>> np.linspace(2.0, 3.0, num=5) # 生成5个等差数列
array([ 2.  ,  2.25,  2.5 ,  2.75,  3.  ])
>>> np.linspace(2.0, 3.0, num=5, endpoint=False) # 不包括终止值3.
array([ 2. ,  2.2,  2.4,  2.6,  2.8])
>>> np.linspace(2.0, 3.0, num=5, retstep=True) # 返回步长0.25,整体是以元组的形式返回的
(array([ 2.  ,  2.25,  2.5 ,  2.75,  3.  ]), 0.25)

 

使用np.logspace函数创建等比数列

先来看个例子:

>>> np.logspace(2.0, 3.0, num=4)
array([  100.        ,   215.443469  ,   464.15888336,  1000.        ])
>>> np.logspace(2.0, 3.0, num=4, endpoint=False)
array([ 100.        ,  177.827941  ,  316.22776602,  562.34132519])
>>> np.logspace(2.0, 3.0, num=4, base=2.0)
array([ 4.        ,  5.0396842 ,  6.34960421,  8.        ])

好像看不出来,再来看看:

array([1.e+01, 1.e+02, 1.e+03, 1.e+04, 1.e+05])
>>> x1 = np.logspace(1,5,num=5)
>>> x1
array([1.e+01, 1.e+02, 1.e+03, 1.e+04, 1.e+05])
>>> x2 = np.logspace(1,5,num=5,base=2)
>>> x2
array([ 2.,  4.,  8., 16., 32.])

这下看清楚了,x1是1乘10的1次方到1乘10的5次方,5个元素;x2是1乘2的1次方到1乘2的5次方,5个元素。base这个参数就是指定底数的。起始值和终止值与元素个数组成一个等差数列,再以base为底数,以这个等差数列中的元素为指数生成的等比数列。

 

reshape函数可以改变数组的形状,我们可以称之为重塑ndarray

我们之前说的那些方法都只是创建一个一维的ndarray,ndarray怎么也来个二维以上吧,那怎么办呢?reshape函数可以将一维数组重塑为多维数组。

举例:将一个使用arange生成的12个元素的一维ndarray,重新变成2行6列的ndarray

>>> np.arange(0,12).reshape(2,6) # 将一个具有12个元素的一维数组转成2行6列的二维数组
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
>>>

如果参数指定的不对,会报错:

>>> np.arange(0,12).reshape(2,7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot reshape array of size 12 into shape (2,7)
>>>

总共有12个元素,人都知道不可能变成2行7列的吧,元素数量明显不够。将reshape其中一维的参数设为-1。

>>> np.arange(0,12).reshape(3,-1)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

reshape第2个参数如果设置成-1,则会根据第一个参数自动计算;也就是根据第1层的维度自动计算第2层的维度。记住不管用reshape重塑几维数组,-1 只能用于其中的一维,还要在给定其它维度的情况下存在这种转换的可能性,如果指定其它维度时,最后一个维度怎么计算都得不到结果,这样的转换自然会报错。

reshape形状参数也可以放在元组中:

>>> np.arange(0,12).reshape((3,-1)) # 将元组传入reshape
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>

 

通过np.ndarray函数创建ndarray

读者可以通过help(np.ndarray)内建函数看一下ndarray方法具体用法。

调用方式:np.ndarray(shape, dtype=float, buffer=None, offset=0, strides=None, order=None)

  • shape:是数组的形状,整型元组;这个参数是必须的。
  • dtype:指定元素类型,如float,可选的,黙认是float64。
  • buffer:用于填充数组的缓冲区,一般使用一维的Ndarray数组,如np.array([1,2,3,4,5,6]),可选的。
  • offset:缓冲中字节偏移量,可选的。
  • strides:跨越内存中的数据,可选的。
  • order:两个选择('C'或'F'),C是C语言风格排序,按行依次排序。'F'是Fortran风格排序,按列依次排序。可选的,黙认按行排序。

举例:使用np.ndarray创建数组:

只给定参数shape,生成2行3列的随机数,黙认类型为np.float64

>>> x = np.ndarray((2,3))
>>> x
array([[1.28625407e+248, 9.99841362e+160, 9.55431966e+213],
       [9.46686048e+218, 8.46983797e+222, 3.93107135e-317]])
>>> x.dtype
dtype('float64')

通过属性ndim查看维度:

>>> x.ndim # 查看维度,是2维
2

根据buffer来创建ndarray:

>>> x = np.ndarray((2,3),buffer=np.array([1,2,3,4,5,6]),dtype=int)
>>> x # 根据buffer创建一个2行3列ndarray
array([[1, 2, 3],
       [4, 5, 6]])
>>> x.shape # ndarray 形状
(2L, 3L)
>>> x.ndim # ndarray 维度
2
>>> x.dtype # ndarray 数据类型
dtype('int32')

offset指定buffer的字节偏移量:

>>> x = np.ndarray((2,3),buffer=np.array([1,2,3,4,5,6,7]),offset=np.int_().itemsize,dtype=int)
>>> x
array([[2, 3, 4],
       [5, 6, 7]])

上面的np.ndarray指定的offset是将np.array([1,2,3,4,5,6,7]),向右偏移一位,本来是1,偏移一位是从2开始,也就是从buffer中第2个元素开始到最后的元素[2,3,4,5,6,7]来填充创建的ndarray。

这里面有一个np.int_().itemsize:这是个什么东西呢?它是指一个整型变量在内存在所占字节数,它的数值是4,也就是offset是4,不是说偏移一位吗,怎么是4位呢?其实这个是字节数,而dtype又是int,所以偏移4个字节就是偏移1个整型数据。那么np.int_()与np.int()有什么区别呢?它们返回的数据都是整型,而np.int()返回的是python中的int型,而np.int_()返回的是numpy中的int型对象,因此才有itemsize这个属性。offset必须是np.int_().itemsize的整数倍,且不能超出buffer的缓冲区范围。不信你设个1试试,会看到很大很奇怪的数据,想想怎么得到的。评论区见!!!

>>> x = np.int_(2)
>>> x
2
>>> type(x)
<type 'numpy.int32'>
>>>

看到了吗,x其实就是个整型数值2,但类型是numpy.int32。可以使用dir(np.int_)看看其中属性。
接下来看看order参数,选C和F分别是什么结果:

>>> x = np.ndarray((2,3),buffer=np.array([1,2,3,4,5,6]),offset=0*np.int_().itemsize,dtype=int,order='C')
>>> x # C是按行排序
array([[1, 2, 3],
       [4, 5, 6]])
>>> x = np.ndarray((2,3),buffer=np.array([1,2,3,4,5,6]),offset=0*np.int_().itemsize,dtype=int,order='F')
>>> x # F 是按列排序
array([[1, 3, 5],
       [2, 4, 6]])

ndarray的srides参数有点复杂,不好理解,也不常用,简单说一下。首先,strides是通过整型元组指定的,而且它的维度必须与shape相同,也就是说shape元组元素个数与strides元组无素个数须相等。它表示内存中数据的跨度。

引用一下:

strides
 |      Tuple of bytes to step in each dimension when traversing an array.
 |
 |      The byte offset of element ``(i[0], i[1], ..., i[n])`` in an array `a`
 |      is::
 |
 |          offset = sum(np.array(i) * a.strides)
 |
 |      A more detailed explanation of strides can be found in the
 |      "ndarray.rst" file in the NumPy reference guide.
 |
 |      Notes
 |      -----
 |      Imagine an array of 32-bit integers (each 4 bytes)::
 |
 |        x = np.array([[0, 1, 2, 3, 4],
 |                      [5, 6, 7, 8, 9]], dtype=np.int32)
 |
 |      This array is stored in memory as 40 bytes, one after the other
 |      (known as a contiguous block of memory).  The strides of an array tell
 |      us how many bytes we have to skip in memory to move to the next position
 |      along a certain axis.  For example, we have to skip 4 bytes (1 value) to
 |      move to the next column, but 20 bytes (5 values) to get to the same
 |      position in the next row.  As such, the strides for the array `x` will be
 |      ``(20, 4)``.
 |
 |      See Also
 |      --------
 |      numpy.lib.stride_tricks.as_strided
 |
 |      Examples
 |      --------
 |      >>> y = np.reshape(np.arange(2*3*4), (2,3,4))
 |      >>> y
 |      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]]])
 |      >>> y.strides
 |      (48, 16, 4)
 |      >>> y[1,1,1]
 |      17
 |      >>> offset=sum(y.strides * np.array((1,1,1)))
 |      >>> offset/y.itemsize
 |      17
 |
 |      >>> x = np.reshape(np.arange(5*6*7*8), (5,6,7,8)).transpose(2,3,1,0)
 |      >>> x.strides
 |      (32, 4, 224, 1344)
 |      >>> i = np.array([3,5,2,2])
 |      >>> offset = sum(i * x.strides)
 |      >>> x[3,5,2,2]
 |      813
 |      >>> offset / x.itemsize
 |      813

>>> x = np.array([[0,1,2,3,4],[5,6,7,8,9]],dtype=np.int32)
>>> x                                                     
array([[0, 1, 2, 3, 4],                                   
       [5, 6, 7, 8, 9]])                                  
>>> x.strides                                             
(20L, 4L)                                                 

上面的数据在连续内存中占用40个字节(每个整型4个字节)。属性strides告诉我们从第1行移动到第2行需要几个字节,从第1列移动到第2列需要几个字节。上述strides为(20L,4L)(末尾L表示长整型),表明了从第1行行首移到第2行行首需要20个字节,从第1列移动到第2列需要4个字节。

下面我们通过np.ndarray方法的strides参数创建数组。

>>> x = np.ndarray((2,3),dtype=np.int32,buffer=np.array([1,2,3,4,5,6,7,8,9,10,11,12]),strides=(8,4))
>>> x # 8表示相同列的两行元素相差8个字节,也就是2个整型数据,相同行两个列之间相差4个字节,即1个整型数据
array([[1, 2, 3],
       [3, 4, 5]])
>>> x = np.ndarray((2,3),dtype=np.int32,buffer=np.array([1,2,3,4,5,6,7,8,9,10,11,12]),strides=(12,4))
>>> x # 12表示相同列的两行元素相差12个字节,也就是3个整型数据,相同行两个列之间相差4个字节,即1个整型数据
array([[1, 2, 3],
       [4, 5, 6]])

这个strides是遍历buffer缓冲区时进行计算的。在strides=(8,4)时,从1开始,1是第1行开始,那么第2行应该是从1偏移8个字节(2个数据即元素3)处开始。选好了行首,然后每列相关4个字节(也就是一个元素依次类推)即可。这需要根据dtype来计算的,要小心行事。

 

随机数生成

使用numpy库中random对象中的random方法生成一个ndarray。random(size)方法只接收一个size参数,这个参数类型是元组,例如:

>>> import numpy as np
>>> x = np.random.random((2,3,4))
>>> x
array([[[0.93901374, 0.16099727, 0.28233592, 0.67971577],
        [0.73135941, 0.15883592, 0.9592103 , 0.68626551],
        [0.24001345, 0.94215957, 0.65371645, 0.75697593]],

       [[0.6912158 , 0.71692135, 0.02452012, 0.07956188],
        [0.0753438 , 0.83542531, 0.73221675, 0.2209369 ],
        [0.57976558, 0.88883098, 0.22543792, 0.48228909]]])
>>> x.dtype # 数据类型
dtype('float64')
>>> x.ndim # 维度
3
>>> type(x) # 返回类型
<type 'numpy.ndarray'>
>>>

上面代码生成了个形状是(2,3,4)的三维数组,元素类型是float64,返回的数据就是numpy.ndarray对象。随机数生成范围在0-1之间。

np.random.random()方法内部实际调用的是np.random.random_sample()函数。

>>> np.random.random_sample() # 没参数只生成一个0-1的随机数
0.13188649562705546
>>> np.random.random_sample((2,3))
array([[0.45948904, 0.28977226, 0.56116225],
       [0.00913285, 0.15645656, 0.66070423]])

 

ndarray对象中的属性

其实前面的讲解中已说了一些属性了,如dtype(元素类型,如果不指定,numpy会自动推断出合适的数据类型),ndim(维数),size(数组长度)等。

我们先创建一个ndarray对象:

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

dtype:获取元素类型

>>> x.dtype
dtype('int32')

ndim:获取元素维度

>>> x.ndim
2

size:获取元素长度

>>> x.size # 12=2x6
12

strides:元素字节跨度之前已详细讲过了

>>> x.strides # 两行字节相差24,两列字节相差4
(24L, 4L)

flags:有关数组内存布局的一些信息

>>> x.flags
  C_CONTIGUOUS : True # 是否C风格排序
  F_CONTIGUOUS : False # 是否Fortran风格排序
  OWNDATA : False # 是否拥有内存
  WRITEABLE : True # 是否可写
  ALIGNED : True # 是否硬件对齐
  WRITEBACKIFCOPY : False # 是否通过另一个数组的复制的
  UPDATEIFCOPY : False # 同 WRITEBACKIFCOPY,已废

详细信息可参考:https://www.numpy.org/devdocs/reference/generated/numpy.ndarray.flags.html#numpy.ndarray.flags

itemsize:数组元素所占字节数,前面讲了np.int_().itemsize是numpy一个整型数据所占用的字节数。

>>> x.itemsize # 元素是整型,所以是4个字节
4

nbytes:数组所占用内存总量,即总字节数

>>> x.nbytes # 48 = size * itemsize = 12 * 4
48

base:底层数据结构

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

我们发现底层的数据结构就一个一维数组。为什么numpy的ndarray的一些运算操作这么快呢?这里点一下,numpy的运算不会改变底层数据结构,只会改变它元信息。其实x是x.base数组的一个视图,所以改变x中的元素,也会改变x.base中的元素。通reshape函数生成的新的ndarray其实也是其原ndarray的视图,如果改变reshape后的数组中的元素,也会改变其原数组的中相对应的元素。

验证reshpae创建的是视图:

>>> x
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
>>> y = x.reshape(6,2) # 将x变换成6行2列的ndarray
>>> x
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
>>> y
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6,  7],
       [ 8,  9],
       [10, 11]])
>>> x.base
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> y.base
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> y[3,1]
7
>>> y[3,1] = 17 # 改变y的第4行第2列改为17
>>> x[1,1] # 发现x中对应的第2行第2列也变成17
17
>>> x.base # x的底层数组也随之改变
array([ 0,  1,  2,  3,  4,  5,  6, 17,  8,  9, 10, 11])
>>> y.base
array([ 0,  1,  2,  3,  4,  5,  6, 17,  8,  9, 10, 11])

如果是副本的话就不是这样子的了,下面看下:

>>> z = x.copy() # x通过copy()方法创建一个副本
>>> z
array([[ 0,  1,  2,  3,  4,  5],
       [ 6, 17,  8,  9, 10, 11]])
>>> z[0,0] = 10
>>> z # z是x的副本,所以改变z不会影响x
array([[10,  1,  2,  3,  4,  5],
       [ 6, 17,  8,  9, 10, 11]])
>>> x
array([[ 0,  1,  2,  3,  4,  5],
       [ 6, 17,  8,  9, 10, 11]])

data:指向数组起始位置的Python对象,好像不知道能干啥?自己help(x.data)一下看看,没准以后能用上。我也没用过cheeky

>>> x.data
<read-write buffer for 0x0000000004C442B0, size 48, offset 0 at 0x0000000004B16110>
>>> type(x.data)
<type 'buffer'>

T:如果将ndarray看成一个矩阵,那么个这个属性就是这个矩阵的转秩,线性代数的知识,不会的回去补一下。就是行变成列,列变成行。

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

flat:这个属性是将多维数据拉平成一维的,返回的是iterator对象,是个迭代器。我们将其转成Python的列表查看。

>>> x.flat
<numpy.flatiter object at 0x00000000036F0090>
>>> list(x.flat)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>>

有的人说,我要将它转成numpy的ndarray怎么办,就这样喽:

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

当然后面还会讲述通过ndarray的方法flatten()也可以直接返回拉平后的Ndarray。