揭开Python科学计算的面纱

春牛春杖。无限春风来海上。便与春工。染得桃红似肉红。

春幡春胜。一阵春风吹酒醒。不似天涯。卷起杨花似雪花。

  标准的Python中用列表保存一组值,可以当做数组使用,但是由于其值类型任意,所以列表中保存的是指针,这样的话保存一个简单的列表,例如:[1,2,3]需要三个指针和三个对象。对于数值运算来说这样十分耗费内存和CPU。

  Python提供了array 模块,他所提供的array对象和列表不同,能直接保存数值和C语言的一维数组相似,但是他不支持多维数组,也没有各种运算函数,因此也不适合做数值运算。

  NumPy的诞生弥补了这些不足之处,NumPy提供了两种基本的对象:

  1. ndarray:英文全称n-dimensional array object ,他是储存单一数据类型的多维数组,后来统称为数组。
  2. ufunc:英文全称为universal function object , 他是一种能够对数组进行特殊处理的函数。

本文采用1.12版本

>>> import numpy as np
>>> np.__version__
‘1.12.0‘

ndarray对象



  Numpy中使用ndarray对象来表示数组,他是整个库的核心对象,NumPy中所有的函数都是围绕这ndarray对象展开处理的。ndarray的结构不复杂,但是功能十分强大,不但可以用它大量高效的储存数值元素,从而提高数组计算的运算速度,还可以用它和各种扩展库进行数据交换。

创建

  首先需要创建数组才能对其进行运算和操作。可以通过给array() , 函数传递Python的序列对象创建数组,如果传递的是多层嵌套的序列,将创建个多维数组:

>>> 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,0]])
>>> a
array([1, 2, 3, 4])
>>> b
array([5, 6, 7, 8])
>>> c
array([[1, 2, 3, 4],
       [4, 5, 6, 7],
       [7, 8, 9, 0]])
>>> a.shape                    # 查看数组的形状可以通过其 shape属性
(4,)
>>> b.shape
(4,)
>>> c.shape
(3, 4)

  数组a的shape属性只有一个元素是因为他是一维数组 . 而数组C的shape属性有两个元素, 是因为他是二维数组 . 其元素的排序是从高维到低维 . 我们还可以通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度.下面的例子讲数组c的shape属性改为(4,3), 注意从(3,4)到(4,3)不是对数组进行转置, 而是改变每个轴的大小,数组元素在内存中的位置没有变化

>>> c.shape = 4,3
>>> c
array([[1, 2, 3],
       [4, 4, 5],
       [6, 7, 7],
       [8, 9, 0]])

  你应该可以发现(4,3)和(3,4)总结起来不还是12个基本元素么 ? 我们改变总容量行不行 ?

>>> c.shape = 4,2
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    c.shape = 4,2
ValueError: cannot reshape array of size 12 into shape (4,2)
>>> c.shape = 4,5
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    c.shape = 4,5
ValueError: cannot reshape array of size 12 into shape (4,5)

  当我们设置某个轴的元素个数为 - 1 的时候, 讲自动计算此轴的长度 . 由于数组c有12个元素因此下面的程序讲c的shape属性改为(2,6):

>>> c.shape = 2,-1
>>> c
array([[1, 2, 3, 4, 4, 5],
       [6, 7, 7, 8, 9, 0]])
>>> c.shape
(2, 6)

  如果是三维数组我们设置两个 -1 呢 ?( 这个问题好像有点弱智 哈 )  发生错误:只能指定一个位置的维度

>>> c = np.array([[[1,2,3,4],[4,5,6,7],[7,8,9,0]],[[1,2,3,4],[4,5,6,7],[7,8,9,0]
]])
>>> c.shape
(2, 3, 4)
>>> c.shape = 3,-1,-1
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    c.shape = 3,-1,-1
ValueError: can only specify(指定) one unknown dimension(维度)

  使用数组的reshape方法, 可以创建指定形状的新数组, 而原数组的形状保持不变:

>>> a
array([1, 2, 3, 4])
>>> d = a.reshape((2,2))
>>> d
array([[1, 2],
       [3, 4]])

  汇编/C语言 中毒比较深的同学可能问了, 那么储存方式呢 ? 其实数组a和d是共享储存空间的,因此如果修改其中任意一个数组的元素都会同事修改另一个数组的内容, 注意在下面的例子中 , 数组d中的2也被改变成了100:(很好,很强大.)

>>> a
array([1, 2, 3, 4])
>>> d = a.reshape((2,2))
>>> d
array([[1, 2],
       [3, 4]])
>>> a[1]
2
>>> a[1] = 100
>>> a
array([  1, 100,   3,   4])
>>> d
array([[  1, 100],
       [  3,   4]])

元素类型

  数组的元素类型可以通过dtype来获得, 在前面的例子中, 创建数组所用到的序列的元素都是证书, 因此创建的数组的元素类型也都是整数, 我用的是Ubuntu64位, 所以我显示的类型是int类型64位, 如果你的是32 位可能你用的是32位的系统.

>>> c
array([[1, 2, 3, 4, 4, 5],
       [6, 7, 7, 8, 9, 0]])
>>> c.dtype
dtype(‘int64‘)

  如果有编译器有代码提示的同学可能就会发现, 那个dtype了, 在没有介绍前面的东西的时候你可能还以为这是个什么鬼 ? 现在应该知道他是用于指定元素类型用的了吧?

>>> ai32 = np.array(
┌──────────────────────────────────────────────────────────────┐
│ np.array: (object, dtype=None, copy=True, order=‘K‘,         │
│ subok=False, ndmin=0)                                        │
│ array           array2string    array_equal                  │
│ array_equiv     array_repr      array_split                  │
│ array_str                                                    │
│ array(object, dtype=None, copy=True, order=‘K‘, subok=False, │
│  ndmin=0)                                                    │
│                                                              │
│ Create an array.                                             │
│                                                              │
│ Parameters                                                   │
│ ----------                                                   │
│ object : array_like                                          │
│     An array, any object exposing the array interface, an ob │
│ ject whose                                                   │
│     __array__ method returns an array, or any (nested) seque │
│ nce.                                                         │
│ dtype : data-type, optional                                  │
└──────────────────────────────────────────────────────────────┘
>>> ai32 = np.array([1,2,3,4],dtype = np.int32)
>>> ai32
array([1, 2, 3, 4], dtype=int32)
>>> ai32.shape
(4,)
>>> af = np.array([1,2,3,4],dtype = np.float)
>>> af
array([ 1.,  2.,  3.,  4.])
>>> ac = np.array([1,2,3,4],dtype = np.complex)
>>> ac
array([ 1.+0.j,  2.+0.j,  3.+0.j,  4.+0.j])
>>> ac.shape
(4,)>>> ai32.dtypedtype(‘int32‘)>>> af.dtypedtype(‘float64‘)>>> ac.dtypedtype(‘complex128‘)

  在上面的例子中传递给dtype参数的都是类型对象, 其中类型对象都是NumPy定义的数据类型. 当然内置的也有并且其效果和内置的相同.

  在需要指定dtype参数的时候, 也可以传递一个字符串来表示元素的数值类型. NumPy中每个数值类型都有集中字符串的表达方式, 字符串和类型之间的对用关系都储存在typeDict字典中,下面的程序获得与float64类型对应的所有键值.

>>> [key for key, value in np.typeDict.items() if value is np.float64]
[12, ‘d‘, ‘float_‘, ‘float‘, ‘double‘, ‘Float64‘, ‘f8‘, ‘float64‘]

  好吧翻译一下.

>>> for key,value in np.typeDict.items():
...     if value is np.float64:
...         value,key
...
...
...
(<class ‘numpy.float64‘>, 12)
(<class ‘numpy.float64‘>, ‘d‘)
(<class ‘numpy.float64‘>, ‘float_‘)
(<class ‘numpy.float64‘>, ‘float‘)
(<class ‘numpy.float64‘>, ‘double‘)
(<class ‘numpy.float64‘>, ‘Float64‘)
(<class ‘numpy.float64‘>, ‘f8‘)
(<class ‘numpy.float64‘>, ‘float64‘)

  完整的类型列表可以通过下面的语句获得, 他讲typeDict字典中的所有值转化为一个集合,从而去除重复项. ( 重复项 值只有这么多, 但是一个值可以有很多个键. )

>>> set(np.typeDict.values())
{<class ‘numpy.float128‘>, <class ‘numpy.uint64‘>, <class ‘numpy.int64‘>, <class
 ‘numpy.str_‘>, <class ‘numpy.complex128‘>, <class ‘numpy.float64‘>, <class ‘num
py.uint32‘>, <class ‘numpy.int32‘>, <class ‘numpy.bytes_‘>, <class ‘numpy.comple
x64‘>, <class ‘numpy.float32‘>, <class ‘numpy.uint16‘>, <class ‘numpy.int16‘>, <
class ‘numpy.bool_‘>, <class ‘numpy.timedelta64‘>, <class ‘numpy.float16‘>, <cla
ss ‘numpy.uint8‘>, <class ‘numpy.int8‘>, <class ‘numpy.object_‘>, <class ‘numpy.
datetime64‘>, <class ‘numpy.uint64‘>, <class ‘numpy.int64‘>, <class ‘numpy.void‘
>, <class ‘numpy.complex256‘>}

  上面显示的数值类型与数组的dtype属性是不同的对象. 通过dtype 对象的type属性可以获得与之对应的数值类型.

>>> c.dtype   # 我的理解是这里的int64 指的是数组中的元素是 int64储存的
dtype(‘int64‘)
>>> c.dtype.type  # 这里应该是数组本身是按照 numpy.int64的方式储存的 , 不知道对不对, 如果不对我会回来修改的.
<class ‘numpy.int64‘>

  通过NumPy的数值类型也可以创建数值对象, 下面创建一个16位的符号整数对象, 它与Python的整数对象不同的是,他的取值范围有限, 因此计算200*200 会溢出,得到一个负数.

>>> a = np.int16(200)
>>> a*a
__console__:1: RuntimeWarning: overflow encountered in short_scalars
-25536
>>> a+a
400

  另外值得指出的是, NumPy的数值对象的运算速度比Python的内置类型的运算速度慢的很多, 如果程序中需要大量的对单个数值进行计算, 应当避免使用NumPy的数值对象. 使用astype()方法可以对数组的元素类型进行转换.

>>> t1 = np.array([1,2,3,4.0],dtype = np.float64)
>>> t2 = np.array([1,2,3,4],dtype = np.complex)
>>> t3 = t1.astype(np.int64)
>>> t4 = t2.astype(np.complex256)
>>> t1.dtype
dtype(‘float64‘)
>>> t2.dtype
dtype(‘complex128‘)
>>> t3.dtype
dtype(‘int64‘)
>>> t4.dtype
dtype(‘complex256‘)
>>> t4.dtype.type
<class ‘numpy.complex256‘>
时间: 2024-11-06 11:16:57

揭开Python科学计算的面纱的相关文章

Python科学计算之Pandas

Reference: http://mp.weixin.qq.com/s?src=3&timestamp=1474979163&ver=1&signature=wnZn1UtWreFWjQbpWweZXp6RRvmmKwW1-Kud3x6OF0czmyPqv*F6KzQ1i-dKhi4D-QvDjp1mFDdqAHLPrCLgMOb1KXJcbbkU5-QAREDarkCaPumjQlORzVAOma541S0X2MGgysuH18DI2567rBcTSkMHPsVf6sxClfB

windows下安装python科学计算环境,numpy scipy scikit等

背景: 目的:要用Python下的DBSCAN聚类算法. scikit-learn 是一个基于SciPy和Numpy的开源机器学习模块,包括分类.回归.聚类系列算法,主要算法有SVM.逻辑回归.朴素贝叶斯.Kmeans.DBSCAN等,目前由INRI 资助,偶尔Google也资助一点. SciPy是一个开源的Python算法库和数学工具包,SciPy包含的模块有最优化.线性代数.积分.插值.特殊函数.快速傅里叶变换.信号处理和图像处理.常微分方程求解和其他科学与工程中常用的计算.其功能与软件MA

python科学计算

windows下python科学计算库的下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/(由于C运行库的问题,scipy在linux下可以用pip安装,而windows下不行) matpoltlib:绘图 numpy:矩阵运算 scipy:科学计算,高阶抽象和物理模型 sklearn:科学计算,多种聚类算法. 数据拟合:http://blog.csdn.net/lsldd/article/details/41251583 遗传算法:http://bl

Python科学计算(二)windows下开发环境搭建(当用pip安装出现Unable to find vcvarsall.bat)

用于科学计算Python语言真的是amazing! 方法一:直接安装集成好的软件 刚开始使用numpy.scipy这些模块的时候,图个方便直接使用了一个叫做Enthought的软件.Enthought是一家位于美国得克萨斯州首府奥斯汀的软件公司,主要使用Python从事科学计算工具的开发.Enthought里面包含了很多库,不需要你自己安装就可以直接使用了. 其实还又很多Python科学计算的集成软件,比如Python(x, y)和WinPython,个人感觉WinPython还是不错的,里面包

linux中安装python科学计算环境-numpy、scipy、matplotlib、OpenCV...

http://blog.csdn.net/pipisorry/article/details/39902327 在Ubuntu中安装numpy.scipy.matplotlib.OpenCV等 和Python(x,y)不一样,在Ubuntu中需要手工安装科学计算的各个模块, 如何安装IPython, NumPy, SciPy, matplotlib, PyQt4, Spyder, Cython, SWIG, ETS, OpenCV: 在Ubuntu下安装Python模块通常可以使用apt-get

目前比较流行的Python科学计算发行版

经常有身边的学友问到用什么Python发行版比较好? 其实目前比较流行的Python科学计算发行版,主要有这么几个: Python(x,y) GUI基于PyQt,曾经是功能最全也是最强大的,而且是Windows系统中科学免费Python发行版的不二选择.不过今时已不同往昔! PythonXY里面的许多包为了兼容性的问题,无法使用最新的程序包.尤其是令人气愤的是MinGW到现在还是古董级的4.5版本,而TDM-GCC现在都4.8.1-3了.不过这个包在你安装了之后,除了占用较大的磁盘空间之外,基本

Python科学计算(两)——时域波形和正弦信号的频谱

Python科学计算(两)-- 时域和频域波形为正弦波形信号生成.计算和显示 # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as pl import matplotlib import math import random row = 4 col = 4 N = 500 fs = 5 n = [2*math.pi*fs*t/N for t in range(N)] axis_x = np.linspace(

Python科学计算函数库介绍

数值计算库 NumPy为Python提供了快速的多维数组处理的能力,而SciPy则在NumPy基础上添加了众多的科学计算所需的各种工具包,有了这两个库,Python就有几乎和Matlab一样的处理数据和计算的能力了. NumPy和SciPy官方网址: http://www.scipy.org NumPy为Python带来了真正的多维数组功能,并且提供了丰富的函数库处理这些数组.它将常用的数学函数都进行数组化,使得这些数学函数能够直接对数组进行操作,将本来需要在Python级别进行的循环,放到C语

Mac OS X中搭建Python科学计算环境

这个日志也是参考了几位网友的经验(例如这篇日志:http://blog.csdn.net/waleking/article/details/7578517).他们推荐使用Mac Ports这样的软件来管理和安装所有的安装包.按照这里的教程:http://www.macports.org/install.php,需要首先安装Xcode,如果下载网速不好的话,使用浏览器下载可能需要数个小时.这里建议国内的朋友试试迅雷之类的离线下载,可以加速很多.安装好Mac Ports之后,在终端中输入: port