Python 科学计算 -- Numpy

标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3],需要有3个指针和三个整数对象。对于数值运算来说这种结构显然比较浪费内存和CPU计算时间。

此外Python还提供了一个array模块,array对象和列表不同,它直接保存数值,和C语言的一维数组比较类似。但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。

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

NumPy 是 Numerical Python 的简称,是高性能计算和数据分析的基础包。其主要功能如下:

  • ndarray,快速和节省空间的多维数组,提供数组化的算术运算和高级的 广播 功能。
  • 使用标准数学函数对整个数组的数据进行快速运算,而不需要编写循环。
  • 读取/写入磁盘上的阵列数据和操作存储器映像文件的工具。
  • 线性代数,随机数生成,和傅里叶变换的能力。
  • 集成C,C++,Fortran代码的工具。

在使用 NumPy 之前,需要先导入该模块:

In [1]:
import numpy as np

一、基本数据结构

NumPy的主要对象是同种元素的多维数组。这是一个所有的元素都是一种类型、通过一个正整数元组索引的元素表格(通常是元素是数字)。在NumPy中维度(dimensions)叫做轴(axes),轴的个数叫做秩(rank)。NumPy的数组类被称作 ndarray ,通常被称作数组。其数据结构如下图所示:

ndarray数组对象在内存中的储存方式

In [2]:
a = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]])
In [3]:
a
Out[3]:
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10]])
In [4]:
type(a)
Out[4]:
numpy.ndarray
  • ndarray.ndim

数组轴的个数,即数组的维度。在 python 的世界中,轴的个数被称作秩。

In [5]:
a.ndim
Out[5]:
2
  • ndarray.shape

数组的大小。这是一个指示数组在每个维度上大小的整数元组。例如一个 n 排 m 列的矩阵,它的shape属性将是(n, m),这个元组的长度显然是秩,即维度或者 ndim 属性。

In [6]:
a.shape
Out[6]:
(3, 4)

可以通过改变 shape 值来改变数组的结构,shape 值的修改可以用 reshape() 方法,或者直接赋值:

In [7]:
a.shape = (4, 3)
In [8]:
a
Out[8]:
array([[ 1,  2,  3],
       [ 4,  4,  5],
       [ 6,  7,  7],
       [ 8,  9, 10]])
In [11]:
a.reshape(3, 4)
Out[11]:
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10]])
  • ndarray.size

数组元素的总个数,等于 shape 属性中元组元素的乘积。

In [12]:
a.size
Out[12]:
12
  • ndarray.dtype

一个用来描述数组中元素类型的对象,可以通过创造或指定dtype使用标准Python类型。另外NumPy提供它自己的数据类型。

In [13]:
a.dtype
Out[13]:
dtype('int64')
  • ndarray.itemsize

数组中每个元素的字节大小。例如,一个元素类型为 float64 的数组 itemsize属性值为 8(=64/8), 又如,一个元素类型为complex32的数组item属性为4(=32/8)。

In [14]:
a.itemsize
Out[14]:
8
  • ndarray.data

包含实际数组元素的缓冲区,通常我们不需要使用这个属性,因为我们总是通过索引来使用数组中的元素。

In [15]:
a.data
Out[15]:
<read-write buffer for 0x7fbeb7867f80, size 96, offset 0 at 0x7fbeb7028bb0>

二、数组创建

  • array

将序列转化为数组,例:

In [16]:
seq1 = [1, 2, 3]
In [17]:
seq2 = (4, 5, 6)
In [18]:
np.array([seq1, seq2])
Out[18]:
array([[1, 2, 3],
       [4, 5, 6]])
  • arange

类似于python的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值:

In [19]:
np.arange(0, 1, 0.1)
Out[19]:
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])
  • linspace

函数通过指定开始值、终值和元素个数来等分的创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值:

In [20]:
np.linspace(1, 10, 5)
Out[20]:
array([  1.  ,   3.25,   5.5 ,   7.75,  10.  ])
In [21]:
np.linspace(1, 10, 10)
Out[21]:
array([  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.])
In [22]:
np.linspace(1, 10, 10).dtype
Out[22]:
dtype('float64')
  • logspace

与 linspace 类似,不过它创建等比数列:

In [23]:
np.logspace(0, 1, 12)
Out[23]:
array([  1.        ,   1.23284674,   1.51991108,   1.87381742,
         2.3101297 ,   2.84803587,   3.51119173,   4.32876128,
         5.33669923,   6.57933225,   8.11130831,  10.        ])
In [24]:
np.logspace(0, 2, 20)
Out[24]:
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.        ])
  • zerosones

使用给定的长度或形状分别的创建0‘s 和 1‘s数组:

In [35]:
np.zeros(10)
Out[35]:
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])
In [37]:
np.zeros((3, 6))
Out[37]:
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.]])
  • empty

创建一个没有使用特定值来初始化的数组。给这些方法传递一个元组作为形状来创建高维数组:

In [38]:
np.empty((2, 3, 2))
Out[38]:
array([[[ 0.,  0.],
        [ 0.,  0.],
        [ 0.,  0.]],

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

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

In [25]:
s = "abcdefgh"
In [28]:
np.fromstring(s, dtype=np.int8)
Out[28]:
array([ 97,  98,  99, 100, 101, 102, 103, 104], dtype=int8)
In [29]:
np.fromstring(s, dtype=np.int16)
Out[29]:
array([25185, 25699, 26213, 26727], dtype=int16)
In [30]:
np.fromstring(s, dtype=np.int32)
Out[30]:
array([1684234849, 1751606885], dtype=int32)
In [31]:
np.fromstring(s, dtype=np.float)
Out[31]:
array([  8.54088322e+194])

fromfunction函数的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape),因为它支持多维数组,所以第二个参数必须是一个序列。可以写一个Python的函数,它将数组下标转换为数组中对应的值,然后使用此函数创建数组,这里用(10,)创建一个10元素的一维数组。:

In [32]:
def func(i):
    return i%4 + 1

np.fromfunction(func, (10,))
Out[32]:
array([ 1.,  2.,  3.,  4.,  1.,  2.,  3.,  4.,  1.,  2.])

再例如,创建一个二维数组表示九九乘法表,输出的数组a中的每个元素a[i, j]都等于func2(i, j):

In [34]:
def func(i, j):
    return (i + 1) * (j + 1)

np.fromfunction(func, (9, 9))
Out[34]:
array([[  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.],
       [  2.,   4.,   6.,   8.,  10.,  12.,  14.,  16.,  18.],
       [  3.,   6.,   9.,  12.,  15.,  18.,  21.,  24.,  27.],
       [  4.,   8.,  12.,  16.,  20.,  24.,  28.,  32.,  36.],
       [  5.,  10.,  15.,  20.,  25.,  30.,  35.,  40.,  45.],
       [  6.,  12.,  18.,  24.,  30.,  36.,  42.,  48.,  54.],
       [  7.,  14.,  21.,  28.,  35.,  42.,  49.,  56.,  63.],
       [  8.,  16.,  24.,  32.,  40.,  48.,  56.,  64.,  72.],
       [  9.,  18.,  27.,  36.,  45.,  54.,  63.,  72.,  81.]])

数组构建函数清单

函数 描述
array 转换输入数据(列表,数组或其它序列类型)到一个ndarray,可以推断一个dtype或明确的设置一个dtype。默认拷贝输入数据。
asarray 转换输入为一个ndarray,当输入已经是一个ndarray时就不拷贝。
arange 同内建的range函数,但不返回列表而是一个ndarray
ones, ones_like 根据提供的shape和dtype产生一个全1的数组。ones_like使用另一歌数组为入参,产生一个shape和dtype都相同的数组。
zeros, zeros_like 同ones和ones_like,但是生成全0的数组
empty, enpty_like 通过分配新内存来构造新的数组,但不同与ones 和 zeros,不初始任何值。
eye, identity 生成一个NxN的单位方阵(对角线上为1,其它地方为0)
frombuffer 从字节序列创建数组
fromstring 从字节序列创建数组
fromfile 从字节序列创建数组

三、数据类型

Numpy数组的数据类型或dtype是一个特别的对象,保存了ndarray如何解释一块内存为特定类型数据的信息:

In [39]:
arr1 = np.array([1, 2, 3], dtype=int16)
In [40]:
arr2 = np.array([1, 2, 3], dtype=int32)
In [41]:
arr3 = np.array([1, 2, 3], dtype=float32)
In [42]:
print arr1.dtype, arr2.dtype, arr3.dtype, 
int16 int32 float32

在大多数情况下,数组的 dtype 直接映射到底层的机器表示,这使得很容易地读取和写入二进制流到磁盘上,也能链接低级语言,如C 或Fortran编写的代码。数值表示的dtypes以相同的方式命名:一个类型名,如 folt 或 int ,后面跟着一个表示数字有多少位的数字。一个标准的双精度浮点值(它是Python的 float 对象的底层表示)占据8字节或64位。因此,这一类型在NumPy中被认为是 float64 。

NumPy支持的全部数据类型的清单

类型 类型码 描述
int8, uint8 i1, u1 有符号和无符号8位(1字节)整数类型
int16, uint16 i2, u2 有符号和无符号16位整数类型
int32, uint32 i4, u4 有符号和无符号32位整数类型
int64, uint64 i8, u8 有符号和无符号64位整数类型
float16 f2 半精度浮点类型
float32 f4 or f 标准精度浮点。与C的 float 兼容
float64, float128 f8 or d 标准双精度浮点。与C的 double 和Python 的 folat 对象兼容
float128 f16 or g 扩展精度浮点
complex64, complex128, complex256 c8, c16, c32 分别使用两个32,64,128位浮点表示的复数
bool ? 布尔值,存储 True 和 False
object O Python对象类型
string_ S 定长字符窜类型(每字符一字节)。例如,为了生成长度为10的字符窜,使用 ‘S10’
unicode_ f16 or g 扩展精度浮点(字节书依赖平台)。同 string_ 有相同的语义规范(例如:U10 )

可以使用ndarray的 astype 方法显示的把一个数组的dtype转换或 投射 到另外的类型:

In [43]:
arr = np.arange(10)
In [44]:
arr.dtype
Out[44]:
dtype('int64')
In [45]:
arr.astype('float')
Out[45]:
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])

如果把浮点数转换到整形dtype,小数部分将会被截断,即只取整数部分:

In [46]:
arr = np.array([random.uniform(1, 15) for item in xrange(0, 10)])
In [47]:
arr
Out[47]:
array([  6.65191142,   5.863138  ,   8.00773073,  14.46790654,
        14.3949338 ,  14.36621263,  13.77403631,   2.15744178,
        10.39546436,   9.38273214])
In [48]:
arr.astype('int32')
Out[48]:
array([ 6,  5,  8, 14, 14, 14, 13,  2, 10,  9], dtype=int32)

在很多情况下,我们拿到的数据可能都是字符串形式,如果要将其转化为 int 或者 float 数据,那么 astype 方式将是很有用的:

In [49]:
numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
In [50]:
numeric_strings
Out[50]:
array(['1.25', '-9.6', '42'], 
      dtype='|S4')
In [51]:
numeric_strings.astype(float)
Out[51]:
array([  1.25,  -9.6 ,  42.  ])

四、元素存取

数组元素的存取方法和Python的标准方法相同:

In [52]:
a = arange(10)
In [53]:
a[:]    # 获取全部元素
Out[53]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [54]:
a[:5]   # 获取前 5 个元素
Out[54]:
array([0, 1, 2, 3, 4])
In [55]:
a[5]
Out[55]:
5
In [56]:
a[7] = 234
In [57]:
a[:-1]    # -1 代表最后一个元素,这里表示获取全部元素
Out[57]:
array([  0,   1,   2,   3,   4,   5,   6, 234,   8])
In [59]:
a[-1] = 10
In [60]:
a[::-1]    # 指定获取元素的步长为 -1 则表示将数组逆序
Out[60]:
array([ 10,   8, 234,   6,   5,   4,   3,   2,   1,   0])

和 Python 的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间:

In [61]:
b = a[1:4]
In [62]:
b
Out[62]:
array([1, 2, 3])
In [63]:
b[2] = 20    # 数组 a 中的也会因此而变化
In [64]:
b
Out[64]:
array([ 1,  2, 20])
In [65]:
a
Out[65]:
array([  0,   1,   2,  20,   4,   5,   6, 234,   8,  10])
In [66]:
a[:2] = 64    # 可以通过切片来同时修改多个值,这里修改前两个元素为 64
In [67]:
a
Out[67]:
array([ 64,  64,   2,  20,   4,   5,   6, 234,   8,  10])

如果希望有数组切片的一个拷贝,则需要明显的拷贝数组;例如:

In [68]:
c = a[5:8].copy() 
In [69]:
c
Out[69]:
array([  5,   6, 234])
In [70]:
c[:] = 8    # c 是从 a 中拷贝过来的,有自己的存储空间,a 中的值不会因此改变
In [71]:
c
Out[71]:
array([8, 8, 8])
In [72]:
a
Out[72]:
array([ 64,  64,   2,  20,   4,   5,   6, 234,   8,  10])

使用整数序列来获取数组的元素(Fancy 索引)

当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间:

In [73]:
x = np.arange(10,1,-1)
In [74]:
x
Out[74]:
array([10,  9,  8,  7,  6,  5,  4,  3,  2])
In [75]:
x[[3, 3, 1, 8]]   # 给定一个列表,选取下表为 3, 3, 1, 8 的元素组成一个新的数组
Out[75]:
array([7, 7, 9, 2])
In [76]:
x[2, 3, 4]  # 注意这种错误的获取方式
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-76-0e04b2c8a814> in <module>()
----> 1 x[2, 3, 4]

IndexError: too many indices for array
In [77]:
b = x[np.array([3,3,-3,8])]  ## 通过数组来获取数组中的片段
In [78]:
b[2] = 100  # b 是从 x 中拷贝过来的,有着自己的存储空间
In [79]:
x   # x 的值没有被修改
Out[79]:
array([10,  9,  8,  7,  6,  5,  4,  3,  2])
In [80]:
b
Out[80]:
array([  7,   7, 100,   2])
In [81]:
x[[3,5,1]] = -1, -2, -3    # # 整数序列下标也可以用来修改元素的值
In [82]:
x
Out[82]:
array([10, -3,  8, -1,  6, -2,  4,  3,  2])

使用布尔数组

当使用布尔数组b作为下标存取数组x中的元素时,将收集数组x中所有在数组b中对应下标为True的元素。使用布尔数组作为下标获得的数组不和原始数组共享数据空间,注意这种方式只对应于布尔数组,不能使用布尔列表。

In [83]:
 x = np.arange(5,0,-1)
In [84]:
x
Out[84]:
array([5, 4, 3, 2, 1])
In [85]:
x[np.array([True, False, True, False, False])]    # 布尔数组中下标为0,2的元素为True,因此获取x中下标为0,2的元素
Out[85]:
array([5, 3])
In [86]:
x[[True, False, True, False, False]]    # 如果是布尔列表,则把True当作1, False当作0,按照整数序列方式获取x中的元素
/opt/conda/envs/python2/lib/python2.7/site-packages/ipykernel/__main__.py:1: FutureWarning: in the future, boolean array-likes will be handled as a boolean array index
  if __name__ == '__main__':
Out[86]:
array([4, 5, 4, 5, 5])
In [87]:
x[np.array([True, False, True, True])]    # 布尔数组的长度不够时,不够的部分都当作False
Out[87]:
array([5, 3, 2])
In [88]:
 x[np.array([True, False, True, True])] = -1, -2, -3     # 布尔数组下标也可以用来修改元素
In [89]:
x
Out[89]:
array([-1,  4, -2, -3,  1])

布尔数组一般不是手工产生,而是使用布尔运算的ufunc函数产生:

In [90]:
 x = np.random.rand(10)     # 产生一个长度为10,元素值为0-1的随机数的数组
In [91]:
x
Out[91]:
array([ 0.2352167 ,  0.25615277,  0.64412622,  0.04478842,  0.89773965,
        0.16132042,  0.59540146,  0.87122774,  0.91003873,  0.42508104])
In [92]:
x>0.5    # 数组x中的每个元素和0.5进行大小比较,得到一个布尔数组,True表示x中对应的值大于0.5
Out[92]:
array([False, False,  True, False,  True, False,  True,  True,  True, False], dtype=bool)
In [93]:
x[x>0.5]     # 使用x>0.5返回的布尔数组收集x中的元素,因此得到的结果是x中所有大于0.5的元素的数组
Out[93]:
array([ 0.64412622,  0.89773965,  0.59540146,  0.87122774,  0.91003873])

多维数组存取

多维数组的存取和一维数组类似,因为多维数组有多个轴,因此它的下标需要用多个值来表示,NumPy采用组元(tuple)作为数组的下标:

In [95]:
# 创建一个二维数组,纵轴的值为0, 10, 20, 30, 40, 50;横轴的值为0, 1, 2, 3, 4, 5。纵轴的每个元素都和横轴的每个元素求和得到一个二位数组。
double_arr = np.arange(0, 60, 10).reshape(-1, 1) + np.arange(0, 6)
In [96]:
double_arr
Out[96]:
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])
In [97]:
double_arr[0, 3:5]
Out[97]:
array([3, 4])
In [99]:
double_arr[3, 3]
Out[99]:
33
In [100]:
double_arr[1]
Out[100]:
array([10, 11, 12, 13, 14, 15])
In [101]:
double_arr[:,2]
Out[101]:
array([ 2, 12, 22, 32, 42, 52])
In [102]:
double_arr[2::2, ::2]
Out[102]:
array([[20, 22, 24],
       [40, 42, 44]])

多维数组同样也可以使用整数序列和布尔数组进行存取:

In [103]:
double_arr[range(5), range(1, 6)]
Out[103]:
array([ 1, 12, 23, 34, 45])
In [104]:
double_arr[3:, [0, 2, 4, 5]]
Out[104]:
array([[30, 32, 34, 35],
       [40, 42, 44, 45],
       [50, 52, 54, 55]])
In [105]:
mask = np.array([1, 0, 0, 1, 1], dtype=np.bool)
In [106]:
mask
Out[106]:
array([ True, False, False,  True,  True], dtype=bool)
In [107]:
double_arr[2, mask]
Out[107]:
array([20, 23, 24])

五、结构数组

在C语言中我们可以通过struct关键字定义结构类型,结构中的字段占据连续的内存空间,每个结构体占用的内存大小都相同,因此可以很容易地定义结构数组。和C语言一样,在NumPy中也很容易对这种结构数组进行操作。只要NumPy中的结构定义和C语言中的定义相同,NumPy就可以很方便地读取C语言的结构数组的二进制数据,转换为NumPy的结构数组。

在 Numpy 中,定义一个结构数组需要先创建一个 dtype 对象,通过其字典参数描述结构类型的各个字段。字典有两个关键字:names,formats。每个关键字对应的值都是一个列表。names定义结构中的每个字段名,而formats则定义每个字段的类型。例如:

persontype = np.dtype({
    'names':['name', 'age', 'weight'],
    'formats':['S32','i', 'f']})
a = np.array([("Zhang",32,75.5),("Wang",24,65.2)],
    dtype=persontype)

结构数组在编写高性能程序,需要用到 C 扩展时是很有用的,但在大多情况下是很少用到的,所以这里只做简单的描述。

六、ufunc运算

ufunc 是 universal function 的缩写,它是一种能对数组的每个元素进行操作的函数。也可以认为它们是对简单函数的一个快速矢量化封装,它们接受一个或多个标量值并产生一个或多个标量值。NumPy内置的许多ufunc函数都是在C语言级别实现的,因此它们的计算速度非常快。

以下两个表格是 numpy 中可用 ufunc 函数清单:

Unary ufuncs

函数 描述
abs, fabs 计算基于元素的整形,浮点或复数的绝对值。fabs对于没有复数数据的快速版本
sqrt 计算每个元素的平方根。等价于 arr ** 0.5
square 计算每个元素的平方。等价于 arr ** 2
exp 计算每个元素的指数。
log, log10, log2, log1p 自然对数(基于e),基于10的对数,基于2的对数和 log(1 + x)
sign 计算每个元素的符号:1(positive),0(zero), -1(negative)
ceil 计算每个元素的天花板,即大于或等于每个元素的最小值
floor 计算每个元素的地板,即小于或等于每个元素的最大值
rint 圆整每个元素到最近的整数,保留dtype
modf 分别返回分数和整数部分的数组
isnan 返回布尔数组标识哪些元素是 NaN (不是一个数)
isfinite, isinf 分别返回布尔数组标识哪些元素是有限的(non-inf, non-NaN)或无限的
cos, cosh, sin sinh, tan, tanh regular 和 hyperbolic 三角函数
arccos, arccosh, arcsin, arcsinh, arctan, arctanh 反三角函数
logical_not 计算基于元素的非x的真值。等价于 -arr

Binary universal funcitons

函数 描述
add 在数组中添加相应的元素
substract 在第一个数组中减去第二个数组
multiply 对数组元素相乘
divide, floor_divide 除和地板除(去掉余数)
power 使用第二个数组作为指数提升第一个数组中的元素
maximum, fmax 基于元素的最大值。 fmax 忽略 NaN
minimum, fmin 基于元素的最小值。 fmin 忽略 NaN
mod 基于元素的模(取余)
copysign 拷贝第二个参数的符号到第一个参数
greater, greater_equal, less, less_equal, not_equal 基于元素的比较,产生布尔数组。等价于中缀操作符 >, >=, <, <=, ==, !=
logical_and, logical_or, logical_xor 计算各个元素逻辑操作的真值。等价于中缀操作符 &, l, ^
In [1]:
x = np.linspace(0, 2*np.pi, 10)
In [2]:
x
Out[2]:
array([ 0.        ,  0.6981317 ,  1.3962634 ,  2.0943951 ,  2.7925268 ,
        3.4906585 ,  4.1887902 ,  4.88692191,  5.58505361,  6.28318531])
In [3]:
y = np.sin(x)     # 对数组x中的每个元素进行正弦计算,返回一个同样大小的新数组
In [4]:
y
Out[4]:
array([  0.00000000e+00,   6.42787610e-01,   9.84807753e-01,
         8.66025404e-01,   3.42020143e-01,  -3.42020143e-01,
        -8.66025404e-01,  -9.84807753e-01,  -6.42787610e-01,
        -2.44929360e-16])