版本 0.8.0 (2012 年 6 月 29 日)#

这是继 0.7.3 之后的一个主要版本,包含了大量关于时间序列处理和基础设施方面的工作,以及库中的许多新功能。它包含了来自 20 多个不同作者的 700 多次提交。大多数 pandas 0.7.3 及更早版本的用户在升级时应该不会遇到任何问题,但由于迁移到 NumPy 的 datetime64 dtype,可能存在一些潜在的错误和不兼容性。如果需要,剩余的不兼容性将在 0.8.1 版本中尽快修复。请参阅完整发布说明或 GitHub 上的问题跟踪器以获取完整列表。

支持非唯一索引#

所有对象现在都可以使用非唯一索引。数据对齐/连接操作根据 SQL 连接语义工作(包括,如果适用,在多对多连接中索引的重复)。

NumPy datetime64 dtype 和 1.6 依赖#

时间序列数据现在使用 NumPy 的 datetime64 dtype 表示;因此,pandas 0.8.0 现在要求至少 NumPy 1.6。它也已测试并验证可在 NumPy 的开发版本 (1.7+) 上工作,该版本包含一些重要的面向用户的 API 更改。NumPy 1.6 还存在许多与纳秒精度数据相关的错误,因此我建议您避免使用 NumPy 1.6 的 datetime64 API 函数(尽管它们是有限的),并且仅使用 pandas 提供的接口与此数据进行交互。

请参阅 0.8.0 部分末尾的“移植”指南,其中列出了用户将旧代码库从 pandas 0.7 或更早版本迁移到 0.8.0 可能遇到的问题。

对于使用旧版 NumPy < 1.6 的用户,将随时提供 0.7.x 系列的错误修复。0.7.x 版本将不再进行除错误修复之外的进一步开发。

时间序列更改和改进#

注意

通过此版本,旧版 scikits.timeseries 的用户应该能够将其代码移植到使用 pandas。

注意

有关 pandas 时间序列 API 的概述,请参阅文档

  • 新的 datetime64 表示方式显著加快了连接操作和数据对齐减少了内存使用,并比 datetime.datetime 显著提高了序列化/反序列化性能。

  • 高性能且灵活的 resample 方法,用于从高频到低频和从低频到高频的转换。支持插值、用户定义的聚合函数以及控制间隔和结果标签的定义方式。还实现了一套基于 Cython/C 的高性能重采样函数(包括开高低收)。

  • 重新设计了频率别名,并支持像“15min”或“1h30min”这样的频率快捷方式

  • 新的DatetimeIndex 类支持固定频率和不规则时间序列。取代了现在已弃用的 DateRange 类。

  • 新的 PeriodIndexPeriod 类,用于表示时间跨度并执行日历逻辑,包括 12 财政季度频率 <timeseries.quarterly>。这是 scikits.timeseries 代码库部分元素的移植和重大增强。支持 PeriodIndex 和 DatetimeIndex 之间的转换。

  • 新的 Timestamp 数据类型是 datetime.datetime 的子类,提供相同的接口,同时能够处理纳秒精度数据。还提供了便捷的时区转换

  • 增强了对时区的支持。向 TimeSeries 和 DataFrame 添加了 tz_converttz_localize 方法。所有时间戳都存储为 UTC;设置了时区的 DatetimeIndex 对象中的时间戳将本地化为本地时间。因此,时区转换基本上是免费的。用户现在几乎不需要了解 pytz 库;只需知道时区名称的字符串即可。时区感知的时间戳相等当且仅当它们的 UTC 时间戳匹配。具有不同时区的时区感知时间序列之间的操作将产生 UTC 索引的时间序列。

  • 时间序列字符串索引便捷功能/快捷方式:使用字符串切片年份、年月以及索引值。

  • 增强的时间序列绘图功能;改编自 scikits.timeseries 基于 matplotlib 的绘图代码。

  • 新的 date_rangebdate_rangeperiod_range 工厂函数

  • 强大的频率推断函数 infer_freq 和 DatetimeIndex 的 inferred_freq 属性,以及在构造 DatetimeIndex 时推断频率的选项。

  • to_datetime 函数可高效地将字符串数组解析为 DatetimeIndex。DatetimeIndex 将把字符串数组或列表解析为 datetime64。

  • 优化了对 Series 和 DataFrame 列中 datetime64-dtype 数据类型的支持。

  • 新的 NaT (Not-a-Time) 类型,用于表示时间戳数组中的 NA

  • 优化了 Series.asof 方法,用于查找时间戳数组的“as of”值

  • Milli、Micro、Nano 日期偏移对象。

  • 可以使用 datetime.time 对象索引时间序列,以选择特定一天中的时间 (TimeSeries.at_time) 或两个时间之间 (TimeSeries.between_time) 的所有数据。

  • 添加了 tshift 方法,用于使用索引的频率(如果存在)进行超前/滞后,而不是使用 shift 进行简单的超前/滞后。

其他新特性#

  • 新增 cutqcut 函数(类似于 R 的 cut 函数),用于通过将值分箱到基于值 (cut) 或基于分位数 (qcut) 的箱中来计算连续变量的分类变量。

  • Factor 重命名为 Categorical 并添加了一些可用性特性。

  • 向 fillna/reindex 添加 limit 参数。

  • GroupBy 中更灵活地应用多个函数,并且可以传递 (名称, 函数) 元组列表以按给定名称的特定顺序获取结果。

  • 添加灵活的 replace 方法,用于高效地替换值。

  • 增强了 read_csv/read_table 函数,用于读取时间序列数据并将多列转换为日期。

  • 向解析器函数(read_csv 等)添加 comments 选项。

  • 向解析器函数添加 dayfirst 选项,用于解析国际 DD/MM/YYYY 日期。

  • 允许用户指定 CSV 阅读器 方言,以控制引号等。

  • 在 read_csv 中处理 千位 分隔符,以改进整数解析。

  • 启用一次性解除堆叠多个级别。缓解 pivot_table 的错误(引入空列)。

  • 迁移到基于 klib 的哈希表进行索引;性能优于 Python 的 dict,并且内存使用更少。

  • 添加 first、last、min、max 和 prod 优化后的 GroupBy 函数。

  • 新增 ordered_merge 函数。

  • 向 DataFrame, Series 添加灵活的 比较 实例方法 eq, ne, lt, gt 等。

  • 改进 scatter_matrix 绘图函数,并在对角线上添加直方图或核密度估计。

  • 添加 “kde” 绘图选项用于密度图。

  • 支持通过 rpy2 将 DataFrame 转换为 R data.frame。

  • 改进了对 Series 和 DataFrame 中复数的支持。

  • 向所有数据结构添加 pct_change 方法。

  • 为 DataFrame 控制台输出添加 max_colwidth 配置选项。

  • 使用索引值插值 Series 值。

  • 可以从 GroupBy 中选择多列。

  • 向 Series/DataFrame 添加 update 方法,用于就地更新值。

  • 向 DataFrame 添加 anyall 方法。

新的绘图方法#

import pandas as pd

fx = pd.read_pickle("data/fx_prices")
import matplotlib.pyplot as plt

Series.plot 现在支持 secondary_y 选项。

plt.figure()

fx["FR"].plot(style="g")

fx["IT"].plot(style="k--", secondary_y=True)

2012 年 GSOC 参与者 Vytautas Jancauskas 添加了许多新的绘图类型。例如,'kde' 是一个新选项。

s = pd.Series(
    np.concatenate((np.random.randn(1000), np.random.randn(1000) * 0.5 + 3))
)
plt.figure()
s.hist(density=True, alpha=0.2)
s.plot(kind="kde")

更多信息请参阅绘图页面

其他 API 更改#

  • 时间序列函数中弃用 offsettime_ruletimeRule 参数名。警告将打印直到 pandas 0.9 或 1.0 版本。

pandas <= 0.7.3 用户潜在的移植问题#

pandas 0.8.0 中可能影响您的主要变化是时间序列索引使用 NumPy 的 datetime64 数据类型,而不是 Python 内置 datetime.datetime 对象的 dtype=object 数组。DateRange 已被 DatetimeIndex 取代,但行为相同。但是,如果您有代码将以前包含 datetime.datetime 值的 DateRangeIndex 对象转换为普通 NumPy 数组,则使用标量值的代码中可能存在潜在错误,因为您正在将控制权交给 NumPy。

In [1]: import datetime

In [2]: rng = pd.date_range("1/1/2000", periods=10)

In [3]: rng[5]
Out[3]: Timestamp('2000-01-06 00:00:00')

In [4]: isinstance(rng[5], datetime.datetime)
Out[4]: True

In [5]: rng_asarray = np.asarray(rng)

In [6]: scalar_val = rng_asarray[5]

In [7]: type(scalar_val)
Out[7]: numpy.datetime64

pandas 的 Timestamp 对象是 datetime.datetime 的子类,支持纳秒(nanosecond 字段存储 0 到 999 之间的纳秒值)。它应该直接替换之前使用 datetime.datetime 值的任何代码。因此,我建议不要将 DatetimeIndex 转换为常规 NumPy 数组。

如果您的代码需要 datetime.datetime 对象数组,您有几个选择。首先,DatetimeIndexastype(object) 方法会生成一个 Timestamp 对象数组。

In [8]: stamp_array = rng.astype(object)

In [9]: stamp_array
Out[9]: 
Index([2000-01-01 00:00:00, 2000-01-02 00:00:00, 2000-01-03 00:00:00,
       2000-01-04 00:00:00, 2000-01-05 00:00:00, 2000-01-06 00:00:00,
       2000-01-07 00:00:00, 2000-01-08 00:00:00, 2000-01-09 00:00:00,
       2000-01-10 00:00:00],
      dtype='object')

In [10]: stamp_array[5]
Out[10]: Timestamp('2000-01-06 00:00:00')

要获取正确的 datetime.datetime 对象数组,请使用 to_pydatetime 方法。

In [11]: dt_array = rng.to_pydatetime()

In [12]: dt_array
Out[12]: 
array([datetime.datetime(2000, 1, 1, 0, 0),
       datetime.datetime(2000, 1, 2, 0, 0),
       datetime.datetime(2000, 1, 3, 0, 0),
       datetime.datetime(2000, 1, 4, 0, 0),
       datetime.datetime(2000, 1, 5, 0, 0),
       datetime.datetime(2000, 1, 6, 0, 0),
       datetime.datetime(2000, 1, 7, 0, 0),
       datetime.datetime(2000, 1, 8, 0, 0),
       datetime.datetime(2000, 1, 9, 0, 0),
       datetime.datetime(2000, 1, 10, 0, 0)], dtype=object)

In [13]: dt_array[5]
Out[13]: datetime.datetime(2000, 1, 6, 0, 0)

matplotlib 知道如何处理 datetime.datetime,但不知道如何处理 Timestamp 对象。虽然我建议您使用 TimeSeries.plot 绘制时间序列,但您可以使用 to_pydatetime 或为 Timestamp 类型注册转换器。有关更多信息,请参阅 matplotlib 文档

警告

NumPy 1.6 中,用户界面 API 的纳秒 datetime64 单位存在 bug。特别是,数组的字符串表示会显示垃圾值,并且转换为 dtype=object 也同样有问题。

In [14]: rng = pd.date_range("1/1/2000", periods=10)

In [15]: rng
Out[15]: 
DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04',
               '2000-01-05', '2000-01-06', '2000-01-07', '2000-01-08',
               '2000-01-09', '2000-01-10'],
              dtype='datetime64[ns]', freq='D')

In [16]: np.asarray(rng)
Out[16]: 
array(['2000-01-01T00:00:00.000000000', '2000-01-02T00:00:00.000000000',
       '2000-01-03T00:00:00.000000000', '2000-01-04T00:00:00.000000000',
       '2000-01-05T00:00:00.000000000', '2000-01-06T00:00:00.000000000',
       '2000-01-07T00:00:00.000000000', '2000-01-08T00:00:00.000000000',
       '2000-01-09T00:00:00.000000000', '2000-01-10T00:00:00.000000000'],
      dtype='datetime64[ns]')

In [17]: converted = np.asarray(rng, dtype=object)

In [18]: converted[5]
Out[18]: Timestamp('2000-01-06 00:00:00')

相信我:不要惊慌。如果您正在使用 NumPy 1.6 并将与 datetime64 值的交互限制在 pandas 的 API 中,那么您将一切顺利。数据类型(内部是 64 位整数)本身没有问题;所有重要的数据处理都在 pandas 中进行,并且经过大量测试。我强烈建议您不要直接在 NumPy 1.6 中使用 datetime64 数组,只使用 pandas API。

支持非唯一索引:在后一种情况下,您可能有一段位于 try:... catch: 块内的代码因索引非唯一而失败。在很多情况下,它将不再失败(某些方法如 append 除非禁用,否则仍然会检查唯一性)。然而,一切并非失去希望:您可以检查 index.is_unique,如果它为 False 则显式引发异常,或者转到不同的代码分支。

贡献者#

共有 27 人为本次发布贡献了补丁。名字旁边带有“+”的人是首次贡献补丁。

  • Adam Klein

  • Chang She

  • David Zaslavsky +

  • Eric Chlebek +

  • Jacques Kvam

  • Kamil Kisiel

  • Kelsey Jordahl +

  • Kieran O’Mahony +

  • Lorenzo Bolla +

  • Luca Beltrame

  • Marc Abramowitz +

  • Mark Wiebe +

  • Paddy Mullen +

  • Peng Yu +

  • Roy Hyunjin Han +

  • RuiDC +

  • Senthil Palanisami +

  • Skipper Seabold

  • Stefan van der Walt +

  • Takafumi Arakaki +

  • Thomas Kluyver

  • Vytautas Jancauskas +

  • Wes McKinney

  • Wouter Overmeire

  • Yaroslav Halchenko

  • thuske +

  • timmie +