数组是大多数程序设计语言 都有的数据结构 它用来表示有序的数据集 这么一说大家应该会有那么灵光一闪吧 似乎列表也是这样的一种结构 确实是的 列表在Python中可以当数组用 另外Python中也有专门的数组类型 那为什么NumPy中还需要 ndarray这样的数据结构呢 马上就可以知道了 列表和元组可以当数组来用 但是它们跟数组还是有点不一样 比如说像列表 由于它的元素可以是任何的类型 因此列表中保存的是对象的指针 比如说要保存一个简单的像 “1 2 3 4”这样4个元素的列表 它就需要4个指针和4个整数对象 浪费内存和计算时间 而array模块 再通过array函数来创建数组 它也有像insert() append() 这样的一些函数 但是它不支持多维数组 并且函数功能也不够丰富 所以使用不多 而ndarray是NumPy中的基本数据结构 它的别名是array 我们也把它叫做数组 数组的所有元素都是同一种类型 基于array有非常丰富的函数 大多数它们的性能都非常强大 好我们先来了解一下ndarray 有这样的一个5*5的数组 我们可以来分析一下这个数组 这个5*5的数组其实我们可以看成 它是由5个一维数组构成的 那每一个一维数组又有5个元素 在这里 这个是第一维 被称为第0轴 这个是第二维 被称为第1轴 就是axis 轴的个数被称为是秩,也就是rank 这个数组当中因为有2个轴,所以rank的值就是2 我们再来看一下axis 在很多函数使用的时候 都可以加上axis这样的一个参数 比如说 axis=0 它表示什么呢 表示沿着第0轴进行操作 其实就是对每一列进行操作 那如果axis=1呢 显然就是对每一行进行操作 ndarray有一些基本的属性 比如说 ndim可以计算它的秩 shape可以计算它的维度 size可以计算元素总个数 例如这边的这个数组 它的秩就是2 维度就是(2,2) 元素的总个数就是25 好我们下面来看一下array的创建方法 在NumPy中提供了很多ndarray的创建函数 最基本的就是array()这样的一个函数 我们可以创建一个一维的数组 也可以创建一个二维的数组 另外像arange() random() linspace() 这几个函数也常常用来创建数组 arange大家应该看上去很熟悉吧 跟我们的range很像 只不过它可以处理浮点数 而random()就是随机数 而linspace()这个函数也是非常常用 它指的是从起始点到终止点以及 个数确定的情况下创建一个等差数组 当然终止点可以不包含在内 把它设为False 默认的为True 除此之外 我们还常常使用像ones() zeros() 这样的函数创建一些基础的数组 另外还有一个比较特殊的 fromfunction()函数 它的功能是从一个函数来创建某一个维度的数组 这里的函数是这样子的 其实这个函数我们可以写成这种形式 return (i+1)*(j+1) 我们看一下 它是不是其实是生成一个9*9的乘法口诀表 就是这样的一个效果 从一一得一到九九八十一 很好玩吧 我们下面来简单演示一下 来创建一个数组 我们利用array()这个函数 假设我们创建的是一个2*3的这样一个数组 我们可以来看一下这个数组的属性 这是它的秩 维度 它的元素个数 而我们再来创建另外的一个元素数组 比如说我们利用arange()这样的一个函数 y就创建成功了 ndarray有很多操作和运算的方法 可以让我们获得我们想要的结果 比如说我们看一下 像这个符号 肯定很熟悉吧 切片 那选择0到2就表示什么呢 就表示我们要选择第0行和第1行 那第一维如果什么都不写 就表示我们行都要 再来看后面的0和1 这是列 就是选择第0列和第1列 所以结果是1 2 4 5 而我们也可以在参数中把两个维度都加上 我们这时候选择第一行 所以我们看到第一行的第0列和 第1列结果就是4和5 我们也可以遍历数组 用这样的方法 来实际操作一下 先定义一个3行3列的数组 如果要选择第1行数据 或者选择第1列和第3列数据 怎么办呢 我们可以用x[0]选择第1行数据 用x[:, [0,2]]选择第1列和第3列 那进一步如果要选择第1行 和第3行 是不是只要加上步长就可以了呢 写成这样的方式 显然用这样的方式就可以选择第1和3列 当然其实我们这两种写法选择的是 是数组的奇数行和奇数列 那如果这样写结果是什么呢 对比一下 我们发现这种写法交换了行 这跟我们在做列表处理时这种写法很类似 那如果要交换列怎么处理呢 是不是写成这样就可以了 我们还可以通过一些函数对ndarray进行操作 比如说 我们可以看到这个array的维度是2 * 3 如果我们要打印的时候 我们可以改变它的维度 可以用reshape()这个函数 我们可以把它变成3 * 2的这样一个数组 我们看到结果 是不是变了 很有意思吧 但是这种方法我们看到 原来的aArray还是原来的形式 如果想要真正改变它的shape的话 我们可以利用resize()这个函数 我们看到 结果就变了 来演示一下 假设我们要创建一个4行4列的数组 值从1到16 应该怎样来实现呢 是不是只要用结合np.arange()函数 就可以了 很方便吧 除了指定要变换的行和列外 科学计算中还常常使用-1这种表示 这种表示非常有用 例如x.reshape(2, -1) 表示将数组x转换成2行n列 这里基于数组和确定的维数 可以算出n是8 因为是唯一确定的所以可以不明确给出 用-1来表示就可以了 再例如在机器学习任务时 我们常常需要用x.reshape(-1, 1) 这样的形式改变数组的形状 以便于进行某些向量计算 另外这组函数也非常的常用 vstack()和hstack() 一个是在垂直方向上拼接 另外一个是在水平方向上拼接 而ndarray我们还可以用一些基本的运算符 对它们进行操作 比如说乘法 加法等等 另外这里我们看到有两个比较特殊的数组 它们居然也可以相加 这两个数组运算为什么能够成功呢 其实这是因为NumPy数组的 一个非常重要的特性——广播 当两个要运算的数组形状 不同时就会触发广播机制 NumPy会逐个比较两个数组的维度 只有相等或其中一维的长度是1 才能正确运算 例如数组a和b都包含3列元素 a有一维是1 处理时沿着这个维度运算 并用此维度上的第一组值 所以a扩展成两行[1,2,3] 所以计算出的计算就是这样的 数组也可以与标量值例如2进行运算 如果2与数组b相加 则它会被扩展成与b的相同维度 所有值均为2的数组 然后再与b逐个元素相加 这样运算 另外我们还可以用一些方法 对数组进行各类的运算 比如说sum()求和 我们之前讲的 我们可以利用这样的参数 分别按列求和和按行求和 这个是返回最小值 这个是返回最大值的索引 我们这个例子里面正好值和索引是一样的 这个大家肯定都知道 平均值 var和std分别代表方差和标准差 ndarray还有一些专门的应用 比如说非常常用的线性代数方面的应用 我们可以通过NumPy中的 一些函数进行各类计算 比如说这里我们可以通过dot()函数 计算矩阵的内积 另外NumPy中也有一个跟 SciPy library中名字一样的模块linalg 它差不多可以认为是SciPy library 中相应模块的一个子集 那我们也可以用它其中的很多函数进行各类运算 比如det()函数可以计算矩阵的行列式 inv()可以计算逆矩阵 在ndarray的最后 我们谈一下ufunc函数 也就是通用函数 NumPy中的通用函数是一种 能对数组中每个元素进行操作的函数 比如说像这样的一些 这边没有列全 我们在官网上能够看到它的所有函数名 通用函数本身还有一些方法 像reduce(), accumulate()等等 这些函数都是在C语言级别实现的 所以计算速度特别快 特别是在数据量大的时候 它比math中相应的函数速度要来的快 我们来看个例子 比如说这样的一个例子 计算的是一组数的sin(t)的二次方 我们通过time中的函数计算运行时间 两者进行比较 我们来试一下这个程序 我们来执行一下这个程序 我们看到 执行结果是这样的 用math库中的pow()和sin()函数 它的运行时间是这样子的 而用通用函数的运行时间是这样子的 我们会看到 差距还是比较大的 所以在数据量比较大的时候 同一个任务我们尽量选用NumPy中的通用函数来处理