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 相关文章推荐
python定时器使用示例分享
Feb 16 Python
python获得文件创建时间和修改时间的方法
Jun 30 Python
Python 中迭代器与生成器实例详解
Mar 29 Python
Python编程之序列操作实例详解
Jul 22 Python
python 读取鼠标点击坐标的实例
Dec 29 Python
python下PyGame的下载与安装过程及遇到问题
Aug 04 Python
python zip()函数使用方法解析
Oct 31 Python
django2.2 和 PyMySQL版本兼容问题
Feb 17 Python
python获取响应某个字段值的3种实现方法
Apr 30 Python
jupyter notebook运行命令显示[*](解决办法)
May 18 Python
利用Python的folium包绘制城市道路图的实现示例
Aug 24 Python
python 批量将中文名转换为拼音
Feb 07 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
phpMyAdmin 安装配置方法和问题解决
2009/06/08 PHP
基于initPHP的框架介绍
2013/04/18 PHP
新手菜鸟必读:session与cookie的区别
2013/08/22 PHP
ThinkPHP3.1新特性之查询条件预处理简介
2014/06/19 PHP
php读取der格式证书乱码解决方法
2015/06/22 PHP
PHP7安装Redis扩展教程【Linux与Windows平台】
2016/09/30 PHP
javascript 正则替换 replace(regExp, function)用法
2010/05/22 Javascript
jQuery.extend 函数的详细用法
2012/06/27 Javascript
js中split函数的使用方法说明
2013/12/26 Javascript
javascript的数组和常用函数详解
2014/05/09 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
微信小程序 图片绝对定位(背景图片)
2017/04/05 Javascript
详解Vue CLI3 多页应用实践和源码设计
2018/08/30 Javascript
小程序封装wx.request请求并创建接口管理文件的实现
2019/04/29 Javascript
微信小程序判断页面是否从其他页面返回的实例代码
2019/07/03 Javascript
express中static中间件的具体使用方法
2019/10/17 Javascript
[38:54]完美世界DOTA2联赛PWL S2 Rebirth vs LBZS 第一场 11.28
2020/12/01 DOTA
简介Python的collections模块中defaultdict类型的用法
2016/07/07 Python
用Python实现读写锁的示例代码
2018/11/05 Python
值得收藏的10道python 面试题
2019/04/15 Python
浅谈Pytorch中的torch.gather函数的含义
2019/08/18 Python
python使用html2text库实现从HTML转markdown的方法详解
2020/02/21 Python
pandas 像SQL一样使用WHERE IN查询条件说明
2020/06/05 Python
JAVA及PYTHON质数计算代码对比解析
2020/06/10 Python
Right-on官方网站:日本知名的休闲服装品牌
2019/07/12 全球购物
Dr. Martens马汀博士德国官网:马丁靴鼻祖
2019/12/26 全球购物
介绍Java的内部类
2012/10/27 面试题
高中生的自我鉴定范文
2014/01/24 职场文书
酒店值班经理的工作职责范本
2014/02/18 职场文书
《日月潭》教学反思
2014/02/28 职场文书
高中学生期末评语
2014/04/25 职场文书
服装设计师求职信
2014/06/04 职场文书
解除劳动合同协议书范本
2014/09/13 职场文书
优秀员工事迹材料
2014/12/20 职场文书
单位工资证明范本
2015/06/12 职场文书
永中文档在线转换预览基于nginx配置部署方案
2022/06/10 Servers