python之numpy库详解

NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多。

ndarray中的所有元素的类型都是相同的,而Python列表中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而python原生list就只能通过寻址方式找到下一个元素,这虽然也导致了在通用性能方面Numpy的ndarray不及Python原生list,但在科学计算中,Numpy的ndarray就可以省掉很多循环语句,代码使用方面比Python原生list简单的多。numpy内置了并行运算功能,当系统有多个核心时,做某种计算时,numpy会自动做并行计算。Numpy底层使用C语言编写,数组中直接存储对象,而不是存储对象指针,所以其运算效率远高于纯Python代码

一.基本操作

使用前一定要先导入 Numpy 包 import numpy as np

1.生成数组

  • arange()函数

arange类似于Python中的 range 函数,只不过返回的不是列表,而是数组,arange(start, stop=None, step=1, dtype=None)产生一个在区间 [start, stop) 之间,以 step 为间隔的数组,如果只输入一个参数,则默认从 0 开始,并以这个值为结束.

range 不同, arange 允许非整数值输入,产生一个非整型的数组

np.arange(4) #array([0, 1, 2, 3])
  • linspace()函数

linspace(start, stop, N),产生 N 个等距分布在 [start, stop]间的元素组成的数组,包括 start, stop

  • logspace()函数

logspace(start, stop, N),产生 N 个对数等距分布的数组,默认以10为底

  • meshgrid()函数

有时候需要在二维平面中生成一个网格,这时候可以使用 meshgrid 来完成

ogrid 相当于 meshgrid(indexing='ij', sparse=True)

mgrid 相当于 meshgrid(indexing='ij', sparse=False)

其中Numpy 使用的是 start:end:step 的表示且这里的结果不包括 end 的值

为了包含 end 的值,我们可以使用这样的技巧:

#在 step 的位置传入一个复数 5j ,表示我们需要一个 5 个值的数组,此时返回值就会包含 end
x, y = np.ogrid[-1:1:5j, -1:1:5j]
(array([[-1. ],
        [-0.5],
        [ 0. ],
        [ 0.5],
        [ 1. ]]), array([[-1. , -0.5,  0. ,  0.5,  1. ]]))
  • r_,c_函数
np.r_[0:1:.1] #array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])
np.r_[0:1:5j] #array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ])
np.r_[(3,22,11), 4.0, [15, 6]] #array([  3.,  22.,  11.,   4.,  15.,   6.])

列向量:

np.c_[1:3:5j]  #array([[ 1. ],[ 1.5],[ 2. ],[ 2.5],[ 3. ]])
  • one_like(),zero_like()函数
a = np.arange(0, 10, 2.5)
np.empty_like(a)
np.zeros_like(a)
np.ones_like(a)
  • identity()
np.identity(3) #产生一个 n 乘 n 的单位矩阵

2.矩阵

numpy基本类型为 ndarray,但提供了支持矩阵操作的类 matrix

mat方法

a = np.array([[1,2,4],[2,5,3], [7,8,9]])
A = np.mat(a)   #matrix([[1, 2, 4],[2, 5, 3],[7, 8, 9]])
#A = np.mat('1,2,4;2,5,3;7,8,9')
a = np.array([[ 1, 2],
              [ 3, 4]])
b = np.array([[10,20], 
              [30,40]])
np.bmat('a,b;b,a')

matrix([[ 1, 2, 10, 20], [ 3, 4, 30, 40], [10, 20, 1, 2], [30, 40, 3, 4]])

注意:

对array,A*B是逐元素相乘,对matrix,A*B是矩阵相乘,multiply函数才能实现逐元素相乘。

3.Numpy类型

布尔型bool 
整型int8, int16, int32, int64, int128, int 
无符号整型
int8, uint16, uint32, uint64, uint128, uint 
 
浮点数float16, float32, float64, float, longfloat默认为双精度 float64longfloat 精度大小与系统有关
复数complex64, complex128, complex, longcomplex默认为 complex128 ,即实部虚部都为双精度
字符串string, unicode可以使用 dtype=S4 表示一个4字节字符串的数组
对象object数组中可以使用任意值
Recordsvoid 
时间datetime64, timedelta64 
a = array([1,1.2,'hello', [10,20,30]],dtype=object)
a * 2

array([2, 2.4, 'hellohello', [10, 20, 30, 10, 20, 30]], dtype=object)

可用asarray()修改类型,但不会改变原数组值

b = a.view(uint8) #view 会将 a 在内存中的表示看成是 uint8 进行解析,修共用一块内存
asarray(a, dtype=uint8)

4.各种属性查看

  • 查看列表属性:
type(a)  #numpy.ndarray

 

  • 查看数组维度:
np.array(a) #1

1

  • 查看数组中的数据类型:
a.dtype

int32

  • 查看array形状:
a.shape
a.shape=2,2 #(4L,)
a.reshape(2,2) #array([1,2],[3,4])

 

  • 查看每个元素所占的字节:
a.itemsize

 

  • 增加或去除数组维数:
y = a[newaxis, :] #(1L, 3L)
y = a[:, newaxis] #(3L, 1L)
y = a[newaxis, newaxis, :] #(1L, 1L, 3L)

 

a = arange(6)
a.shape = (2,1,3)
b = a.squeeze() #(2L, 3L) #去除多余的轴,返回一个将所有长度为1的维度去除的新数组
  • 列表不支持将列表中的每个元素增加1的操作,用array可以
a+1
b=array([2,3,4,5])
a+b
a*b //对应元素相乘,不是按照矩阵乘法(多维矩阵时注意)

5.where语句

  1. 对于一维:
a = array([0, 12, 5, 20])
a > 10

array([False, True, False, True], dtype=bool)

indices = where(a > 10)
indices = indices[0]
indices
indices = where(a>10)[0]  #array([1, 3], dtype=int64)

注意到 where 的返回值是一个元组。

使用元组是由于 where 可以对多维数组使用,此时返回值就是多维的。

可以直接用 where 的返回值进行索引:

loc = where(a > 10)
a[loc]

array([12, 20])

2.多维数组

a = array([[0, 12, 5, 20],
           [1, 2, 11, 15]])
loc = where(a > 10)
loc

(array([0, 0, 1, 1], dtype=int64), array([1, 3, 2, 3], dtype=int64))

3.np.where(condition, x, y):符合条件输出x,否则y

np.where([[True,False], [True,True]],    # 官网上的例子
			 [[1,2], [3,4]],
             [[9,8], [7,6]])
array([[1, 8],
	   [3, 4]])

第一个值从[1,9]中选,因为条件为True,所以是选1。第二个值从[2,8]中选,因为条件为False,所以选8,后面以此类推

6.数据读取

txt文本文件,npy二进制文件

data = np.loadtxt('myfile.txt', 
                  skiprows=1,         #忽略第一行
                  dtype=np.int,      #数组类型
                  delimiter=',',     #逗号分割
                  usecols=(0,1,2,4), #指定使用哪几列数据
                  comments='%'       #百分号为注释符
                 )
import os
a = array([102,111,212], 
          dtype=uint8)
a.tofile('foo.dat') #写入二进制数据
b = frombuffer('foo', dtype=uint8) #从数据中读入,要指定类型
os.remove('foo.dat')  #清理数据文件

data = np.array([[1,2], 
                 [3,4]])
np.savetxt('out.txt', datafmt="%d") #保存为整数,默认使用科学计数法的形式保存
with open('out.txt') as f:
    for line in f:
        print line

1 2

3 4

 

7.数组方法

 求和:

a = array([[1,2,3],[4,5,6]])
sum(a) #求所有元素的和或a.sum()
sum(a, axis=0) #沿着第一维求和或a.sum(axis=0)
sum(a, axis=-1) #沿着最后一维求和

求积:

a.prod() #求所有元素的乘积
prod(a, axis=0) #array([4,10,18])

求最大最小值:

a.min() #全局最小
a.min(axis=0) #沿着某个轴的最小
a.argmin()
a.argmin(axis=0) #max同理

均值:

a.mean()
a.mean(axis=-1)
average(a, axis = 0)
average(a, axis = 0, weights=[1,2]) #average 函数还支持加权平均

 标准差:

a.std(axis=1) #用 std 方法计算标准差
a.var(axis=1) #用 var 方法计算方差

限制数据:

a.clip(3,5) #小于3的变成3,大于5的变成5

 计算最大值和最小值之差:

a.ptp(axis=1)
a.ptp()

 数组倒置:

对于复数数组,转置并不返回复共轭,只是单纯的交换轴的位置,原数组的值也改变

a.transpose()
#a.T  //缩写

连接:

#x(2L,3L),y(2L.3L)
z = concatenate((x,y)) #默认沿着第一维进行连接(4L,3L)
z = concatenate((x,y), axis=1) #沿着第二维进行连接(2L,6L)
vstack((x, y)) #(4L, 3L)
hstack((x, y)) #(2L, 6L)
dstack((x, y)) #(2L, 3L, 2L)

查看它的对角线元素:

a.diagonal()
a.diagonal(offset=1) #使用偏移来查看它的次对角线,正数表示右移,负数表示左移
i = [0,1,2]
a[i, i] = 2 #更新对角线的值

8.排序

weights = array([20.8, 93.2, 53.4, 61.8])
#也支持方法操作,但是sort方法会改变数组的值
sort(weights) #返回的结果是从小到大排列的
argsort(weights) #从小到大的排列在数组中的索引位置

二维:

a = array([[.2, .1, .5], [.4, .8, .3],[.9, .6, .7]])
sort(a) #默认相当于对每一行进行排序
sort(a, axis = 0) #改变轴,对每一列进行排序

 searchsorted(sorted_array, values),第一个必需是已排序的数组,返回的值相当于保持第一个数组的排序性质不变,将第二个数组中的值插入第一个数组中的位置

from numpy.random import rand
data = rand(100)
data.sort()
bounds = .4, .6
low_idx, high_idx = searchsorted(data, bounds)
data[low_idx:high_idx] #利用插入位置,将数组中所有在这两个值之间的值提取出来

9.数组与字符串转换

a.tostring() #转化为字符串
a = np.fromstring(s, dtype=np.uint8) #使用 fromstring 函数从字符串中读出数据,不过要指定类型

 

二.索引操作

简单操作

提取元素,切片,索引操作与python数组相同,下面之讲解多维数组。

a=array([0,1,2,3],[10,11,12,13])
a[1,3]=-1 //利用索引赋值
a[1] //返回第二行元素组成的array
a[0,1:3] //第一行第2,3个元素
a[0::1,::2] //[lower:upper:step]

(ps:切片是引用机制,意味着,Python并没有为 b 分配新的空间来存储它的值,而是让 b 指向了 a 所分配的内存空间,因此,改变 b 会改变 a 的值

a=array([1,2,2,3,4])
b=a[2:4]
b[0]=10
print(a)

[0,1,10,3,4]

若不改变可采用copy()进行赋值,申请新的内存

a = array([0,1,2,3,4])
b = a[2:4].copy()
b[0] = 10
print(a)

[0, 1, 2, 3, 4]

但是这种现象在列表中不会出现

花式索引

  • 一维

切片只能支持连续或者等间隔的切片操作,要想实现任意位置的操作,需要使用花式索引

与 range 函数类似,我们可以使用 arange 函数来产生等差数组

a = np.arange(0, 80, 10)

花式索引需要指定索引位置:

indices = [1, 2, -3]
y = a[indices]
print y

[10 20 50]

还可以使用布尔数组来花式索引:

mask = array([0,1,1,0,0,1,0,0],
            dtype=bool)
a[mask]

array([10, 20, 50])

或者用布尔表达式生成 mask(mask 必须是布尔数组):

from numpy.random import rand
a = rand(10)
mask = a > 0.5
a[mask]

array([ 0.73365131, 0.62068734, 0.53085308])

  • 二维:

对于二维花式索引,我们需要给定 rowcol 的值

a = array([[ 0, 1, 2, 3, 4, 5],
           [10,11,12,13,14,15],
           [20,21,22,23,24,25],
           [30,31,32,33,34,35],
           [40,41,42,43,44,45],
           [50,51,52,53,54,55]])
a[(0,1,2,3,4), (1,2,3,4,5)]

array([ 1, 12, 23, 34, 45])

mask = array([1,0,1,0,0,1],
            dtype=bool)
a[mask, 2]

array([ 2, 22, 52])

三.其他操作

1.向量化函数

def sinc(x):
    if x == 0.0:
        return 1.0
    else:
        w = np.pi * x
        return np.sin(w) / w

但这个函数不能作用于数组x = np.array([1,2,3])

此时可以使用 numpyvectorize 将函数 sinc 向量化,产生一个新的函数

vsinc = np.vectorize(sinc)  #其作用是为 x 中的每一个值调用 sinc 函数

2.ufunc对象

Numpy 有两种基本对象:ndarray (N-dimensional array object)ufunc (universal function object)ndarray 是存储单一数据类型的多维数组,而 ufunc 则是能够对数组进行处理的函数,比如add()对象,accumulate方法等

a = np.array([1,2,3,4])
np.add.accumulate(a)  #array([ 1,  3,  6, 10])

outer()方法

a = np.array([0,1])
b = np.array([1,2,3])
#对于 a 中每个元素,将 op 运用到它和 b 的每一个元素上所得到的结果
np.add.outer(a, b)  #array([[1, 2, 3],[2, 3, 4]])

3.choose函数实现条件筛选

control = np.array([[1,0,1],
                    [2,1,0],
                    [1,2,2]])

np.choose(control, [10, 11, 12])  #将 0,1,2 对应的值映射为了 10, 11, 12

array([[11, 10, 11], [12, 11, 10], [11, 12, 12]])

i0 = np.array([[0,1,2],
               [3,4,5],
               [6,7,8]])
i2 = np.array([[20,21,22],
               [23,24,25],
               [26,27,28]])
control = np.array([[1,0,1],
                    [2,1,0],
                    [1,2,2]])

np.choose(control, [i0, 10, i2])#choose 不仅仅能接受下标参数,还可以接受下标所在的位置

array([[10, 1, 10], [23, 10, 5], [10, 27, 28]])

np.choose(a < 10, (a, 10))  #将数组中所有小于 10 的值变成了 10
np.choose(choice, (a, 10, 15))  #将数组中所有小于 10 的值变成了 10,大于 15 的值变成了 15

4.结构化数组

a = np.array([1.0,2.0,3.0,4.0], np.float32)

使用 view 方法,将 a 对应的内存按照复数来解释,即我们可以把复数看成一个结构体:

a.view(np.complex64)

换句话说,我们只需要换种方式解释这段内存,便可以得到结构化数组的效果,dtype 创造了自定义的结构类型,然后用自定义的结构来解释数组 a 所占的内存

my_dtype = np.dtype([('mass', 'float32'), ('vol', 'float32')])
a.view(my_dtype)

my_data[0]['vol']  #得到第一个元素的速度信息,可以使用域的名称来索引

自定义排序规则,先按速度,再按质量:

my_data.sort(order=('vol', 'mass'))

生成记录数组要使用 numpy.rec 里的 fromrecords 方法

from numpy import rec
particals_rec = rec.fromrecords([(1,1), (1,2), (2,1), (1,3)], 
                                dtype = partical_dtype)
#在记录数组中,域可以通过属性来获得:
particals_rec.mass  #也可以通过域来查询:particals_rec['mass']

array([ 1., 1., 2., 1.])

5.内存映射

内存映射也是一种处理文件的方法,内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。

使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。

  • memmap
memmap(filename,
       dtype=uint8,
       mode='r+'
       offset=0
       shape=None
       order=0)

mode 表示文件被打开的类型:

r 只读,c 复制+写,但是不改变源文件r+ 读写,使用 flush 方法会将更改的内容写入文件,w+ 写,如果存在则将数据覆盖

offset 表示从第几个位置开始。

四.比较总结

matlab,numpy_array, numpy_matrix

[1,2,3;4,5,6]array([[1.,2.,3.],[4.,5.,6.]])mat([[1.,2.,3.],[4.,5.,6.]]), mat('1,2,3;4,5,6')2x3 矩阵
[a b;c d]vstack([hstack([a,b]), hsatck([c,d])]])bmat('a b;c d')分块矩阵构造
a(end)a[-1]a[:,-1][0,0]最后一个元素
a'a.conj().Ta.H复共轭转置
a * bdot(a,b)a * b矩阵乘法
a .* ba * bmultiply(a,b)逐元素乘法
a.^3a**3power(a,3)逐元素立方
a(:,find(v>0.5))a[:,nonzero(v>0.5)[0]]a[:,nonzero(v.A>0.5)[0]]找出行向量 v>0.5 对应的 a 中的列
a(:,find(v>0.5))a[:,v.T>0.5]a[:,v.T>0.5)]找出列向量 v>0.5 对应的 a 中的列
a .* (a>0.5)a * (a>0.5)mat(a.A * (a>0.5).A)将所有小于 0.5 的元素设为 0
1:10arange(1.,11.), r_[1.:11.], r_[1:10:10j]mat(arange(1.,11.)), r_[1.:11., 'r']这里 1. 是为了将其转化为浮点数组
0:9arange(10.), r_[:10.], r_[:9:10j]mat(arange(10.)), r_[:10., 'r'] 
[1:10]'arange(1.,11.)[:,newaxis]r_[1.:11.,'c']列向量
zeros, ones, eye, diag, linspacezeros, ones, eye, diag, linspacemat(...) 
rand(3,4)random.rand(3,4)mat(...)0~1 随机数
[x,y]=meshgrid(0:8,0:5)mgrid[0:9., 0:6.], meshgrid(r_[0:9.],r_[0:6.])mat(...)网格
ogrid[0:9.,0:6.], ix_(r_[0:9.],r_[0:6.])mat()建议在 Numpy 中使用 
[x,y]=meshgrid([1,2,4],[2,4,5])meshgrid([1,2,4],[2,4,5])mat(...) 
ix_([1,2,4],[2,4,5])mat(...)  
repmat(a, m, n)tile(a, (m,n))mat(...)产生 m x na
[a b]c_[a,b]concatenate((a,b),1)列对齐连接
[a; b]r_[a,b]concatenate((a,b))行对齐连接
norm(v)sqrt(dot(v,v)), linalg.norm(v)sqrt(dot(v.A,v.A)), linalg.norm(v)
[Q,R,P]=qr(a,0)Q,R = scipy.linalg.qr(a)mat(...)QR 分解
[L,U,P]=lu(a)L,U = Sci.linalg.lu(a)mat(...)LU 分解
fft(a)fft(a)mat(...)FFT
ifft(a)ifft(a)mat(...)IFFT
sort(a)sort(a),a.sortmat(...)排序

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值