第1章 NumPy快速入门
让我们开始吧。首先,我们将介绍如何在不同的操作系统中安装NumPy和相关软件,并给出使用NumPy的简单示例代码。然后,我们将简单介绍IPython(一种交互式shell工具)。如前言所述,SciPy和NumPy有着密切的联系,因此你将多次看到SciPy的身影。在本章的末尾,我们将告诉你如何利用在线资源,以便你在受困于某个问题或不确定最佳的解题方法时,可以在线获取帮助。
本章涵盖以下内容:
在Windows、Linux和Macintosh操作系统上安装Python、SciPy、Matplotlib、IPython和NumPy;
编写简单的NumPy代码;
了解IPython;
浏览在线文档和相关资源。
1.1Python
NumPy是基于Python的,因此在安装NumPy之前,我们需要先安装Python。某些操作系统已经默认安装有Python环境,但你仍需检查Python的版本是否与你将要安装的NumPy版本兼容。Python有很多种实现,包括一些商业化的实现和发行版。在本书中,我们将使用CPython 实现,从而保证与NumPy兼容。
1.2动手实践:在不同的操作系统上安装Python
NumPy在Windows、各种Linux发行版以及Mac OS X上均有二进制安装包。如果你愿意,也可以安装包含源代码的版本。你需要在系统中安装Python 2.4.x或更高的版本。我们将给出在以下操作系统中安装Python的各个步骤。
(1) Debian和Ubuntu Debian和Ubuntu可能已经默认安装了Python,但开发者包(development headers) 一般不会默认安装。在Debian和Ubuntu中安装python和python-dev的命令如下:
sudo apt-get install python
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:
sudo port install python27
LAPACK并不是必需的,但如果需要,NumPy在安装过程中将检测并使用之。我们推荐大家安装LAPACK以便应对海量数据的计算,因为它拥有高效的线性代数计算模块。
刚才做了些什么
我们在Debian、Ubuntu、Windows和Mac操作系统中安装了Python。
. 1.3Windows
在Windows上安装NumPy是很简单的。你只需要下载安装程序,运行后在安装向导的指导下完成安装。
1.4动手实践:在Windows上安装NumPy、Matplotlib、SciPy和IPython
在Windows上安装NumPy是必需的,但幸运的是,安装过程并不复杂,我们将在下面详细阐述。建议你安装Matplotlib、SciPy和IPython,虽然这一操作对于使用本书不是必需的。我们将按照如下步骤安装这些软件。
(1) 从SourceForge网站下载NumPy的Windows安装程序:
http://sourceforge.net/projects/numpy/files/
请选择合适的版本。在上图中,我们选择了numpy-1.7.0-win32-superpack-python2.7.exe。
(2) 下载完成后,双击运行安装程序。
(3) 现在,我们可以看到一段对NumPy的描述以及其特性,如上图所示。单击Next(下一步)按钮以继续安装。
(4) 如果你已经安装了Python,NumPy的安装程序应该能自动检测到。如果没有检测到Python,可能是你的路径设置有误。在本章的末尾,我们列出了一些在线资源,供安装NumPy时遇到问题的读者参考。
(5) 在上图中,安装程序成功检测到系统中已安装Python 2.7,此时应单击Next按钮继续安装;否则,请单击Cancel(取消)按钮并安装Python(NumPy不能脱离Python单独安装)。继续单击Next按钮,从这一步起就不能回退到上一步了,因此请你确认是否选择了合适的安装路径和其他安装选项。现在,真正的安装过程开始了,你需要等待一段时间。
(6) SciPy和Matplotlib可以通过Enthough安装,地址为www.enthought.com/products/epd.php。在安装过程中,你可能需要将一个文件msvcp71.dll放到目录C:\Windows\system32下。你可以从这里下载这个文件:www.dll-files.com/dllindex/dll-files.shtml?msvcp71。Windows下的IPython安装程序可以通过访问IPython的官网下载:http://ipython.scipy.org/Wiki/IpythonOnWindows。
刚才做了些什么
我们在Windows上安装了NumPy、SciPy、Matplotlib以及IPython。
1.5Linux
在Linux上安装NumPy和相关软件的方法取决于具体使用的Linux发行版。我们将用命令行的方式安装NumPy,不过你也可以使用图形界面安装程序,这取决于具体的Linux发行版。除了软件包的名字不一样,安装Matplotlib、SciPy和IPython的命令与安装NumPy时是完全一致的。这几个软件包不是必需安装的,但这里建议你也一并安装。
1.6动手实践:在Linux上安装NumPy、Matplotlib、SciPy和IPython
大部分Linux发行版都有NumPy的软件包。我们将针对一些流行的Linux发行版给出安装步骤。
(1) 要在Red Hat上安装NumPy,请在命令行中执行如下命令:
yum install python-numpy
(2) 要在Mandriva上安装NumPy,请在命令行中执行如下命令:
urpmi python-numpy
(3) 要在Gentoo上安装NumPy,请在命令行中执行如下命令:
sudo emerge numpy
(4) 要在Debian或Ubuntu上安装NumPy,请在命令行中执行如下命令:
sudo apt-get install python-numpy
下表给出了各Linux发行版中相关软件包的名称以供参考。
Linux发行版NumPySciPyMatplotlibIPython
Arch Linuxpython-numpypython-scipypython-matplotlibipython
Debianpython-numpypython-scipypython-matplotlibipython
Fedoranumpypython-scipypython-matplotlibipython
Gentoodev-python/numpyscipymatplotlibipython
OpenSUSEpython-numpy,python-numpy-develpython-scipypython-matplotlibipython
Slackwarenumpyscipymatplotlibipython
刚才做了些什么
我们在各种Linux发行版上安装了NumPy、SciPy、Matplotlib以及IPython。
1.7Mac OS X
在Mac上,你可以通过图形用户界面或者命令行来安装NumPy、Matplotlib和SciPy,根据自己的喜好选择包管理工具,如MacPorts或Fink等。
1.8动手实践:在Mac OS X上安装NumPy、Matplotlib和SciPy
我们将使用图形用户界面安装程序,安装步骤如下所示。
(1) 我们先从SourceForge页面下载NumPy的安装程序,地址为http://sourceforge.net/projects/ numpy/files/。Matplotlib和SciPy也可以用类似的方式下载,只需将前面URL中的numpy修改为scipy或matplotlib。在我写作本书的时候,IPython还没有提供图形界面的安装程序。如下面的截图所示,请单击下载合适的DMG文件,且通常要选择最新版本的文件。
(2) 打开下载的DMG文件(示例中为numpy-1.7.0-py2.7-python.org-macosx10.6.dmg),如下图所示。
在打开的窗口中,双击那个下方文字以.mpkg结尾的图标,我们将看到安装程序的欢迎界面。
单击Continue(继续)按钮进入Read Me(自述页)界面,我们将看到一小段NumPy的描述文字,如下图所示 。
单击Continue按钮,可以看到关于软件许可协议的说明。
(3) 阅读软件许可协议,单击Continue按钮,在被提示是否接受协议时单击Accept(同意)按钮。继续安装,最后单击Finish(完成)按钮结束安装。
刚才做了些什么
我们在Mac OS X上用图形用户界面安装程序安装了NumPy。SciPy和Matplotlib的安装步骤与之很类似,使用上面第(1)步中提到的URL进行下去即可。
1.9动手实践:使用MacPorts或Fink安装NumPy、SciPy、Matplotlib和IPython
我们也可以选择另外一种安装方式,即使用MacPorts或Fink来安装NumPy、SciPy、Matplotlib以及IPython。下面给出的安装步骤将安装所有这些软件包。在本书中只有NumPy是必需的,如果你对其他软件包不感兴趣,也可以暂不安装。
(1) 输入以下命令,从MacPorts安装这些软件包:
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。执行如下命令,我们来安装基于Python 2.6的NumPy以及其他推荐安装的软件包:
fink install scipy-core-py26 scipy-py26 matplotlib-py26
刚才做了些什么
我们在Mac OS X上使用MacPorts和Fink安装了NumPy以及其他推荐安装的软件包。
1.10编译源代码
NumPy的源代码可以使用git获取,如下所示:
git clone git://github.com/numpy/numpy.git numpy
使用如下命令将NumPy安装至/usr/local:
python setup.py build
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代码可以解决上述问题:
def pythonsum(n):
a = range(n)
b = range(n)
c = []
for i in range(len(a)):
a[i] = i ** 2
b[i] = i ** 3
c.append(a[i] + b[i])
return c
(2) 以下是使用NumPy的代码,它同样能够解决问题:
def numpysum(n):
a = numpy.arange(n) ** 2
b = numpy.arange(n) ** 3
c = a + b
return c
注意,numpysum()函数中没有使用for循环。同时,我们使用NumPy中的arange函数来创建包含0~n 的整数的NumPy数组。代码中的arange函数前面有一个前缀numpy,表明该函数是从NumPy模块导入的。
下面我们做一个有趣的实验。在前言部分我们曾提到,NumPy在数组操作上的效率优于纯Python代码。那么究竟快多少呢?接下来的程序将告诉我们答案,它以微秒(10?6 s)的精度分别记录下numpysum()和pythonsum()函数的耗时。这个程序还将输出加和后的向量最末的两个元素。让我们来看看纯Python代码和NumPy代码是否得到相同的结果:
#!/usr/bin/env/python
import sys
from datetime import datetime
import numpy as np
"""
本书第1章
该段代码演示Python中的向量加法
使用如下命令运行程序:
python vectorsum.py n
n为指定向量大小的整数
加法中的第一个向量包含0到n的整数的平方
第二个向量包含0到n的整数的立方
程序将打印出向量加和后的最后两个元素以及运行消耗的时间
"""
def numpysum(n):
a = np.arange(n) ** 2
b = np.arange(n) ** 3
c = a + b
return c
def pythonsum(n):
a = range(n)
b = range(n)
c = []
for i in range(len(a)):
a[i] = i ** 2
b[i] = i ** 3
c.append(a[i] + b[i])
return c
size = int(sys.argv[1])
start = datetime.now()
c = pythonsum(size)
delta = datetime.now() - start
print "The last 2 elements of the sum", c[-2:]
print "PythonSum elapsed time in microseconds", delta.microseconds
start = datetime.now()
c = numpysum(size)
delta = datetime.now() - start
print "The last 2 elements of the sum", c[-2:]
print "NumPySum elapsed time in microseconds", delta.microseconds
程序在向量元素个数为1000、2000和3000时的输出分别为:
$ python vectorsum.py 1000
The last 2 elements of the sum [995007996, 998001000]
PythonSum elapsed time in microseconds 707
The last 2 elements of the sum [995007996 998001000]
NumPySum elapsed time in microseconds 171
$ python vectorsum.py 2000
The last 2 elements of the sum [7980015996, 7992002000]
PythonSum elapsed time in microseconds 1420
The last 2 elements of the sum [7980015996 7992002000]
NumPySum elapsed time in microseconds 168
$ python vectorsum.py 4000
The last 2 elements of the sum [63920031996, 63968004000]
PythonSum elapsed time in microseconds 2829
The last 2 elements of the sum [63920031996 63968004000]
NumPySum elapsed time in microseconds 274
如果你是www.packtpub.com的用户并从那里购买了图书,可以从网站上下载配套的示例代码。如果你是在别处购买了本书,可以访问www.packtpub.com/ support进行登记,我们会直接将示例代码文件以邮件形式发送给你。
刚才做了些什么
显然,NumPy代码比等价的纯Python代码运行速度快得多。有一点可以肯定,即不论我们使用NumPy还是Python,得到的结果是一致的。不过,两者的输出结果在形式上有些差异。注意,numpysum()函数的输出不包含逗号。这是为什么呢?显然,我们使用的是NumPy数组,而非Python自身的list容器。正如前言中所述,NumPy数组对象以专用数据结构来存储数值。我们将在下一章中详细介绍NumPy数组对象。
突击测验:arange函数的功能
问题1arrange(5)的作用是什么?
(1) 创建一个包含5个元素的Python列表(list),取值分别为1~5的整数
(2) 创建一个包含5个元素的Python列表,取值分别为0~4的整数
(3) 创建一个包含5个元素的NumPy数组,取值分别为1~5的整数
(4) 创建一个包含5个元素的NumPy数组,取值分别为0~4的整数
(5) 以上都不对
勇敢出发:进一步分析
我们用来比较NumPy和常规Python代码运行速度的程序不是特别严谨,如果将相同的实验重复多次并计算相应的统计量(如平均运行时间等)会更科学。你可以把实验结果绘制成图表,并展示给你的好友和同事。
我们在本章的最后给出了一些在线文档和相关资源,你可以在线获取帮助。顺便提一下,NumPy中的统计函数可以帮你计算平均数。建议你使用Matplotlib绘图。(第9章概述了Matplotlib。)
1.13IPython:一个交互式shell工具
科学家和工程师都喜欢做实验,而IPython正是诞生于爱做实验的科学家之手。IPython提供的交互式实验环境被很多人认为是Matlab、Mathematica和Maple的开源替代品。你可以在线获取包括安装指南在内的更多信息,地址为http://ipython.org/。
IPython是开源免费的软件,可以在Linux、Unix、Mac OS X以及Windows上使用。IPython的作者们希望那些用到IPython的科研工作成果在发表时能够提到IPython,这是他们对IPython使用者唯一的要求。下面是IPython的基本功能:
Tab键自动补全;
历史记录存档;
行内编辑;
使用%run可以调用外部Python脚本;
支持系统命令;
支持pylab模式;
Python代码调试和性能分析。
在pylab模式下,IPython将自动导入SciPy、NumPy和Matplotlib模块。如果没有这个功能,我们只能手动导入每一个所需模块。
而现在,我们只需在命令行中输入如下命令:
$ ipython --pylab
Python 2.7.2 (default, Jun 20 2012, 16:23:33)
Type "copyright", "credits" or "license" for more information.
IPython 0.14.dev -- An enhanced Interactive Python.
? -) Introduction and overview of IPython's features.
%quickref -) Quick reference.
help-) Python's own help system.
object? -) Details about 'object', use 'object??' for extra details.
Welcome to pylab, a matplotlib-based Python environment [backend: MacOSX].
For more information, type 'help(pylab)'.
In [1]: quit()
使用quit()函数或快捷键Ctrl+D均可以退出IPython shell。有时我们想要回到之前做过的实验,IPython可以便捷地保存会话以便稍后使用。
In [1]: %logstart
Activating auto-logging. Current session state plus future input saved.
Filename : ipython_log.py
Mode : rotate
Output logging : False
Raw input log: False
Timestamping : False
State: active
举例来说,我们将之前的向量加法程序放在当前目录下,可以按照如下方式运行脚本:
In [1]: ls
READMEvectorsum.py
In [2]: %run -i vectorsum.py 1000
你可能还记得,这里的1000是指向量中元素的数量。%run的–d参数将开启ipdb调试器,键入c后,脚本就开始逐行执行了(如果脚本有n行,就一共执行n步直到代码结束)。在ipdb提示符后面键入quit可以关闭调试器。
In [2]: %run -d vectorsum.py 1000
*** Blank or comment
*** Blank or comment
Breakpoint 1 at: /Users/.../vectorsum.py:3
在ipdb)提示符后面键入c,从而开始运行代码。
)(string)(1)(module)()
ipdb) c
) /Users/.../vectorsum.py(3)(module)()
2
1---) 3 import sys
4 from datetime import datetime
ipdb) n
)
/Users/.../vectorsum.py(4)(module)()
1 3 import sys
----) 4 from datetime import datetime
5 import numpy
ipdb) n
) /Users/.../vectorsum.py(5)(module)()
4 from datetime import datetime
----) 5 import numpy
6
ipdb) quit
我们还可以使用%run的–p参数对脚本进行性能分析。
In [4]: %run -p vectorsum.py 1000
1058 function calls (1054 primitive calls) in 0.002 CPU seconds
Ordered by: internal time
ncallstottimepercallcumtimepercallfilename:lineno(function)
1 0.0010.0010.0010.001 vectorsum.py:28(pythonsum)
1 0.0010.0010.0020.002 {execfile}
1000 0.0000.0000.0000.000{method "append" of 'list' objects}
1 0.0000.000 0.0020.002 vectorsum.py:3((module))
1 0.0000.0000.0000.000vectorsum.py:21(numpysum)
30.0000.0000.0000.000{range}
10.0000.0000.0000.000arrayprint.py:175(_array2string)
3/10.0000.0000.0000.000 arrayprint.py:246(array2string)
20.0000.0000.0000.000{method 'reduce' of 'numpy.ufunc' objects}
40.0000.0000.0000.000{built-in method now}
20.0000.0000.0000.000arrayprint.py:486(_formatlnteger)
20.0000.0000.0000.000{numpy.core.multiarray.arange}
10.0000.0000.0000.000arrayprint.py:320(_formatArray)
3/10.0000.0000.0000.000 numeric.py:1390(array_str)
10.0000.0000.0000.000numeric.py:216(asarray)
20.0000.0000.0000.000arrayprint.py:312(_extendLine)
10.0000.0000.0000.000fromnumeric.py:1043(ravel)
20.0000.0000.0000.000arrayprint.py:208((lambda))
10.0000.0000.0020.002(string):1((module))
110.0000.0000.0000.000 {len}
20.0000.0000.0000.000{isinstance}
10.0000.0000.0000.000{reduce}
10.0000.0000.0000.000{method 'ravel' of 'numpy.ndarray' objects}
40.0000.0000.0000.000{method 'rstrip' of 'str' objects}
30.0000.0000.0000.000{issubclass}
20.0000.0000.0000.000{method 'item' of 'numpy.ndarray' objects}
10.0000.0000.0000.000{max}
10.0000.0000.0000.000{method 'disable' of ' lsprof.Profiler'
objects}
根据性能分析的结果,可以更多地了解程序的工作机制,并能够据此找到程序的性能瓶颈。使用%hist命令可以查看命令行历史记录。
In [2]: a=2+2
In [3]: a
Out[3]: 4
In [4]: %hist
1: _ip.magic("hist ")
2: a=2+2
3: a
通过前面的介绍,希望你也认为IPython是非常有用的工具了!
1.14在线资源和帮助
在IPython的pylab模式下,我们可以使用help命令打开NumPy函数的手册页面。你并不需要知道所有函数的名字,因为可以在键入少量字符后按下Tab键进行自动补全。例如,我们来查看一下arange函数的相关信息。
In [2]: help ar(Tab)
In [2]: help arange
另一种方法是在函数名后面加一个问号:
In [3]: arange?
可以访问http://docs.scipy.org/doc/查看NumPy和SciPy的在线文档。在这个网页上,你可以访问http://docs.scipy.org/doc/numpy/reference/浏览NumPy的参考资料、用户指南以及一些使用教程。
NumPy的wiki站点上也有许多相关文档可供参考:http://docs.scipy.org/numpy/Front%20Page/。
NumPy和SciPy的论坛地址为http://ask.scipy.org/en。
广受欢迎的开发技术问答网站Stack Overflow上有成百上千的提问被标记为numpy相关问题。你可以到这里查看这些问题:http://stackoverflow.com/questions/tagged/numpy。
如果你确实被某个问题困住了,或者想了解NumPy开发的最新进展,可以订阅NumPy的讨论组邮件列表,电子邮件地址为numpy-discussion@scipy.org。每天的邮件数量不会太多,并且基本不会讨论无意义的事情。最重要的是,NumPy的活跃开发者们也愿意回答讨论组里提出的问题。完整的邮件列表可以在这里找到:www.scipy.org/Mailing_Lists。
对于IRC 的用户,可以查看irc.freenode.net上的IRC频道。尽管该频道的名称是#scipy,但你也可以提出NumPy的问题,因为SciPy是基于NumPy的,SciPy的用户也了解NumPy的知识。SciPy频道上至少会有50人同时在线。
1.15本章小结
在本章中,我们安装了NumPy以及其他推荐软件。我们成功运行了向量加法程序,并以此证明了NumPy优异的性能。随后,我们介绍了交互式shell工具IPython。此外,我们还列出了供你参考的NumPy文档和在线资源。
在下一章中,我们将深入了解NumPy中的一些基本概念,包括数组和数据类型。