title: NumPy-快速处理数据 create: 2016.12.7 modified: 2016.12.7 tags: python ndarray ufunc
7
[TOC]
标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3],需要有3个指针和三个整数对象。对于数值运算来说这种结构显然比较浪费内存和CPU计算时间。
此外Python还提供了一个array模块,array对象和列表不同,它直接保存数值,和C语言的一维数组比较类似。但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。
NumPy的诞生弥补了这些不足,NumPy提供了两种基本的对象:ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray(下文统一称之为数组)是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。
In [2]:
import numpy as np
a = np.array([1, 2, 3, 4])
c = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]])
c
Out[2]:
数组的大小可以通过其shape属性获得:
In [6]:
c.shape
Out[6]:
使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变:
In [7]:
d = a.reshape((2,2))
d
Out[7]:
In [8]:
a
Out[8]:
数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组的内容:
In [9]:
a[1] = 100
d
Out[9]:
数组的元素类型可以通过dtype属性获得。上面例子中的参数序列的元素都是整数,因此所创建的数组的元素类型也是整数,并且是32bit的长整型。可以通过dtype参数在创建时指定元素类型:
In [12]:
a.dtype
Out[12]:
In [11]:
b=np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.float)
b
Out[11]:
上面的例子都是先创建一个Python序列,然后通过array函数将其转换为数组,这样做显然效率不高。因此NumPy提供了很多专门用来创建数组的函数。下面的每个函数都有一些关键字参数,具体用法请查看函数说明。
In [14]:
np.arange(0, 1, 0.1)
Out[14]:
In [15]:
np.linspace(0, 1, 12)
Out[15]:
In [16]:
np.logspace(0, 2, 20)
Out[16]:
In [17]:
a = np.arange(10)
a[5]
Out[17]:
In [18]:
a[:5] # 省略开始下标,表示从a[0]开始
Out[18]:
和Python的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间:
In [20]:
b = a[3:7]
b
Out[20]:
In [22]:
b[2] = -10 # 将b的第2个元素修改为-10
a # a的第5个元素也被修改为-10
Out[22]:
In [33]:
a= np.arange(0, 60, 10).reshape(-1, 1)+ np.arange(0, 6)
a
Out[33]:
用于存取数组的下标和仍然是一个有两个元素的元组,元组中的每个元素都是整数序列,分别对应数组的第0轴和第1轴。从两个序列的对应位置取出两个整数组成下标: a[0,1], a[1,2], ..., a[4,5]。
In [34]:
a[(0,1,2,3,4),(1,2,3,4,5)]
Out[34]:
In [4]:
x = np.linspace(0, 2*np.pi, 10)
x
Out[4]:
In [5]:
y = np.sin(x) # 对数组x中的每个元素进行正弦计算,返回一个同样大小的新数组
y
Out[5]:
我用下面这个小程序,比较了一下numpy.math和Python标准库的math.sin的计算速度::
In [6]:
import time
import math
import numpy as np
x = [i * 0.001 for i in xrange(1000000)]
start = time.clock()
for i, t in enumerate(x):
x[i] = math.sin(t)
print "math.sin:", time.clock() - start
x = [i * 0.001 for i in xrange(1000000)]
x = np.array(x)
start = time.clock()
np.sin(x,x)
print "numpy.sin:", time.clock() - start
# 输出
# math.sin: 1.15426932753
# numpy.sin: 0.0882399858083
通过上面的例子我们了解了如何最有效率地使用math库和numpy库中的数学函数。因为它们各有长短,因此在导入时不建议使用*号全部载入,而是应该使用import numpy as np的方式载入,这样我们可以根据需要选择合适的函数调用。
In [7]:
a = np.arange(0,12,0.5).reshape(4,-1)
np.savetxt("a.txt", a) # 缺省按照'%.18e'格式保存数据,以空格分隔
np.loadtxt("a.txt")
Out[7]:
In [9]:
np.savetxt("a.txt", a, fmt="%d", delimiter=",") #改为保存为整数,以逗号分隔
np.loadtxt("a.txt",delimiter=",") # 读入的时候也需要指定逗号分隔
Out[9]:
In [ ]: