• NumPy学习指南(第2版)


    第一章 NumPy快速入门
    首先,我们将介绍如何在不同的操作系统中安装NumPy和相关软件,并给出使用NumPy的简单示例代码。
    然后,我们将简单介绍IPython(一种交互式shell工具)。
    如前言所述,SciPy和NumPy有着密切的联系,因此你将多次看到SciPy的身影。
    在本章的末尾,我们将告诉你如何利用在线资源,以便你在受困于某个问题或不确定最佳的解题方法时,可以在线获取帮助。
     
    本章涵盖以下内容:
    1.在Windows、Linux和Macintosh操作系统上安装Python,SciPy,Matplotlib,IPython和NumPy;
    2.编写简单的NumPy代码;
    3.了解IPython;
    4.浏览在线文档和相关资源。
     
    1.1 Python
    NumPy是基于Python的,因此在安装NumPy之前,我们需要先安装Python。某些操作系统已经默认安装有Python环境,但你仍需检查Python的版本是否与你将要安装的NumPy版本兼容。
    Python有很多种实现,包括一些商业化的实现和发行版。
    在本书中,我们将使用CPython(CPython是用C语言实现的Python解释器)实现,从而保证与NumPy兼容。
     
    1.2 动手实践:在不同的操作系统上安装Python
    NumPy在Windows、各种Linux发行版以及Mac OS X上均有二进制安装包。
    如果你愿意,也可以安装包含源代码的版本。
    (1) Debian和Ubuntu Debian和Ubuntu可能已经默认安装了Python,但开发者包(development headers) ①一般不会默认安装。在Debian和Ubuntu中安装python和python-dev的命令如下:
    1. sudo apt-get install python
    2. sudo apt-get install python-dev
     
    (2) Windows Python的Windows安装程序可以在www.python.org/download下载。在这个站点中,我们也可以找到Mac OS X的安装程序,以及Linux、 Unix和Mac OS X下的源代码包。
     
    (3) Mac Mac OS X中预装了Python,而我们也可以通过MacPorts、 Fink或者类似的包管理工具来获取Python。举例来说,可以使用如下命令安装Python 2.7:
    1. sudo port install python27
     
    LAPACK并不是必需的,但如果需要,NumPy在安装过程中将检测并使用之。我们推荐大家安装LAPACK以便应对海量数据的计算,因为它拥有高效的线性代数计算模块。
     
    1.3 Windows
    在Windows上安装NumPy是很简单的。你只需要下载安装程序,运行后在安装向导的指导下完成安装。
     
    1.4 动手实践:在Windows上安装NumPy、Matplotlib、SciPy和IPython
    在Windows上安装NumPy是必需的,但幸运的是,安装过程并不复杂,我们将在下面详细阐述。
    虽然这一操作对于使用本书不是必需的。
    我们将按照如下步骤安装这些软件。
     
     
     
     
     
    1.5 Linux
    在Linux上安装NumPy和相关软件的方法取决于具体使用的Linux发行版。我们将用命令行的方式安装NumPy,不过你也可以使用图形界面安装程序,这取决于具体的Linux发行版。除了软件包的名字不一样,安装Matplotlib、SciPy和IPython的命令与安装NumPy时是完全一致的。
    这几个软件包不是必需安装的,但这里建议你也一并安装。
     
    1.6 动手实践:在Linux上安装NumPy,Matplotlib,SciPy和IPython
    大部分Linux发行版都有NumPy的软件包。我们将针对一些流行的Linux发行版给出安装步骤。
    (1)要在Red Hat上安装NumPy,请在命令行中执行如下命令:
    1. yum install python-numpy
    (2)要在Mandriva上安装NumPy,请在命令行中执行如下命令:
    1. urpmi python-numpy
    (3)要在Gentoo上安装NumPy,请在命令行中执行如下命令:
    1. sudo emerge numpy
    (4)要在Debian或Ubuntu上安装NumPy,请在命令行中执行如下命令:
    1. sudo apt-get install python-numpy
     
    1.7 Mac OS X
    在Mac上,你可以通过图形用户界面或者命令行来安装NumPy,Matplotlib和SciPy,根据自己的喜好选择包管理工具,如MacPorts或Fink等。
     
    1.8 动手实践:在Mac OS X上安装NumPy,Matplotlib和SciPy
     
     
     
     
     
    1.9 动手实践:使用MacPorts或Fink安装NumPy,SciPy,Matplotlib和IPython
    我们也可以选择另外一种安装方式,即使用MacPorts或Fink来安装NumPy,SciPy,Matplotlib以及IPython。
    下面给出的安装步骤将安装所有这些软件包。
    (1)输入以下命令,从MacPorts安装这些软件包:
    1. sudo port install py-numpy py-scipy py-matplotlib py-ipython
    (2)Fink也包含了相关软件包,NumPy的有scipy-core-py24,scipy-core-py25和scipy-core-py26;SciPy的有scipy-py24,scipy-py25和scipy-py26。
    执行如下命令,我们来安装基于Python2.6的NumPy以及其他推荐安装的软件包。
    1. fink install scipy-core-py26 scipy-py26 matplotlib-py26
    ??书中是这么写的,但我怀疑numpy的安装是出现的错误。
     
    1.10 编译源代码
    NumPy的源代码可以使用git获取,如下所示:
    git clone git://github.com/numpy/numpy.git numpy
    使用如下命令将NumPy安装至/usr/local;
    1. python setup.py build
    2. sudo python setup.py install --prefix=/usr/local
    我们需要有C编译器(如GCC)和Python开发者包(python-dev或python-devel),然后才可对源代码进行编译。
     
    1.11 数组对象
    在介绍完NumPy的安装步骤后,我们来看看NumPy中的数组对象。NumPy数组在数值运算方面的效率优于Python提供的list容器。
    使用NumPy可以在代码中省去很多循环语句,因此其代码比等价的Python代码更为简洁。
     
    1.12 动手实践:向量加法
    假设我们需要对两个向量a和b做加法。
    这里的向量即数学意义上的一维数组,随后我们将在第5章中学习如何用NumPy数组表示矩阵。
    向量a的取值为0-n的整数的平方,例如n取3时,向量a为0,1,或4.
    向量b的取值为0-n的整数的立方,例如n取3时,向量b为0,1,或8.
    用纯Python代码应该怎么写呢?我们先想一想这个问题,随后再与等价的NumPy代码进行比较。
    (1)以下的纯Python代码可以解决上述问题。
    1. def pythonsum(n):
    2. a=range(n)
    3. b=range(n)
    4. c=[]
    5. for i in range(Len(a)):
    6. a[i]=i**2
    7. b[i]=i**3
    8. c.append(a[i]+b[i])
    9. return c
    (2)以下是使用NumPy的代码,它同样能够解决问题:
    1. def numpysum(n):
    2. a=numpy.arange(n)**2
    3. b=numpy.arange(n)**3
    4. c=a+b
    5. return c
    注意,numpysum()函数中没有使用for循环。同时,我们使用NumPy中的arange函数来创建包含0-n的整数的NumPy数组。
    代码中的arange函数前有一个前缀numpy,表明该函数是从NumPy模块导入的。
     
    下面我们做一个有趣的实验。
    在前言部分我们曾提到,NumPy在数组操作上的效率优于纯Python代码。
    那么究竟快多少呢?
    接下来的程序将告诉我们答案,它以微秒106 s的精度分别记录下numpysum()和pythonsum()函数的耗时。
    这个程序还将输出加和候的向量最末的两个元素。
    让我们来看看纯Python代码和NumPy代码是否得到相同的结果。
    1. #!/usr/bin/env/python
    2. import sys
    3. from datetime import datetime
    4. import numpy as np
    5. '''
    6. 本书第1章
    7. 该段代码演示Python中的向量加法
    8. 使用如下命令运行程序:
    9. python vectorsum.py n
    10. n为指定向量大小的整数
    11. 加法中的第一个向量包含0到n的整数的平方
    12. 第二个向量包含0到n的整数的立方
    13. 程序将打印出向量加和后的最后两个元素以及运行消耗的时间
    14. '''
    15. def numpysum():
    16. a=np.arange(n)**2
    17. b=np.arange(n)**3
    18. c=a+b
    19. return c
    20. def pythonsum():
    21. a=range(n)
    22. b=range(n)
    23. c=[]
    24. for i in range(len(a)):
    25. a[i]=i**2
    26. b[i]=i**3
    27. c.append(a[i]+b[i])
    28. return c
    29. size=int(sys.argv[1])
    30. start=datetime.now()
    31. c=pythonsum(size)
    32. delta=datetime.now()-start
    33. print('The last 2 elements of the sum',c[-2:])
    34. print('PythonSun elapsed time in microseconds',delta.microseconds)
    35. start=datetime.now()
    36. c=numpysum(size)
    37. delta=datetime.now()-start
    38. print("The last 2 elements of the sum",c[-2:])
    39. print('NumPySum elapsed time in microseconds',delta.microseconds)
     显然,NumPy代码比等价的纯Python代码运行速度快得多。
    有一点可以肯定,即不论我们使用NumPy还是Python,得到的结果是一致的。
    不过,两者的输出结果在形式上有些差异。
    注意,numpysum()函数的输出不包含逗号。这是为什么呢?显然,我们使用的是NumPy数组,而非Python资深的list容器。
    正如前言所述,NumPy数组对象以专用数据结构来存储数值。我们将在下一章中详细介绍NumPy数组对象。
     
     
    1.13 IPython:一个交互式shell工具
    科学家和工程师都喜欢做实验,而IPython正是诞生于爱做实验的科学家之手。IPython提供的交互式实验环境被很多人认为是Matlab,Mathematica和Maple的开源替代品。
    你可以在线获取包括安装指南在内的更多信息,地址为http://ipython.org/。
    IPython是开源免费的软件,可以在Linux、Unix、Mac OS以及Windows上使用。
    IPython的作者们希望那些用导IPython的科研工作成果在发表时能够提到IPython,这是他们对IPython使用者唯一的要求。
    下面是IPython的基本功能:
        tab键自动补全;
        历史记录存档;
        行内编辑;
        使用%run可以调用外部Python脚本;
        支持系统命令;
        支持pylab模式;
        Python代码调试和性能分析。
     
     
    在pylab模式下,IPython将自动导入SciPy,NumPy和Matplotlib模块。如果没有这个功能,我们只能手动导入每一个所需模块。
    而现在,我们只需在命令行中输入如下命令:
     
    1. ipython--pylab
    使用quit()函数或快捷键Ctrl+D均可以退出IPython shell。
    有时我们想要回到之前做过的实验,IPython可以便捷地保存会话以便稍后使用。
     
    1. %logstart
     
    举例来说,我们之前的向量加法程序放在当前目录下,可以按照如下方式运行脚本:
     
    1. ls
    2. README vectorsum.py
    3. %run -i vectorsum.py 1000
    你可能还记得,这里的1000是指向量中元素的数量。%run的-d参数将开启ipdb调试器,键入c后,脚本就开始逐行执行了(如果脚本有n行,就一共执行n步直到代码结束)。
    在ipdb提示符后面键入quit可以关闭调试器。
     
    我们还可以使用%run的-p参数对脚本进行性能分析。
     
     
     
    根据性能分析的结果,可以更多地了解程序的工作机制,并能够据此找到程序的性能瓶颈。
    使用%hist命令可以查看命令行历史记录。
     
    1.14 在线资源和帮助
    在IPython的pylab模式下,我们可以使用help命令打开NumPy函数的手册页面。
    你并不需要知道所偶函数的名字,因为可以在键入少量字符后按下Tab键进行自动补全。
    例如,我们来查看一下arange函数的相关信息。
     
     
     
    广受欢迎的开发技术问题网站Stack Overflow上有成百上千的提问被标记为numpy相关问题。你可以到这里查看这些问题:
     
     
     
    1.15 本章小结
    在本章中,我们安装了NumPy以及其他推荐软件。我们成功运行了向量加法程序,并以此证明NumPy优异的性能。随后,我们介绍了交互式shell工具IPython。此外,我们还列出了供你参考的NumPy文档和在线资源。
    在下一章中,我们将深入了解NumPy中的一些基本概念,包括数组和数据类型。
     
     
     
     
     
     
     
    第2章  NumPy基础
    本章涵盖以下内容:
    数据类型
    数组类型
    类型转换
    创建数组
    数组索引
    数组切片
    改变维度
     
    本章代码段中的输入和输出均来自IPython会话。
    (IPython是用于科学计算的交互式shell工具)IPython的pylab模式可以自动导入包括NumPy在内的很多Python科学计算库,并且在IPython中没有必要显式调用print语句输出变量的值。
     
     
    2.1 NumPy数组对象
    NumPy中的ndarray是一个多维数组对象,该对象由两部分组成:
        实际的数据;
        描述这些数据的元数据。
    大部分的数组操作仅仅修改元数据部分,而不改变底层的实际数据。
     
    在第1章中,我们已经知道如何使用arange函数创建数组。实际上,当时创建的数只是包含一组数字的一维数组,而ndarray支持更高的维度。
    NumPy数组一般是同质的(但有一种特殊的数组类型例外,它是异质的),即数组中的所有元素类型必须是一致的。
    这样有一个好处:如果我们知道数组中的元素均为同一类型,该数组所需的存储空间就很容易确定下来。
     
    与Python中一样,NumPy数组的下标也是从0开始的。数组元素的数据类型用专门的对象表示,而这些对象我们将在本章详细探讨。
    我们再次用arange函数创建数组,并获取其数据类型:
    1. a=np.arange(5)
    2. a.dtype
    3. Out[17]: dtype('int32')
    数组a的数据类型为int32。——如果你使用64位的Python,得到的结果可能是int64.不论哪种情形,该数组的数据类型都是整数(64位或32位)。除了数据类型,数组的维度也是重要的属性。
    第1章中的例子演示了怎样创建一个向量(即一维的NumPy数组)。向量在数学中很常用,但大部分情况下,我们需要更高维的对象。先来确定一下刚刚所创建向量的维度。
    1. a
    2. Out[18]: array([0,1,2,3,4])
    3. a.shape
    4. Out[19]:(5,)
    正如你所看到的,这是一个包含5个元素的向量,取值分别为0-4的整数。数组的shape属性返回一个元组(tuple),元组中的元素即为NumPy数组每一个维度上的大小。上面例子中的数组是一维的,因此元组中只有一个元素。
     
    2.2 动手实践:创建多维数组
    既然我们已经知道如何创建向量,现在可以试着创建多维的NumPy数组,并查看其维度了。
    (1)创建一个多维数组。
    (2)显示该数组的维度。
    1. m=np.array([np.arange(2),np.arange(2)])
    2. m
    3. Out[23]:
    4. array([[0,1],
    5. [0,1]])
    6. m.shape
    7. Out[24]:(2,2)
    我们将arange函数创建的数组作为列表元素,把这个列表作为参数传给array函数,从而创建了一个2*2的数组,而且没有出现任何报错信息。

    array函数可以根据给定的对象生成数组。给定的对象应是类数组,如Python中的列表。

    在上面的例子中,我们传给array函数的对象是一个NumPy数组的列表。像这样的类型数组对象是array函数的唯一必要参数,其余的诸多参数均有默认值的可选参数。
     
     
    2.2.1 选取数组元素
    有时候,我们需要选取数组中的某个特定元素。首先还是创建一个2*2的多维数组。
    1. a=np.array([[1,2],[3,4]])
    2. a
    3. Out[34]:
    4. array([[1,2],
    5. [3,4]])
    在创建这个多维数组时,我们给array函数传递的对象是一个嵌套的列表。现在来依次选取该数组中的元素。记住,数组的下表是从0开始的。
    1. a
    2. Out[34]:
    3. array([[1,2],
    4. [3,4]])
    5. a[0]
    6. Out[35]: array([1,2])
    7. a[1]
    8. Out[36]: array([3,4])
    9. a[0,0]
    10. Out[37]:1
    11. a[0,1]
    12. Out[38]:2
    从数组中选取元素就是这么简单,对于数组a,只需要用a[m,n]选取各数组元素,其中m和n为元素下表,对应的位置如下表所示。
     
    2.2.2 NumPy数据类型
    Python支持的数据类型有:整型,浮点型以及复数型。
    但这些类型不足以满足科学计算的需求,因此NumPy添加了很多其他的数据类型。在实际应用中,我们需要不同精度的数据类型,它们占用的内容空间也是不同的。在NumPy中,大部分数据类型名是以数字结尾的,这个数字表示其在内存中所占用的位数。
    下面的表格列出了NumPy中支持的数据类型。
     每一种数据类型均有对应的类型转换函数:
    1. float(42)
    2. Out[39]:42.0
    3. int(42.0)
    4. Out[40]:42
    5. bool(42)
    6. Out[41]:True
    7. bool(0)
    8. Out[42]:False
    9. float(True)
    10. Out[43]:1.0
    11. float(False)
    12. Out[44]:0.0
    在NumPy中,许多函数的参数中可以指定数据类型,通常这个参数是可选的:
    1. np.arange(7)
    2. Out[55]: array([0,1,2,3,4,5,6])
    3. _.dtype
    4. Out[57]: dtype('int32')
    5. np.arange(9,dtype='int64')
    6. Out[58]: array([0,1,2,3,4,5,6,7,8], dtype=int64)
    需要注意的是,复数是不能和转换为整数的,这将触发TypeError错误。
    1. int(42.0+1.j)
    2. Traceback(most recent call last):
    3. File"<ipython-input-60-9e29587d355a>", line 1,in<module>
    4. int(42.0+1.j)
    5. TypeError: can't convert complex to int
    同样,复数也不能转换为浮点数。
    不过,浮点数却可以转换为复数,例如complex(1.0)。注意,有j的部分为复数的虚部。
     
    2.2.3 数据类型对象
    数据类型对象是np.dtype类的实例。
    如前所述,NumPy数组是有数据类型的,更确切地说,NumPy数组中的每一个元素均为相同的数据类型。
    数据类型对象可以给出单个数组元素在内存中占用的字节数,即dtype类的itemsize属性。
    1. a.dtype.itemsize
    2. Out[62]:4
     
    2.2.4 字符编码
    NumPy可以使用字符编码来表示数据类型,这是为了兼容NumPy的前身Numeric。
    我不推荐使用字符编码,但有时会用到,因此下面还是列出了字符编码的对应表。
    读者应该优先使用dtype对象来表示数据类型,而不是这些字符编码。
     下面的代码创建了一个单精度浮点数数组:
    1. np.arange(7,dtype='f')
    2. Out[64]: array([0.,1.,2.,3.,4.,5.,6.], dtype=float32)
    与此类似,还可以创建一个复数数组:
    1. np.arange(7,dtype='D')
    2. Out[65]: array([0.+0.j,1.+0.j,2.+0.j,3.+0.j,4.+0.j,5.+0.j,6.+0.j])
     
    2.2.5 自定义数据类型
    我们有很多种自定义数据类型的方法,以浮点型为例。
    可以使用Python中的浮点数类型。
    dype='float32'
    可以使用字符编码来指定单精度浮点数类型;
    可以使用字符编码来指定双精度浮点数类型。
    dtype='f'
    dtype='d'
     
    还可以将两个字符作为参数传给数据类型的构造函数。
    此时,第一个字符表示数据类型,第二个字符表示该类型在内容中占用的字节数(2,,8分别代表精度为16,32,64位的浮点数)
    1. np.arange(1,dtype='f8')
    2. Out[67]: array([0.])
    3. _.dtype
    4. Out[68]: dtype('float64')
     
    完整的NumPy数据类型列表可以在sctypeDict.keys()中找到:
    1. np.sctypeDict.keys()
    2. Out[70]: dict_keys(['?',0,'byte','b',1,'ubyte','B',2,'short','h',3,'ushort','H',4,'i',5,'uint','I',6,'intp','p',9,'uintp','P',10,'long','l',7,'L',8,'longlong','q','ulonglong','Q','half','e',23,'f',11,'double','d',12,'longdouble','g',13,'cfloat','F',14,'cdouble','D',15,'clongdouble','G',16,'O',17,'S',18,'unicode','U',19,'void','V',20,'M',21,'m',22,'bool8','Bool','b1','float16','Float16','f2','float32','Float32','f4','float64','Float64','f8','complex64','Complex32','c8','complex128','Complex64','c16','object0','Object0','bytes0','Bytes0','str0','Str0','void0','Void0','datetime64','Datetime64','M8','timedelta64','Timedelta64','m8','int32','uint32','Int32','UInt32','i4','u4','int64','uint64','Int64','UInt64','i8','u8','int16','uint16','Int16','UInt16','i2','u2','int8','uint8','Int8','UInt8','i1','u1','complex_','int0','uint0','single','csingle','singlecomplex','float_','intc','uintc','int_','longfloat','clongfloat','longcomplex','bool_','unicode_','object_','bytes_','str_','string_','int','float','complex','bool','object','str','bytes','a'])
     
    2.2.6 dtype类的属性
    dtype类有很多有用的属性。
    例如,我们可以获取数据类型的字符编码:
    1. t=np.dtype('float64')
    2. t.char
    3. Out[77]:'d'
    type属性对应于数组元素的数据类型:
    1. t.type
    2. Out[78]: numpy.float64
    str属性可以给出数据类型的字符串表示,该字符串的首个字符表示字节序(endianness),后面如果还有字符的话,将是一个字符编码,接着一个数字表示每个数组元素存储所需的字节数。
    这里,字节序是指位长尾32或64的字(word)存储的顺序,包括大端序(big-endian)和小端序(little-endian)。
    大端序是将最高位字节存储在最低的内存地址处,用>表示;
    小端序是将最低位字节存储在最低的内存地址处,用<表示:
    1. t.str
    2. Out[79]:'<f8'
     
     
    2.3 动手实践:创建自定义数据类型
    自定义数据类型是一种异构数据类型,可以当作用来记录电子表格或数据库中一行数据的结构。
    作为示例,我们将创建一个存储商店库存信息的数据类型。其中,我们用一个长度为40个字符的字符串来记录商品名称,用一个32位的整数来记录商品的库存数量,最后用一个32位的单精度浮点数来记录商品价格。
    下面是具体的步骤。
    (1)创建数据类型:
     
     
    (2)查看数据类型(也可以查看某一字段的数据类型):
     
     
     
     





  • 相关阅读:
    Android中没有插入SD情况下的文件写入和读取
    Android在OnCreate中获取控件的宽度和高度
    Android Adapter遇到的崩溃问题
    IIS Server Application Unavailable 解决方法
    Silverlight跨域访问WebService解决方法
    Silverlight 与 JS交互
    Dell 1440 黑苹果 (从10.6.3升级到10.6.8)
    Android控件系列之相册Gallery&Adapter适配器入门&控件缩放动画入门
    Android颜色编辑器的制作中遇到的问题
    马云讲给在工厂里工作的员工的话(转自qq)
  • 原文地址:https://www.cnblogs.com/zoe233/p/7026239.html
Copyright © 2020-2023  润新知