numpy randn 和_《利用Python进行数据分析》- Numpy高阶功能
发布日期:2021-10-31 07:31:58 浏览次数:4 分类:技术文章

本文共 5022 字,大约阅读时间需要 16 分钟。

2f8659380cee6999ed1872af5b60b542.png

ndarray对象内幕

NumPy的ndarray提供了一种方法将一组同构数据(连续的或跨步的)解释为多维数组对象。数据类型或dtype决定数据如何被解释为浮点数、整数、布尔值或我们正在查看的任何其他类型。

让ndarray如此灵活的部分原因是每个数组对象都是一个数据块的分布视图。例如,你可能会想知道数组视图arr[::2,::-1]如何做到不复制任何数据。原因是ndarray不仅仅是一块内存和一个dtype,它还具有“跨步”信息,使数组能够以不同的步长在内存中移动。更准确地说,ndarray内部包含以下内容:

  • 指向数据的指针——即RAM中或内存映射文件中的数据块
  • 数据类型或dtype,描述数组中固定大小的值单元格
  • 表示数组形状(shape)的元组
  • 步长元组,表示要“步进”的字节数的整数以便沿维度推进一个元素

如下图是一个简单的ndarray内部构造:

140012f143279f84bf8d4dbc33632625.png
ndarray对象

例如,一个10*5的数组,其shape为(10,5)

import

一个典型的(C阶)345 float64值(8字节)的数组具有跨度(160,40,8)(理解跨度可能是有用的,因为通常特定轴上的跨度越大,沿着该轴执行计算的代价越高):

np

虽然一般的NumPy用户很少会对数组跨度(strides)感兴趣,但它们是构建“零复制”数组视图的关键因素。跨度甚至可以是负的,这使得数组能够穿过内存“向后”移动(例如,在诸如obj[::-1]或object[:,::-1]的切片中就是这种情况。

NumPy dtype层次结构

你可能时不时会需要写代码检查数组是否包含整数、浮点数、字符串或Python对象。由于浮点数有多种类型(float16到float128),因此检查dtype是否在类型列表中会非常麻烦。幸运的是,dtype有超类,如np.integer和np.floating,它们可以和np.issubtype函数一起使用:

ints

你可以通过调用类型的mro方法来查看特定dtype的所有父类:

np

因此,我们可以得到:

np

大部分NumPy用户不必知道这点,但知道了就偶尔可以派上用场。

高阶数组操作

除了神奇索引、切片和布尔值子集外,还有很多方式可以处理数组。虽然不部分数据分析应用程序的繁重工作都是由pandas中的高级函数处理的,但有时候你可能需要编写一些在现有库中找不到的数据算法。

重塑数组

在很多情况下,你将数组从一个形状转换为另一个形状,并且不复制任何数据。为了实现这个功能,可以向reshape数组实例方法传递一个表示新形状的元组。例如,假设我们有一个一维数组,我们想要把该数组重新排列进一个矩阵:

arr

多维数组也可以被重塑:

arr

传递的形状维度可以有一个值是-1,表示维度通过数据进行推断:

arr

由于数组的shape属性是一个元组,它可以被传递给reshape:

other_arr

reshape的反操作可以将更高维度的数组转换为一维数组,这种操作通常被称为扁平化(flattening)或分散化(raveling):

arr

如果结果中的值在原始数组中是连续的,则ravel不会生成底层数据的副本。flatten方法的行为类似于ravel,但它总是返回数据的副本:

arr

连接和分隔数组

numpy.concatenate可以获取数组的序列(元组、列表等),并沿着输入将它们按顺序连接在一起:

import

对于常见的连接类型有一些方便的函数,比如vstack和hstack。之前的操作可以这样表达:

np

另一方面,split可以将一个数组沿轴向切片成多个数组:

arr

传递给np.split的值[1,3]表示将数组拆分时的索引位置。

堆叠助手:r_和c_

在NumPy命名空间中有两个特殊的对象:r_和c_,它们可以使堆栈数组的操作更为简洁:

arr

这些函数还可以将切片转换为数组:

np

重复元素:tile和repeat

repeat和tile函数是用于重复或复制数组的两个有用的工具。repeat函数按照给定次数对数组中的每个元素进行复制,生成一个更大的数组:

arr

默认情况下,如果你传递一个整数,每个元素都会复制相应的次数。如果你传递了一个整数数组,每个元素都会重复相应的不同次数:

arr

多维数组可以在指定的轴向上对它们的元素进行重复:

arr

请注意,如果没有传递轴,数组将首先扁平化,这可能不是你想要的。同样,需要按照不同次数重复多维数组的切片时,你可以传递一个整数数组:

arr

另一方面,tile是一种快捷方法,它可以沿着轴向堆叠副本。在视觉上,你可以把它看作类似于“铺设瓷砖”:

arr

第二个参数是瓷砖的数量。用标量来说,铺设是逐行进行的,而不是逐列。tile的第二个参数可以是表示“铺瓷砖”布局的元组:

arr

神奇索引的等价方法:take和put

使用整数数组通过索引是获取、设置数组子集的一种方式:

import

还有其他一些ndarray方法可以用于特殊情况下在单个轴上的数据选取:

arr

如果要在别的轴上使用take,你可以传递axis关键字:

inds

广播

广播描述了算法如何在不同形状的数组之间进行运算。它是一个强大的功能,但可能会导致混淆,即使对于有经验的用户也是如此。最简单的广播示例发生在将标量值与数组组合的时候:

import

上面将标量值4广播给乘法运算的所有其他运算。 例如,我们可以通过减去列均值来降低数组中的每一列的数值。在这种情况下,它非常简单:

arr

通过广播设定数组的值

控制算法运算的相同广播规则也适用于通过数组索引设置值。在一个简单的例子中,我们可以做这样的事情:

import

但是,如果我们想要将数值的一维数组设置到数组的列中,只要形状是兼容的就可以做到这一点:

col

高阶ufunc用法

Numpy的每个二元ufunc(通用函数)都有特殊的方法来执行某些特殊的向量化操作。 reduce方法接收单个数组并通过执行一系列二元操作在可选的轴向上对数组的值进行聚合。例如,使用np.add.reduce是对数组进行加和的另一种方法:

import

起始值(对于add方法是0)取决于ufunc。如果传递了一个轴,则沿该轴执行缩聚。这使你能够以简洁的方式回答某些种类的问题。作为一个不太重要的例子,我们可以使用np.logical_and检查数组的每一行中的值是否被排序:

np

请注意,logical_and.reduce等价于all方法。

accumlate与reduce是相关的,就像cumsum与sum相关一样。accumulate生成一个数组,其尺寸与中间“累计”值相同:

arr

outer在两个数组之间执行成对的交叉乘积:

arr

outer的输出的维度等于输入的维度总和:

x

最后一个方法reduceat执行“本地缩聚”,本质上是一个数组groupby操作,在操作中数组的切片聚合在一起。reduceat方法接受一系列的“箱体边缘”,这些箱体边缘表示如何分割以及聚合数据值:

arr

结果是在arr[0:5],arr[5:8]和arr[8:]上执行了缩聚(此处是加和)。在其他方法中,你可以传递一个axis参数:

arr

结构化和记录数组

ndarray是一个同构数据的容器。也就是说,它表示一个内存块,其中每个元素占用相同数量的字节,有dtype确定。表面上,ndarray的这种特性不允许你使用它表示异构的数据或表格型数据。结构化数组时一个ndarray,其中每个元素可以被认为代表C中的struct(因此是“结构化”的名称),或者是SQL表中的具有多个命名字段的行:

import

有几种方法可以指定结构化的dtyp。一种典型的方式是使用(field_name,field_data_type)作为元组的列表。现在,数组的元素是元组对象,其元素可以像字典一样访问:

sarr

字段名称存储在dtype.names属性中。当你访问结构化数组中的字段时,将返回数据的分步视图,因此不会复制任何内容:

sarr

嵌套dtype和多维字段

当指定结构化的dtype时,你可以另外传递一个形状(以int或元组的形式):

dtype

在这种情况下,x字段引用的是每条记录中长度为3的数组:

arr

很方便地,访问arr['x']然后返回一个二维数组,而不是像之前的例子那样返回一个一维数组:

arr

这使你可以将更复杂的嵌套结构表示为数组中的单个内存块。你也可以嵌套dtype来创建更复杂的结构。这里是一个例子:

dtype

为什么要使用结构化数组

与pandas的DataFrame相比,Numpy结构化数组时一个相对底层的工具。结构化数组提供了一宗将内存块解释为具有任意复杂嵌套列的表格结构的方法。由于数组的每个元素都在内存中表示为固定数量的字节,因此结构化数组提供了读/写磁盘(包括内存映射)数据,以及在网络上传输数据和其他此类用途的非常快速有效的方法。

高级排序

ndarray的sort实例方法是一种原位排序,意味着数组的内容进行了重排列,而不是生成一个新的数组:

import

在进行数组原位排序时,请记住如果数组不是ndarray的视图的话,原始数组将会被改变:

arr

另一方面,numpy.sort产生的是一个数组的新的、排序后的副本。否则,它接受与ndarray.sort相同的参数(如kind):

arr

所有这些排序方法都有一个axis参数,用于独立地沿着传递的轴对数据部分进行排序:

arr

你可以会注意到所有的排序方法都没有降序排列的选项。这是一个实践中的问题,因为数组切片会产生视图,因此不需要生成副本也不需要任何计算工作。同时ndarray也有和列表一样的反序即values[::-1]的功能:

arr

间接排序:argsort和lexsort

在数据分析中,你可能需要通过一个或多个键对数据集进行重新排序。例如,有关某些学生的好时机表可能需要按姓氏排序,然后按名字排序。这是一个间接排序的例子。还有,给定一个或多个键(一个或多个值的数组),你希望获得一个整数索引数组,整数索引将告诉你如何重新排列数据为指定顺序。两种实现该功能的方法是argsort和numpy.lexsort。举个例子:

values

作为一个更复杂的例子,下面的代码对一个二维数组按照它的第一行进行重新排序:

arr

lexsort类似于argsort,但它对多键数组执行间接字典排序。假设我们想对一些由名字和姓氏标识的数据进行排序:

first_name

稳定排序

稳定排序算法保留了相等元素的相对位置。在相对顺序有意义的间接排序中,这可能尤其重要:

import

唯一可用的稳定排序时mergesort,它保证了O(nlogn)性能,但其平均性能比默认的quicksort方法更差。

数组的部分排序

排序的目标之一可以是确定数组中最大或最小的元素。Numpy已经优化了方法numpy.partition和np.argpartition,用于围绕第k个小元素对数组进行分区:

import

在调用partition(arr,3)之后,结果中的前三个元素是最小的三个值,并不是特定的顺序。numpy.argpartition类似于numpy.argsort排序,它返回的是将数据重新排列为等价顺序的索引:

indices

numpy.searchsorted:在已排序的数组寻找元素 searchsorted是一个数组方法,它对已排序数组执行二分搜索,返回数组中需要插入值的位置以保持排序:

arr

你还可以传递一个值数组来获取一个索引数组:

arr

你可能已经注意到,对于0元素,searchsorted返回0。这是因为默认行为是返回一组相等值左侧的索引:

arr

作为searchsorted的另一个应用,假设我们有一个介于0和10,000之间的数值,以及我们想用来分隔数据的单独的“桶边界”数组:

data

然后得到每个数据点属于哪个区间的标签(其中1代表桶[0,100)),我们可以简单地使用searchsorted:

labels

可以和pandas的groupby一起被用于分桶数据:

import

转载地址:https://blog.csdn.net/weixin_39934257/article/details/110581502 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:json 插入数据_SQL-mysql操作json
下一篇:python数据自动可视化_Python可视化数据呈现

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年03月29日 05时12分38秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章