python科学计算之narray对象用法


Posted in Python onNovember 25, 2019

写在前面

最近在系统的看一些python科学计算开源包的内容,虽然以前是知道一些的,但都属于零零碎碎的,希望这次能把常用的一些函数、注意项整理下。小白的一些废话,高手请略过^ _ ^。文章中的函数仅仅是为了自己好理解,并没有按照官方文档上的函数声明形式记录。

numpy.narray

numpy.narray创建

numpy.narray的构造方式挺多的,这里就不一一说明,因为一般情况下,在进行科学计算时是通过给定的数据文件来读取的,而读取时使用的是pandas,具体可参考官方文档,或者参见这位大牛的文章。

numpy.narray.shape & numpy.narray.reshape

numpy.narray的形状可以用numpy.narray.shape属性来获取,它返回的是narray形状的tuple,反映了各个轴的长度。

na_a = np.array([1,2,3,4]) #长度为4的一维数组
na_b = np.array([[1,2,3,4],[5,6,7,8]]) #2行4列的二维数组

out:
#print na_a
[1 2 3 4] 
#print na_b
[[1 2 3 4] 
 [5 6 7 8]] 
#print na_a.shape
(4,)
#print na_b.shape 
(2, 4)

numpy.narray.shape相当于一个c++的public成员,不仅可以获取,还可以通过它改变narray的形状。当某一轴指定为-1时,该轴的长度将通过其他轴来计算。

na_b.shape = (4,2)
na_a.shape = (2,-1)

out:
#print na_b
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
#print na_a
 [[1 2]
 [3 4]]

需要注意的是:通过shape属性改变narray的形状时,并没对narray元素内存中的位置改变,只是改变了外观,仅仅是换了件马甲。

当然,如果你熟悉了使用函数,不想使用属性来改变形状时,可以通过narray.reshape(),注意的是该函数返回的结果和原narray共享内存空间,换句话说,一个narray对象的改变将导致另一个narray也发生相应的改变。

na_c = na_b.reshape((4,2))
na_c[0][0] = 100

out:
#print na_c
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
#print na_c
[[100 2]
 [ 3 4]
 [ 5 6]
 [ 7 8]]
#print na_b
[[100 2]
 [ 3 4]
 [ 5 6]
 [ 7 8]]

numpy.narray.dtype

narray元素的类型可以使用dtype属性来获取,当然也可以在构造narray对象时指定元素的类型,需要注意的是,在numpy中float是64位,而complex是128位的。这里的float和complex是python内置的数据类型,numpy也定义了自己的float等数据类型,而且更加的细化,比如float类型,numpy就有float16、float32、float64和float128.

af = np.array([1,2,3,4], dtype=float)
ac = np.array([5,6,7,8], dtype=complex)
af.dtype
ac.dtype

dtype('float64')
dtype('complex128')

python的完整数据类型中有大部分是所占字节来细化的,完整的数据在typeDict中定义,可通过numpy.typeDict.values()来获取完整类型。numpy在多维数组上的计算很高效,但是在数值对象计算上却比python慢很多,所以在进行数值计算时应避免使用numpy。

numpy.narray.astype() 类型转换

numpy.narray.astype() 可以对narray对象中元素逐一进行类型转换。

a = np.array([1,2,3,4], dtype=np.float)
a.dtype
dtype('float64')

b = a.astype(np.int32)
b.dtype
dtype('int32')

c.dtype
c = a.astype(np.complex)
c.dtype
dtype('complex128')

numpy.narray的自动生成

1.np.arange(start,end,step,dtype) 指定开始值、终值和步长生成一个等差数列,生成的narray中不包括end值。

2.np.linspace(start, end, element_nums, endpoint,dtype) 指定开始值、终值和元素个数生成一个等差数列,通过endpoint指定包不包括end,默认为True。

3.np.logspace(start, end, element_nums, base, endpoint,dtype) endpoint默认为True,base默认为10,该函数产生一个等比数列,元素为 python科学计算之narray对象用法

4.np.zeros(dim,dtype)对维度为dim的narray对象初始化为0,数据类型为dtype

5.np.ones(dim, dtype) 对维度为dim的narray对象初始化为1,数据类型为dtype

6.np.empty(dim,dtype) 该函数相当于对narray对象分配内存空间,但不进行初始化,所以切不可认为产生的元素为0。

7.np.full(dim, val, dtype) 产生维度为dim的narray对象并且全部初始为val,前面的zeros()和ones()可看作该函数的特殊形式。

8.上面函数的like版本,即np.zeros_like(object) 、np.ones_like(object) 、np.empty_like(object) 、np.full_like(object) ,这里的object是narray对象,这些函数产生的narray对象和上面一样,但narray的维度(shape)以及数据类型(dtype)是和传入的参数一样的,例如np.zeros_like(object) ==np.zeros(object.shape, object.dtype)。

9.fromstring(s, dtype)这个函数是比较又意思的,将字符串转换为一个narray对象, 我们先看看这个函数输出情况。

s="abcdefgh"
np.fromstring(s)

array([ 8.54088322e+194]) ## 这是什么鬼?
### 输出一下dtype呢?
dtype('float64')

显然,这里是按照float64类型存放的,那如果换一个数据类型呢?

np.fromstring(s,dtype=np.int8)

array([ 97, 98, 99, 100, 101, 102, 103, 104], dtype=int8)

这个学过c语言的都应该知道是ASCII编码,也就可以看出,在python中一个字符是占8位,即一个字节的,继续看:

np.fromstring(s,dtype=np.int16)

array([25185, 25699, 26213, 26727], dtype=int16)

这里改变数据类型位2个字节,那么应该是两个字符联立一起表示一个int16,25185=98*256+97,高位存放在低字节中,这是小端模式。OK,那如果我现在要存放的是[‘a','b'…'h']这样的narray对象呢?数据类型是什么?应该是‘|s1'

np.fromstring(s,'|S1')

array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  dtype='|S1')

frombuffer()也可以创建的narray对象,但此时创建的narray对象和原字符串是内存共享的,学过c++的都知道,string类型是只读类型,无法修改,所以在frombuffer()创建的narray无法做修改,如果要修改,请用fromstring()。

. fromfunction(fun, dim)通过自定义函数接口来创建narray对象,fun是一个函数名(看作指针),dim是一个创建对象的维度。

def fun(i):
 return i%4+1
np.fromfunction(fun,(10,))

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

可见利用fromfunction()创建narray时,参数i是从0开始自增的,自增的次数是维度的大小给定的,上面给定的维度位(10,),是一个一维数组,i从0自增到9(共10次)。看另外一个例子:

def fun2(i,j):
 return (i+1)*(j+1)
np.fromfunction(fun2,(9,9))

array([[ 1., 2., 3., 4., 5., 6., 7., 8., 9.],
  [ 2., 4., 6., 8., 10., 12., 14., 16., 18.],
  [ 3., 6., 9., 12., 15., 18., 21., 24., 27.],
  [ 4., 8., 12., 16., 20., 24., 28., 32., 36.],
  [ 5., 10., 15., 20., 25., 30., 35., 40., 45.],
  [ 6., 12., 18., 24., 30., 36., 42., 48., 54.],
  [ 7., 14., 21., 28., 35., 42., 49., 56., 63.],
  [ 8., 16., 24., 32., 40., 48., 56., 64., 72.],
  [ 9., 18., 27., 36., 45., 54., 63., 72., 81.]])

行可以看作j的自增,列可以看作i的自增,所以可以看作是两个for循环。

numpy.narray的元素存取

可以按照python中list存取元素的方式。

a = np.arange(10) #array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a[5]  #5
a[3:5] #[3,4]
a[:5] #[0,1,2,3,4]
a[:-1] #[0, 1, 2, 3, 4, 5, 6, 7, 8]

### 也可以指定步长,通过第三个数指定
a[1:-1:2] #从开始到结束,没隔两个数取一次 array([1, 3, 5, 7])
a[5:1:-2] #反向取 array([5, 3])

注意,通过这种方式取的新narray和原始narray内存共享,所以任何一个改变,另一个也将改变。 除此之外,numpy还提供了一下几个存取方式: 使用list存取,list的每个元素作为下标,这种方式得到的新narray和原始narray不共享内存。

a = np.arange(10)
a[[1,1,7,7]] #array([1, 1, 7, 7])

使用narray提取新数组,narray的元素作为下标,得到的新narray维度和参数narray维度相同。这个有点绕,看个例子吧:

a[np.array([2,1,3,6])] #array([2, 1, 3, 6])
a[np.array([[2,1,3,6],[7,4,6,1]])] 
## 
## array([[2, 1, 3, 6],
  [7, 4, 6, 1]])

使用bool数组提取,提取bool数组中为True的下标元素:

a[np.array([True, False,True,False,False,False,True,False,False,False])]

## array([0, 2, 6])

a[np.array([True,False,True,False,False,False,True,False,False,False])]=-1,-2,-3
print a #array([-1, 1, -2, 3, 4, 5, -3, 7, 8, 9])

多维数组

请先看一张图:

python科学计算之narray对象用法

左边是用切片方式提取右边6*6的narray对象元素。这种提取元素方式和原narray对象内存共享。

这里个人的理解,利用切片方式提取的新narray和原narray是内存共享的,而使用列表、bool数组等方式则不共享,原因很简单,利用切片方式,例如a[3:5],是从第三个元素到第5个元素(不包括),那么是用元素所占字节来移动的,就像c中的指针,这样比较便利。而其他方式是用下标,这些下标往往不连续,如果用指针方式的话则要来回移动,比较麻烦。所以不提供内存共享这种方式。

在这之前我们使用切片都是通过在[]中指定起点、终点以及步长,如果要单独创建切片对象呢?使用slice对象,创建的方式很简单,把[]中的:替换为None。

a = np.arange(0,60,10).reshape(-1,1)+np.arange(6)
### 广播,后面会说到
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[::2,2:]
## 
array([[ 2, 3, 4, 5],
  [22, 23, 24, 25],
  [42, 43, 44, 45]])
idx = slice(None,None,2),slice(2,None)
a[idx]
##
array([[ 2, 3, 4, 5],
  [22, 23, 24, 25],
  [42, 43, 44, 45]])

同时,numpy提供了IndexExpression类的对象s_来方便slice的创建。

np.s_[::2,2:]
## 
(slice(None, None, 2), slice(2, None, None))

结构体数组

numpy提供了和c类似的结构体数组,并且相互之间能够读取,以一个例子来说明:

## 创建persontype类型
persontype=np.dtype({
 'names':['name','age','weight'],
 'formats':['S30','i','f']}, align=True)
## 创建结构体数组
a=np.array([("zhang",20,55.5), ("wang",24,65.2)], dtype=persontype)

persontype有两个key,names和formats,names是以字典的方式标明结构体所含的字段,formats是对相应字段的数据类型。S30表示长度不超过30个字节的字符串,i相当于np.int32,f相当于np.float32,下面创建结构体数组的时候指定数据类型是我们创建的persontype。

## print a
array([('zhang', 20, 55.5  ), ('wang', 24, 65.19999695)],
  dtype={'names':['name','age','weight'], 'formats':['S30','<i4','<f4'], 'offsets':[0,32,36], 'itemsize':40, 'aligned':True})

## print a[0]
('zhang', 20, 55.5)
## a[0].dtype
dtype({'names':['name','age','weight'], 'formats':['S30','<i4','<f4'], 'offsets':[0,32,36], 'itemsize':40}, align=True)
## a[0]["name"]
'zhang'
b=a['age'] ## 20 24
b[0]=50
## print a[0]
('zhang', 50, 55.5)

通过tostring()和tofile()可以将结构体数组写入文件,并可以通过c读取,由于c中的结构体存在对齐,所以在python创建结构体数组时也需要使用相应的对齐方式,这一点通过align来指定,True为对齐,False不对齐。

narray内存结构

以二维narray对象为例,我们来看看narray对象在内存中的结构。

a = np.array([[0,1,2],[3,4,5],[6,7,8]], dtype=np.float32)

该二维数组的结构如下图:

python科学计算之narray对象用法

左边时一个结构体,描述了该narray对象的基本信息,包括数据类型(np.float32)、维度(轴的数量)、每个轴的数据个数、每个轴相邻元素的字节差、最后是存放数据的内存地址。通过切片方式得到的新narray就是在data字段表示的内存上获得原始narray的视图,我们来看看:

b=a[::2,::2]
## b
array([[ 0., 2.],
  [ 6., 8.]], dtype=float32)
## b.strides
(24, 8)

获得的新narray.strides发生了变化,而这个变化也刚好是每个轴相邻元素跨越的字节数。narray的数据在内存上的排列有两种形式,分别是C和FORTRAN格式,上面我们展示的就是C的格式,第0轴是最上位的,也就是说,第0轴作为行,所以第0轴的相邻元素跨越的字节数是最多的(比如这里为3*4=12),而FORTRAN结构与C格式相反,它是第1轴跨越的字节数最多。numpy默认是C格式,如果想改成FORTRAN的格式,只需要在创建narray的时候设置order=‘F'。narray的flags属性描述了存储区的一些属性:

## a.flags
C_CONTIGUOUS : True  #C语言格式
F_CONTIGUOUS : False #Fortran语言格式
OWNDATA : True   #数组是否拥有该存储区,如果是一个narray的视图则不拥有
WRITEABLE : True  #是否可写 (改变其中数据)
ALIGNED : True   # 对齐
UPDATEIFCOPY : False

OK,这里引出一个东东,如果要将a进行转置,我们是需要将需要将a顺时针旋转90°,那么还有上面简单的方法?我们先看看a.T.flags:

## a.T.flags
 C_CONTIGUOUS : False
 F_CONTIGUOUS : True
 OWNDATA : False
 WRITEABLE : True
 ALIGNED : True
 UPDATEIFCOPY : False

从这上面可以看到,对于a的转置,numpy是将其内存格式改变了,从C语言格式变成了Fortran的格式,并且转置是a的一个视图。这样的方式比旋转方式更加快速。

以上这篇python科学计算之narray对象用法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
高效测试用例组织算法pairwise之Python实现方法
Jul 19 Python
Python实现的ftp服务器功能详解【附源码下载】
Jun 26 Python
浅谈Pandas Series 和 Numpy array中的相同点
Jun 28 Python
用Python从0开始实现一个中文拼音输入法的思路详解
Jul 20 Python
pandas DataFrame的修改方法(值、列、索引)
Aug 02 Python
python 利用pywifi模块实现连接网络破解wifi密码实时监控网络
Sep 16 Python
python脚本实现音频m4a格式转成MP3格式的实例代码
Oct 09 Python
python Popen 获取输出,等待运行完成示例
Dec 30 Python
tensorflow实现打印ckpt模型保存下的变量名称及变量值
Jan 04 Python
Expected conditions模块使用方法汇总代码解析
Aug 13 Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
Jan 05 Python
Python字符串常规操作小结
Apr 03 Python
python运用pygame库实现双人弹球小游戏
Nov 25 #Python
python科学计算之scipy——optimize用法
Nov 25 #Python
基于python中__add__函数的用法
Nov 25 #Python
pygame库实现移动底座弹球小游戏
Apr 14 #Python
python科学计算之numpy——ufunc函数用法
Nov 25 #Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
Nov 25 #Python
Python解析json代码实例解析
Nov 25 #Python
You might like
PHP统计目录大小的自定义函数分享
2014/11/18 PHP
PHP unlink与rmdir删除目录及目录下所有文件实例代码
2018/02/07 PHP
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
jQuery实现鼠标可拖动调整表格列宽度
2014/05/26 Javascript
Javascript显示和隐藏ul列表的方法
2015/07/15 Javascript
Javascript实现网络监测的方法
2015/07/31 Javascript
springMVC结合AjaxForm上传文件
2016/07/12 Javascript
Angular.js实现动态加载组件详解
2017/05/28 Javascript
AngularJS日程表案例详解
2017/08/15 Javascript
《javascript少儿编程》location术语总结
2018/05/27 Javascript
原生JavaScript实现remove()和recover()功能示例
2018/07/24 Javascript
微信小程序新手教程之启动页的重要性
2019/03/03 Javascript
vue实现多条件和模糊搜索功能
2019/05/28 Javascript
vue实现自定义H5视频播放器的方法步骤
2019/07/01 Javascript
[01:53]2016完美“圣”典风云人物:Maybe专访
2016/12/05 DOTA
[55:42]VG vs VGJ.T 2018国际邀请赛淘汰赛BO1 8.21
2018/08/22 DOTA
Python批量转换文件编码格式
2015/05/17 Python
在Python中用get()方法获取字典键值的教程
2015/05/21 Python
使用Python编写简单的画图板程序的示例教程
2015/12/08 Python
python3中bytes和string之间的互相转换
2017/02/09 Python
Python numpy 常用函数总结
2017/12/07 Python
python实现学生管理系统
2018/01/11 Python
Python queue队列原理与应用案例分析
2019/09/27 Python
pandas-resample按时间聚合实例
2019/12/27 Python
国际经济贸易专业推荐信
2013/11/06 职场文书
中专生自我鉴定范文
2013/12/19 职场文书
优秀导游先进事迹材料
2014/01/25 职场文书
小学体育教学反思
2014/01/31 职场文书
大学生2014全国两会学习心得体会
2014/03/10 职场文书
学习雷锋精神心得体会范文
2014/03/12 职场文书
图书馆志愿者活动总结
2014/06/27 职场文书
六查六看六改心得体会
2014/10/14 职场文书
小学生读书笔记范文
2015/06/30 职场文书
Nginx设置日志打印post请求参数的方法
2021/03/31 Servers
Java面试题冲刺第十八天--Spring框架3
2021/08/07 面试题
SQL bool盲注和时间盲注详解
2022/07/23 SQL Server