Skip to content

Latest commit

 

History

History
303 lines (158 loc) · 13.1 KB

File metadata and controls

303 lines (158 loc) · 13.1 KB

六、索引数据

索引是用于优化查询序列或数据帧中的值的工具。 它们很像关系数据库中的键,但是功能更强大。 它们为多组数据提供了对齐方式,还带有如何处理数据的各种任务(如重采样到不同频率)的语义。

您将对 Pandas 执行的许多建模工作很大程度上取决于您如何设置索引。 正确实现的索引将优化性能,并成为推动分析的宝贵工具。

我们之前曾简要地使用过索引,在本章中,我们将进行更深入的探讨。 在这次深入学习中,我们将详细了解:

  • 索引的重要性
  • Pandas 索引的类型,包括RangeIndexInt64IndexCategoricalIndexFloat64IndexDatetimeindexPeriodIndex
  • 设置和重置索引
  • 创建分层索引
  • 使用分层索引选择数据

配置 Pandas

我们从 Pandas 的标准配置开始,但是我们也加载了 S&P 500 数据,以供几个示例使用。

索引的重要性

Pandas 索引允许有效地查找值。 如果不存在索引,则将需要对我们所有数据进行线性搜索。 索引使用直接查找而不是搜索过程为特定数据项创建优化的快捷方式。

为了开始检查索引的值,我们将使用以下10000随机数的DataFrame

假设我们要查找key==10099处的随机数的值(我明确选择了此值,因为它是DataFrame中的最后一行)。 我们可以使用布尔选择来做到这一点。

从概念上讲,这很简单。 但是,如果我们想重复执行此操作怎么办? 可以使用%timeit语句在 Python 中进行模拟。 以下代码重复执行查找并报告性能。

该结果表明,1,000 个循环执行了三次,并且这三次中最快的一次平均每个循环花费了 0.00535 秒(一组 1,000 个循环总计 5.35 秒)。

现在让我们尝试使用索引来帮助我们查找值。 以下代码设置此DataFrame的索引以匹配keys列的值。

现在可以使用.loc[]查找该值。

那只是一个查询。 让我们用%timeit计时。

使用索引的查找大约快五倍。 由于具有更高的性能,因此通常最好的方法是在可能的情况下按索引执行查找。 使用索引的不利之处在于构造索引可能会花费一些时间,并且还会消耗更多的内存。

很多时候,您会天生就知道索引应该是什么,您可以直接创建索引并开始探索。 其他时间,首先需要进行一些探索才能确定最佳指数。 通常,您可能没有足够的数据或适当的字段来创建适当的索引。 在这些情况下,您可能需要使用返回多个半歧义结果的部分索引,并且仍然对该集合执行布尔选择以获得所需的结果。

在执行探索性数据分析以首先加载数据并使用查询/布尔选择进行探索时,这是最佳实践。 如果您的数据自然支持一个索引,或者您确实需要提高速度,则创建索引。

Pandas 索引类型

Pandas 提供许多内置索引。 每种索引类型都根据特定的数据类型或数据模式设计用于优化查找。 让我们看看其中几种常用的。

基本类型 - Index

这种类型的索引是最通用的,表示一组有序和可切片的值。 它包含的值必须是可哈希的 Python 对象。 这是因为索引将使用此哈希来形成与该对象的值相关联的值的有效查找。 尽管哈希查找比线性查找更受青睐,但还有其他类型的索引可以进一步优化。

列索引通常是这种通用类型。 以下代码演示了如何将这种索引类型用作DataFrame的列。

虽然这种类型的索引通常对于字母数字列名非常有效,但是如果需要,可以使用其他类型的索引作为列索引。

使用Int64IndexRangeIndex的整数索引标签

Int64Index表示映射到值的不可变的 64 位整数数组。 直到更新版本的 pandas 为止,这是未指定索引或使用整数的默认索引类型,如以下代码片段所示:

使用此索引,DataFrame中的行查找非常高效,因为它们是使用连续的内存中数组执行的。

Pandas 的最新版本添加了RangeIndex作为Int64Index的优化。 它具有表示基于整数的索引的能力,该索引从特定的整数值开始,具有结束的整数值,并且还可以指定步骤。

使用开始,停止和步进是一种常见的模式,因此需要向 Pandas 添加自己的子类。 通过使用这三个值,可以节省内存,并且执行时间与Int64Index中的顺序相同。

RangeIndex已成为 Pandas 对象的默认索引。 以下内容对此进行了演示,该示例创建了默认为RangeIndex的整数值的序列。

使用Float64Index的浮点标签

通过使用Float64Index,浮点数可用作索引标签。

请注意,此片返回了 11 行,而不是前 5 行。 这是因为Float64Index,并且 Pandas 从一开始就将我们的意思表示为 5.0 之前的所有值。

使用IntervalIndex表示离散间隔

可以使用IntervalIndex表示不同的标签桶。 该间隔在一端(左端或右端)关闭,这意味着该间隔的该端值包含在该间隔中。 以下代码显示了使用间隔作为索引创建DataFrame的过程。

作为索引的类别值 - CategoricalIndex

CategoricalIndex用于表示基础类别的稀疏填充索引。 下面创建一个DataFrame,其中一列为“类别”。

将类别列(B)移到DataFrame的索引中可以看到现在有CategoricalIndex

然后可以使用基础类别中的现有值执行查找。

类别将在第 7 章“类别数据”中进行详细检查。

使用DatetimeIndex的日期时间索引

DatetimeIndex用于表示一组日期和时间。 这些在时间序列数据中得到了广泛使用,在这些时间序列数据中,以特定的时间间隔采样。 为了简要说明这一点,下面的代码创建了5-每小时时间段的范围,并将它们用作该序列的索引。

索引的类型可以看作是DatetimeIndex

日期/时间的基本表示形式是 64 位整数,这使得按日期和时间进行查找非常有效。

使用PeriodIndex的时间段索引

能够表示诸如日,月或年之类的时间段也很重要。 这很像一个间隔,但要持续一段时间。 可以通过使用PeriodIndex并为索引中的时间段指定特定频率来对这些场景进行建模。

下面通过对从2017-01开始的三个 1 个月周期进行建模进行演示。

然后可以在SeriesDataFrame中使用该索引。

使用索引

在介绍了创建各种类型的 Pandas 索引之后,现在让我们检查一下这些索引的几种常见使用模式。 具体来说,我们将检查:

  • 对序列或数据帧创建和使用索引
  • 用索引选择值的方法
  • 在索引之间移动数据
  • 重新索引 Pandas 对象

对序列或数据帧创建和使用索引

索引可以显式创建,也可以让 Pandas 隐式创建。 当您使用构造器的index参数分配索引时,会显式创建。

以下代码通过首先独立创建DatetimeIndex进行演示。

您可以单独使用此索引,也可以将其与SeriesDataFrame关联。 此代码利用索引创建一个DataFrame

通过设置.index属性,也可以将索引直接分配给现有的DataFrame或序列。

使用索引选择值

可以使用[]运算符使用索引或使用SeriesDataFrame的以下属性索引器来查找值:

.loc[] 通过标签而不是位置查找。 但小心点; 如果标签是整数,则整数将被视为标签!
.at[] 类似于.loc[],但这只能检索单个值。
.iloc[] 查找基于基于0的位置,而不是基于索引标签。
.ix[] 混合,当给出整数时将尝试基于0的查找; 其他类型是基于标签的。 将不建议使用此属性,因此请保留其他三个属性。

可以使用[]运算符在Series中查找值,如以下DataFrame所示,该运算符已检索到b值。

Series上使用[]进行查找等同于使用.loc[]属性。

[]运算符应用于DataFrame时,检索列而不是行。

若要使用DataFrame通过行索引进行查找,必须使用属性索引器之一。

属性索引器表单也可以使用切片。

并且还可以传递值列表。

在索引之间移动数据

通过使用.reset_index()可以重置DataFrame对象的索引。 通常将其用于将DataFrame对象的索引的内容移到一个或多个列中。

以下代码将sp500索引中的符号移到一列中,并将索引替换为默认的整数索引。

可以使用.set_index()方法并通过指定要移动的列将数据列移动到DataFrame对象的索引。 以下代码将Sector列移至索引。

可以将多个列移至索引,从而形成一个层次/多索引。 层次结构索引将在本章后面介绍。

重新索引 Pandas 对象

可以使用.reindex()方法重新索引DataFrame。 重新索引使DataFrame符合新索引,将旧索引中的数据与新索引对齐,并在对齐失败的地方填充NaN

此代码演示将sp500重新索引到三个指定的索引标签。

此过程将创建具有指定行的新DataFrame。 如果未找到特定值的行,则将插入NaN值,如'FOO'标签所示。 这种方法实际上是一种基于索引标签过滤出数据的好技术。

重新索引也可以在列上完成,如下面的代码所示,用于指定的三个列名称:

由于NewCol的值未包含在原始数据中,因此将为其插入NaN值。

分层索引

分层索引是 Pandas 的一项功能,它允许每行结合使用两个或多个索引。 层次结构索引中的每个索引都称为一个级别。 索引中多个级别的规范允许使用每个级别的值的不同组合来有效选择数据的不同子集。 从技术上讲,具有多个层次结构的 Pandas 索引称为MultiIndex

以下代码演示了使用sp500数据通过MultiIndex创建和访问数据。 假设我们要通过SectorSymbol的值来组织此数据,以便我们可以基于来自两个变量的值的组合来有效地查找数据。 我们可以使用以下代码将SectorSymbol的值移动到MultiIndex中,以完成此操作:

.index属性现在显示索引为MultiIndex对象:

如上所述,MultiIndex对象包含两个或多个级别,在这种情况下为两个:

每个级别都是一个不同的Index对象:

可以通过.get_level_values()方法检索每行特定级别的索引本身的值:

使用.xs()方法通过层次索引访问DataFrame对象中的值。 此方法的工作方式类似于.ix属性,但是提供了用于指定索引多维性的参数。

以下代码选择索引标签为Industrials的所有项目:0Sector):

结果DataFrame的索引由未指定的级别组成,在这种情况下为Symbol。 从结果索引中删除为其指定值的级别。

level参数可用于选择在指定级别具有特定索引值的行。 以下代码选择索引的Symbol分量为ALLE的行。

为了防止电平下降(如果您未指定每个级别),可以使用drop_levels=False选项。

要从索引层次结构中进行选择,可以将具有不同级别的.xs()调用链接在一起。 下面选择级别为0Industrials和级别为1UPS的行。

另一种语法是将层次结构索引的每个级别的值作为元组传递。

请注意,.xs()仅可用于获取,而不能用于设置值。

总结

在本章中,我们更深入地研究了在 Pandas 中使用索引来组织和检索数据。 我们研究了许多有用的索引类型,以及它们如何与不同类型的数据一起使用以有效访问值而无需查询行中的数据。 最后,我们对使用分层索引的研究进行了总结,该分层索引能够有效地检索与多个索引中的标签匹配的数据,从而为我们提供了选择数据子集的有力手段。

至此,我们已经涵盖了 Pandas 的许多基本建模部分。 在下一章中,我们将研究用 Pandas 表示分类变量。