Numpy——ndarray对象(1):创建数组

标准安装的Python中用列表( list )保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3],需要有3个指针和三个整数对象。对于数值运算来说这种结构显然比较浪费内存和CPU计算时间。
此外Python还提供了一个 array 模块,array 对象和列表不同,它直接保存数值,和C语言的一维数组比较类似。但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。

NumPy 提供了两种基本的对象:
ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray(简称数组)是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。

要使用这两种对象,首先要导入模块:
import numpy as np

下面通过代码及注释了解创建numpy数组的基本操作:

>>> a = np.array([1,2,3,4])
>>> b = np.array([5,6,7,8])
>>> c = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]])   #array只有一个参数
>>> b                                                #一维数组
array([5, 6, 7, 8])
>>> c                                                #二维数组
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10]])
>>> c.dtype                                          #获得数组元素的类型
dtype('int32')
>>> a.shape                                          #数组的大小可以通过其shape属性获得
(4,)                                                 #一维的
>>> c.shape                                          #3行4列
(3, 4)
'''
#shape属性可以在保持数组元素个数不变的情况下,改变数组每个轴的长度,但只是改变每个轴的大小,数组元素在内存中的位置并没有改变
'''
>>> c.shape = 4,3
>>> c
array([[ 1,  2,  3],
       [ 4,  4,  5],
       [ 6,  7,  7],
       [ 8,  9, 10]])
>>> c.shape = 2,-1                                   #当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度
>>> c
array([[ 1,  2,  3,  4,  4,  5],
       [ 6,  7,  7,  8,  9, 10]])
>>> d = a.reshape((2,2))                             #有一个参数
#使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape属性保持不变
>>> d
array([[1, 2],
       [3, 4]])
>>> a                                                #a保持不变
array([1, 2, 3, 4])
#数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组的内容
>>> a[1]
2
>>> a[1] = 100
>>> d                                               #d中元素也改变了
array([[  1, 100],
       [  3,   4]])
#可以通过dtype参数在创建时指定元素类型:
>>> np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]],dtype = np.float)    #指定元素为浮点型
array([[  1.,   2.,   3.,   4.],
       [  4.,   5.,   6.,   7.],
       [  7.,   8.,   9.,  10.]])
>>> np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]],dtype = np.complex)  #指定元素为复数
array([[  1.+0.j,   2.+0.j,   3.+0.j,   4.+0.j],
       [  4.+0.j,   5.+0.j,   6.+0.j,   7.+0.j],
       [  7.+0.j,   8.+0.j,   9.+0.j,  10.+0.j]])

以上都是先创建一个Python序列,然后通过 array 函数将其转换为数组。
下面介绍一下numpy中的一些产生数组数据的函数:

>>> np.arange(0,1,0.1)      #arange函数类似于python的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])
>>> np.linspace(0,1,12)
#linspace函数通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值
array([ 0.        ,  0.09090909,  0.18181818,  0.27272727,  0.36363636,
        0.45454545,  0.54545455,  0.63636364,  0.72727273,  0.81818182,
        0.90909091,  1.        ])
>>> np.linspace(0,1,12,endpoint = False)      #不包括终值
array([ 0.        ,  0.08333333,  0.16666667,  0.25      ,  0.33333333,
        0.41666667,  0.5       ,  0.58333333,  0.66666667,  0.75      ,
        0.83333333,  0.91666667])
>>> np.logspace(0,2,20)    #创建等比数列,此处产生1(10^0)到100(10^2)、有20个元素的等比数列
array([   1.        ,    1.27427499,    1.62377674,    2.06913808,
          2.6366509 ,    3.35981829,    4.2813324 ,    5.45559478,
          6.95192796,    8.8586679 ,   11.28837892,   14.38449888,
         18.32980711,   23.35721469,   29.76351442,   37.92690191,
         48.32930239,   61.58482111,   78.47599704,  100.        ])

此外,使用 frombuffer, fromstring, fromfile 等函数可以从字节序列创建数组:

>>> s = "abcdefgh"
>>> np.fromstring(s, dtype = np.int8)
'''Python的字符串实际上是字节序列,每个字符占一个字节,因此如果从字符串s创建一个8bit的整数数组的话,所得到的数组正好就是字符串中每个字符的ASCII编码'''
array([ 97,  98,  99, 100, 101, 102, 103, 104], dtype=int8)
>>> np.fromstring(s, dtype = np.int16)
'''如果从字符串s创建16bit的整数数组,那么两个相邻的字节就表示一个整数,把字节98和字节97当作一个16位的整数,它的值就是98*256+97 = 25185。可以看出内存中是以little endian(低位字节在前)方式保存数据的'''
array([25185, 25699, 26213, 26727], dtype=int16)
>>> np.fromstring(s, dtype = np.float)    #把整个字符串转换为一个64位的双精度浮点数数组
array([  8.54088322e+194])
'''如果我们用C语言的二进制方式写了一组double类型的数值到某个文件中,那么可以从此文件读取相应的数据,并通过fromstring函数将其转换为float64类型的数组。'''

还可以使用fromfunction创建数组:

>>> def func(i):
        return i % 4 + 1

>>> np.fromfunction(func, (10,))
array([ 1.,  2.,  3.,  4.,  1.,  2.,  3.,  4.,  1.,  2.])
'''fromfunction函数的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape),因为它支持多维数组,所以第二个参数必须是一个序列,本例中用(10,)创建一个10元素的一维数组。'''