Numpy 科学计算库介绍
2017-03-02
安装 Numpy
pip install numpy
基本概念
NumPy提供了两种基本的对象:ndarray, ufunc
- ndarray 是存储单一数据类型的多维数组
- ufunc 是对数组进行处理的函数
基本使用
创建数组
多维 数组可以每个轴有一个索引。这些索引由一个逗号分割的元组给出
# 通过给array函数传递 Python 序列对象创建数组
# 如果传递的是多层嵌套的序列,将创建多维数组
>>> a = np.array([1,2,3,4,5,6])
>>> b = np.array([7,8,9,10])
>>> c = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]])
>>> c.dtype
dtype('int64')
# 数组元素的个数
>>> c.size
12
# 数组类型可以在创建时显示指定
>>> d = np.array( [ [1,2], [3,4] ], dtype=np.int)
# 使用索引访问数据
>>> d[0,0]
1
数组的纬度大小可以通过其shape属性获得
>>> a.shape
(6,)
>>> c.shape
(3, 4)
>>> c
array([[ 1, 2, 3, 4],
[ 4, 5, 6, 7],
[ 7, 8, 9, 10]])
还可以通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度
# c 的shape改为(4,3),从(3,4)改为(4,3)不是对数组进行转置,只是改变每个轴的大小
# 数组元素在内存中的位置并没有改变
>>> c.shape = 4, 3
array([[ 1, 2, 3],
[ 4, 4, 5],
[ 6, 7, 7],
[ 8, 9, 10]])
# 当某个轴的元素为-1时,根据数组元素的个数自动计算此轴的长度
# 因此下面的程序将数组 c 的shape改为了(2,6)
>>> c
array([[ 1, 2, 3, 4, 4, 5],
[ 6, 7, 7, 8, 9, 10]])
>>> c.shape
(2, 6)
使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变
>>> d = a.reshape((2,3))
>>> d
array([[1, 2, 3],
[4, 5, 6]])
>>> a
array([1, 2, 3, 4, 5, 6])
数组a和d其实共享数据存储内存区域,此修改其中一个数组的元素两个数组都会变
>>> a[1] = 100
>>> d
array([[ 1, 100, 3],
[ 4, 5, 6]])
其他创建数组的函数
# arange函数类似于python的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值:
>>> np.arange(0,1,0.1)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
# linspace函数通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值:
>>> np.linspace(0, 1, 12)
array([ 0. , 0.09090909, 0.18181818, 0.27272727, 0.36363636,
0.45454545, 0.54545455, 0.63636364, 0.72727273, 0.81818182,
0.90909091, 1. ])
# logspace函数和linspace类似,不过它创建等比数列,下面的例子产生1(10^0)到100(10^2)、有20个元素的等比数列:
>>> np.logspace(0, 2, 20)
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. ])
# 创建 0 的多维数组
>>> np.zeros( (3,4) )
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
# 创建 1 的数组
>>> a = np.ones(3, dtype=np.int32)
array([1, 1, 1], dtype=int32)
元素的存取
>>> a = np.arange(10)
# 用整数作为下标可以获取数组中的某个元素
>>> a[3]
3
# 用范围作为下标获取数组的一个切片,包括a[3]不包括a[5]
>>> a[3:5]
array([3, 4])
# 下标还可以用来修改元素的值
>>> a[2:4] = 100,101
使用下标范围获取的新的数组,得到的是原是数组的一个视图
它与原始数组共享同一块数据空间
# 通过下标范围产生一个新的数组b,b和a共享同一块数据空间
>>> b = a[3:7]
>>> b
array([101, 4, 5, 6])
# 将b的第2个元素修改为 -8
>>> b[2] = -8
>>> b
array([101, 4, -8, 6])
# a的第5个元素也被修改为 -8
>>> a
array([ 0, 1, 100, 101, 4, -8, 6, 7, 8, 9])
使用整数序列
当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标, 整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间
>>> x = np.arange(10,1,-1)
>>> x
array([10, 9, 8, 7, 6, 5, 4, 3, 2])
# 获取x中的下标为3, 3, 1, 8的4个元素,组成一个新的数组
>>> x[[3, 3, 1, 8]]
array([7, 7, 9, 2])
#下标可以是负数
>>> b = x[np.array([3,3,-3,8])]
>>> b[2] = 100
>>> b
array([7, 7, 100, 2])
# 由于b和x不共享数据空间,因此x中的值并没有改变
>>> x
array([10, 9, 8, 7, 6, 5, 4, 3, 2])
# 整数序列下标也可以用来修改元素的值
>>> x[[3,5,1]] = -1, -2, -3
>>> x
array([10, -3, 8, -1, 6, -2, 4, 3, 2])
使用布尔数组
使用布尔数组
作为下标存取数组中的元素,获得的数组不和原始数组共享数据空间
>>> x = np.arange(5,0,-1)
>>> x
array([5, 4, 3, 2, 1])
# 布尔数组中下标为0,2的元素为True,因此获取x中下标为0,2的元素
>>> x[np.array([True, False, True, False, False])]
array([5, 3])
# 如果是布尔列表,则把True当作1, False当作0,按照整数序列方式获取x中的元素
>>> x[[True, False, True, False, False]]
array([4, 5, 4, 5, 5])
# 布尔数组的长度不够时,不够的部分都当作False
>>> x[np.array([True, False, True, True])]
array([5, 3, 2])
# 布尔数组下标也可以用来修改元素
>>> x[np.array([True, False, True, True])] = -1, -2, -3
>>> x
array([-1, 4, -2, -3, 1])
ufunc 函数运算
一种能对数组的每个元素进行操作的函数,NumPy内置的许多ufunc函数都是在C语言级别实现的, 因此它们的计算速度非常快,例如:
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
# 速度差10倍
# math.sin: 0.0008650000000000047
# numpy.sin: 8.500000000000174e-05
reduce 函数
# 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
>>> np.add.reduce(range(10))
45
# 沿着 axis 1 累加
>>> np.add.reduce([range(10),range(10)], axis=1)
array([45, 45])
基本计算
>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
# 计算每一列和
>>> b.sum(axis=0)
array([12, 15, 18, 21])
# 每一行最小值
>>> b.min(axis=1)
array([0, 4, 8])
# 计算每一行累加和
>>> b.cumsum(axis=1)
array([[ 0, 1, 3, 6],
[ 4, 9, 15, 22],
[ 8, 17, 27, 38]])