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中的面向对象编程详解(上)
Apr 13 Python
Python实现PS图像调整之对比度调整功能示例
Jan 26 Python
Python数据分析之双色球统计单个红和蓝球哪个比例高的方法
Feb 03 Python
django反向解析URL和URL命名空间的方法
Jun 05 Python
Python3多目标赋值及共享引用注意事项
May 27 Python
python fuzzywuzzy模块模糊字符串匹配详细用法
Aug 29 Python
Python time库基本使用方法分析
Dec 13 Python
python的sys.path模块路径添加方式
Mar 09 Python
pytorch  网络参数 weight bias 初始化详解
Jun 24 Python
Pycharm Git 设置方法
Sep 15 Python
Python语言编写智力问答小游戏功能
Oct 13 Python
超级详细实用的pycharm常用快捷键
May 12 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生成QRcode实例
2014/09/22 PHP
PHP面向对象五大原则之开放-封闭原则(OCP)详解
2018/04/04 PHP
php使用mysqli和pdo扩展,测试对比mysql数据库的执行效率完整示例
2019/05/09 PHP
PHP实现的AES 128位加密算法示例
2019/09/16 PHP
判断iframe是否加载完成的完美方法
2010/01/07 Javascript
Javascript中自动切换焦点实现代码
2012/12/15 Javascript
用jQuery模拟select下拉框的简单示例代码
2014/01/26 Javascript
Vuejs第十一篇组件之slot内容分发实例详解
2016/09/09 Javascript
AngularJS实现星星等级评分功能
2016/09/24 Javascript
简单实现Bootstrap标签页
2020/08/09 Javascript
JS 实现随机验证码功能
2017/02/15 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
2017/10/24 Javascript
ionic3实战教程之随机布局瀑布流的实现方法
2017/12/28 Javascript
如何使node也支持从url加载一个module详解
2018/06/05 Javascript
vue-router的HTML5 History 模式设置
2018/09/08 Javascript
NodeJS使用Range请求实现下载功能的方法示例
2018/10/12 NodeJs
ZK中使用JS读取客户端txt文件内容问题
2019/11/07 Javascript
Python编程中的反模式实例分析
2014/12/08 Python
Python中有趣在__call__函数
2015/06/21 Python
Python数据分析之获取双色球历史信息的方法示例
2018/02/03 Python
python爬虫之线程池和进程池功能与用法详解
2018/08/02 Python
Pycharm 文件更改目录后,执行路径未更新的解决方法
2019/07/19 Python
解决在pycharm运行代码,调用CMD窗口的命令运行显示乱码问题
2019/08/23 Python
Python统计时间内的并发数代码实例
2019/12/28 Python
使用Python将图片转正方形的两种方法实例代码详解
2020/04/29 Python
Python退出时强制运行一段代码的实现方法
2020/04/29 Python
解决python使用list()时总是报错的问题
2020/05/05 Python
python os模块在系统管理中的应用
2020/06/22 Python
python3 os进行嵌套操作的实例讲解
2020/11/19 Python
Shell编程面试题
2012/05/30 面试题
总经理办公室主任岗位职责
2013/11/12 职场文书
大学生个人求职口试自我评价
2014/02/16 职场文书
基层党员公开承诺书
2014/05/29 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
python解决12306登录验证码的实现
2021/04/18 Python
Python自动化实战之接口请求的实现
2022/05/30 Python