Pandas-2-2-中文文档-五十五-

Pandas 2.2 中文文档(五十五)

原文:pandas.pydata.org/docs/

版本 0.18.1(2016 年 5 月 3 日)

原文:pandas.pydata.org/docs/whatsnew/v0.18.1.html

这是从 0.18.0 的次要 bug 修复版本,包括大量的 bug 修复以及一些新功能、增强功能和性能改进。我们建议所有用户升级到此版本。

主要亮点包括:

  • .groupby(...) 已得到加强,以提供与 .rolling(..).expanding(..).resample(..) 每个组的方便语法,参见此处

  • pd.to_datetime() 现在可以从 DataFrame 组装日期,请参阅此处

  • 方法链改进,请参阅此处。

  • 自定义工作时间偏移,请参阅此处。

  • 在处理 sparse 时进行了许多 bug 修复,请参阅此处

  • 通过@TomAugsburger提供的现代 pandas 功能,扩展了 Tutorials section。 (GH 13045).

v0.18.1 中的新功能

  • 新特性

    • 自定义工作时间

    • 方法.groupby(..)语法与窗口和重采样操作

    • 方法链改进

    • DatetimeIndex 的部分字符串索引时,作为 MultiIndex 的一部分

    • 组装日期时间

    • 其他增强功能

  • 稀疏更改

  • API 更改

    • 方法 .groupby(..).nth() 更改

    • NumPy 函数兼容性

    • 在 GroupBy 重采样上使用 .apply

    • read_csv 异常的更改

    • 方法 to_datetime 错误更改

    • 其他 API 更改

    • 弃用

  • 性能改进

  • 错误修复

  • 贡献者

新特性

自定义工作时间

CustomBusinessHourBusinessHourCustomBusinessDay 的混合,允许您指定任意假期。详情请参阅自定义工作时间 (GH 11514)

In [1]: from pandas.tseries.offsets import CustomBusinessHour

In [2]: from pandas.tseries.holiday import USFederalHolidayCalendar

In [3]: bhour_us = CustomBusinessHour(calendar=USFederalHolidayCalendar()) 

MLK Day 前的星期五

In [4]: import datetime

In [5]: dt = datetime.datetime(2014, 1, 17, 15)

In [6]: dt + bhour_us
Out[6]: Timestamp('2014-01-17 16:00:00') 

MLK Day 后的星期二(星期一因为是假日而跳过)

In [7]: dt + bhour_us * 2
Out[7]: Timestamp('2014-01-20 09:00:00') 
```  ### 方法 `.groupby(..)` 语法与窗口和重采样操作

`.groupby(...)` 已增强以提供方便的语法,用于处理每个组的`.rolling(..)`、`.expanding(..)`和`.resample(..)`,请参阅 ([GH 12486](https://github.com/pandas-dev/pandas/issues/12486), [GH 12738](https://github.com/pandas-dev/pandas/issues/12738))。

现在你可以在 groupbys 上将`.rolling(..)`和`.expanding(..)`作为方法使用。 这些会返回另一个延迟对象(类似于在未分组的 pandas 对象上所做的`.rolling()`和`.expanding()`)。 然后,您可以以类似的方式操作这些`RollingGroupby`对象。

以前,要按组获得滚动窗口平均值,您必须执行以下操作:

```py
In [8]: df = pd.DataFrame({"A": [1] * 20 + [2] * 12 + [3] * 8, "B": np.arange(40)})

In [9]: df
Out[9]: 
 A   B
0   1   0
1   1   1
2   1   2
3   1   3
4   1   4
.. ..  ..
35  3  35
36  3  36
37  3  37
38  3  38
39  3  39

[40 rows x 2 columns] 
In [1]: df.groupby("A").apply(lambda x: x.rolling(4).B.mean())
Out[1]:
A
1  0      NaN
 1      NaN
 2      NaN
 3      1.5
 4      2.5
 5      3.5
 6      4.5
 7      5.5
 8      6.5
 9      7.5
 10     8.5
 11     9.5
 12    10.5
 13    11.5
 14    12.5
 15    13.5
 16    14.5
 17    15.5
 18    16.5
 19    17.5
2  20     NaN
 21     NaN
 22     NaN
 23    21.5
 24    22.5
 25    23.5
 26    24.5
 27    25.5
 28    26.5
 29    27.5
 30    28.5
 31    29.5
3  32     NaN
 33     NaN
 34     NaN
 35    33.5
 36    34.5
 37    35.5
 38    36.5
 39    37.5
Name: B, dtype: float64 

现在你可以这样做:

In [10]: df.groupby("A").rolling(4).B.mean()
Out[10]: 
A 
1  0      NaN
 1      NaN
 2      NaN
 3      1.5
 4      2.5
 ... 
3  35    33.5
 36    34.5
 37    35.5
 38    36.5
 39    37.5
Name: B, Length: 40, dtype: float64 

对于.resample(..)类型的操作,以前您必须执行:

In [11]: df = pd.DataFrame(
 ....:    {
 ....:        "date": pd.date_range(start="2016-01-01", periods=4, freq="W"),
 ....:        "group": [1, 1, 2, 2],
 ....:        "val": [5, 6, 7, 8],
 ....:    }
 ....: ).set_index("date")
 ....: 

In [12]: df
Out[12]: 
 group  val
date 
2016-01-03      1    5
2016-01-10      1    6
2016-01-17      2    7
2016-01-24      2    8

[4 rows x 2 columns] 
In[1]: df.groupby("group").apply(lambda x: x.resample("1D").ffill())
Out[1]:
                  group  val
group date
1     2016-01-03      1    5
      2016-01-04      1    5
      2016-01-05      1    5
      2016-01-06      1    5
      2016-01-07      1    5
      2016-01-08      1    5
      2016-01-09      1    5
      2016-01-10      1    6
2     2016-01-17      2    7
      2016-01-18      2    7
      2016-01-19      2    7
      2016-01-20      2    7
      2016-01-21      2    7
      2016-01-22      2    7
      2016-01-23      2    7
      2016-01-24      2    8 

现在你可以这样做:

In[1]: df.groupby("group").resample("1D").ffill()
Out[1]:
                  group  val
group date
1     2016-01-03      1    5
      2016-01-04      1    5
      2016-01-05      1    5
      2016-01-06      1    5
      2016-01-07      1    5
      2016-01-08      1    5
      2016-01-09      1    5
      2016-01-10      1    6
2     2016-01-17      2    7
      2016-01-18      2    7
      2016-01-19      2    7
      2016-01-20      2    7
      2016-01-21      2    7
      2016-01-22      2    7
      2016-01-23      2    7
      2016-01-24      2    8 
```  ### 方法链改进

以下方法/索引器现在接受一个`callable`。 旨在使这些在方法链中更有用,请参阅文档。 ([GH 11485](https://github.com/pandas-dev/pandas/issues/11485), [GH 12533](https://github.com/pandas-dev/pandas/issues/12533))

+   `.where()`和`.mask()`

+   `.loc[]`、`iloc[]`和`.ix[]`

+   `[]` 索引

#### 方法`.where()`和`.mask()`

这些可以接受条件和`other`参数的可调用对象。

```py
In [13]: df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})

In [14]: df.where(lambda x: x > 4, lambda x: x + 10)
Out[14]: 
 A   B  C
0  11  14  7
1  12   5  8
2  13   6  9

[3 rows x 3 columns] 

方法.loc[].iloc[].ix[]

这些可以接受一个可调用对象和一个切片器的元组。 可调用对象可以返回有效的布尔索引器或任何对这些索引器的输入有效的内容。

# callable returns bool indexer
In [15]: df.loc[lambda x: x.A >= 2, lambda x: x.sum() > 10]
Out[15]: 
 B  C
1  5  8
2  6  9

[2 rows x 2 columns]

# callable returns list of labels
In [16]: df.loc[lambda x: [1, 2], lambda x: ["A", "B"]]
Out[16]: 
 A  B
1  2  5
2  3  6

[2 rows x 2 columns] 

使用[]进行索引

最后,您可以在 Series、DataFrame 和 Panel 的[]索引中使用可调用对象。 可调用对象必须根据其类和索引类型返回[]索引的有效输入。

In [17]: df[lambda x: "A"]
Out[17]: 
0    1
1    2
2    3
Name: A, Length: 3, dtype: int64 

使用这些方法/索引器,您可以在不使用临时变量的情况下链接数据选择操作。

In [18]: bb = pd.read_csv("data/baseball.csv", index_col="id")

In [19]: (bb.groupby(["year", "team"]).sum(numeric_only=True).loc[lambda df: df.r > 100])
Out[19]: 
 stint    g    ab    r    h  X2b  ...     so   ibb   hbp    sh    sf  gidp
year team                                   ... 
2007 CIN       6  379   745  101  203   35  ...  127.0  14.0   1.0   1.0  15.0  18.0
 DET       5  301  1062  162  283   54  ...  176.0   3.0  10.0   4.0   8.0  28.0
 HOU       4  311   926  109  218   47  ...  212.0   3.0   9.0  16.0   6.0  17.0
 LAN      11  413  1021  153  293   61  ...  141.0   8.0   9.0   3.0   8.0  29.0
 NYN      13  622  1854  240  509  101  ...  310.0  24.0  23.0  18.0  15.0  48.0
 SFN       5  482  1305  198  337   67  ...  188.0  51.0   8.0  16.0   6.0  41.0
 TEX       2  198   729  115  200   40  ...  140.0   4.0   5.0   2.0   8.0  16.0
 TOR       4  459  1408  187  378   96  ...  265.0  16.0  12.0   4.0  16.0  38.0

[8 rows x 18 columns] 
```  ### 部分字符串索引在`MultiIndex`中的部分`DatetimeIndex`

部分字符串索引现在在`MultiIndex`的一部分`DateTimeIndex`上匹配 ([GH 10331](https://github.com/pandas-dev/pandas/issues/10331))

```py
In [20]: dft2 = pd.DataFrame(
 ....:    np.random.randn(20, 1),
 ....:    columns=["A"],
 ....:    index=pd.MultiIndex.from_product(
 ....:        [pd.date_range("20130101", periods=10, freq="12H"), ["a", "b"]]
 ....:    ),
 ....: )
 ....:

In [21]: dft2
Out[21]:
 A
2013-01-01 00:00:00 a  0.469112
 b -0.282863
2013-01-01 12:00:00 a -1.509059
 b -1.135632
2013-01-02 00:00:00 a  1.212112
...                         ...
2013-01-04 12:00:00 b  0.271860
2013-01-05 00:00:00 a -0.424972
 b  0.567020
2013-01-05 12:00:00 a  0.276232
 b -1.087401

[20 rows x 1 columns]

In [22]: dft2.loc["2013-01-05"]
Out[22]:
 A
2013-01-05 00:00:00 a -0.424972
 b  0.567020
2013-01-05 12:00:00 a  0.276232
 b -1.087401

[4 rows x 1 columns] 

在其他级别

In [26]: idx = pd.IndexSlice

In [27]: dft2 = dft2.swaplevel(0, 1).sort_index()

In [28]: dft2
Out[28]:
 A
a 2013-01-01 00:00:00  0.469112
 2013-01-01 12:00:00 -1.509059
 2013-01-02 00:00:00  1.212112
 2013-01-02 12:00:00  0.119209
 2013-01-03 00:00:00 -0.861849
...                         ...
b 2013-01-03 12:00:00  1.071804
 2013-01-04 00:00:00 -0.706771
 2013-01-04 12:00:00  0.271860
 2013-01-05 00:00:00  0.567020
 2013-01-05 12:00:00 -1.087401

[20 rows x 1 columns]

In [29]: dft2.loc[idx[:, "2013-01-05"], :]
Out[29]:
 A
a 2013-01-05 00:00:00 -0.424972
 2013-01-05 12:00:00  0.276232
b 2013-01-05 00:00:00  0.567020
 2013-01-05 12:00:00 -1.087401

[4 rows x 1 columns] 
```  ### 组装日期时间

`pd.to_datetime()` 已经具备了从传递的`DataFrame`或字典中组装日期时间的能力。 ([GH 8158](https://github.com/pandas-dev/pandas/issues/8158))。

```py
In [20]: df = pd.DataFrame(
 ....:    {"year": [2015, 2016], "month": [2, 3], "day": [4, 5], "hour": [2, 3]}
 ....: )
 ....: 

In [21]: df
Out[21]: 
 year  month  day  hour
0  2015      2    4     2
1  2016      3    5     3

[2 rows x 4 columns] 

使用传递的框架进行组装。

In [22]: pd.to_datetime(df)
Out[22]: 
0   2015-02-04 02:00:00
1   2016-03-05 03:00:00
Length: 2, dtype: datetime64[ns] 

您只需传递您需要组装的列。

In [23]: pd.to_datetime(df[["year", "month", "day"]])
Out[23]: 
0   2015-02-04
1   2016-03-05
Length: 2, dtype: datetime64[ns] 
```  ### 其他增强

+   `pd.read_csv()` 现在支持`delim_whitespace=True`用于 Python 引擎 ([GH 12958](https://github.com/pandas-dev/pandas/issues/12958))

+   `pd.read_csv()` 现在支持打开包含单个 CSV 的 ZIP 文件,通过扩展推断或显式`compression='zip'` ([GH 12175](https://github.com/pandas-dev/pandas/issues/12175))

+   `pd.read_csv()` 现在支持使用 xz 压缩打开文件,通过扩展推断或明确指定`compression='xz'`; `xz` 压缩也通过相同的方式由`DataFrame.to_csv`支持 ([GH 11852](https://github.com/pandas-dev/pandas/issues/11852))

+   `pd.read_msgpack()` 现在即使使用压缩,也始终提供可写的 ndarrays([GH 12359](https://github.com/pandas-dev/pandas/issues/12359))

+   `pd.read_msgpack()` 现在支持使用 msgpack 序列化和反序列化分类变量([GH 12573](https://github.com/pandas-dev/pandas/issues/12573))

+   `.to_json()` 现在支持包含分类和稀疏数据的 `NDFrames`([GH 10778](https://github.com/pandas-dev/pandas/issues/10778))

+   `interpolate()` 现在支持 `method='akima'`([GH 7588](https://github.com/pandas-dev/pandas/issues/7588))。

+   `pd.read_excel()` 现在接受路径对象(例如 `pathlib.Path`, `py.path.local`)作为文件路径,与其他 `read_*` 函数一致([GH 12655](https://github.com/pandas-dev/pandas/issues/12655))

+   已添加 `.weekday_name` 属性作为 `DatetimeIndex` 和 `.dt` 访问器的组成部分([GH 11128](https://github.com/pandas-dev/pandas/issues/11128))

+   `Index.take` 现在对 `allow_fill` 和 `fill_value` 的处理更加一致([GH 12631](https://github.com/pandas-dev/pandas/issues/12631))

    ```py
    In [24]: idx = pd.Index([1.0, 2.0, 3.0, 4.0], dtype="float")

    # default, allow_fill=True, fill_value=None
    In [25]: idx.take([2, -1])
    Out[25]: Index([3.0, 4.0], dtype='float64')

    In [26]: idx.take([2, -1], fill_value=True)
    Out[26]: Index([3.0, nan], dtype='float64') 
    ```

+   `Index` 现在支持 `.str.get_dummies()`,返回 `MultiIndex`,参见 创建指示变量([GH 10008](https://github.com/pandas-dev/pandas/issues/10008), [GH 10103](https://github.com/pandas-dev/pandas/issues/10103))

    ```py
    In [27]: idx = pd.Index(["a|b", "a|c", "b|c"])

    In [28]: idx.str.get_dummies("|")
    Out[28]: 
    MultiIndex([(1, 1, 0),
     (1, 0, 1),
     (0, 1, 1)],
     names=['a', 'b', 'c']) 
    ```

+   `pd.crosstab()` 增加了一个 `normalize` 参数用于归一化频率表([GH 12569](https://github.com/pandas-dev/pandas/issues/12569))。更新文档中的示例在 这里。

+   `.resample(..).interpolate()` 现在受支持([GH 12925](https://github.com/pandas-dev/pandas/issues/12925))

+   `.isin()` 现在接受传递的 `sets`([GH 12988](https://github.com/pandas-dev/pandas/issues/12988))  ## 稀疏变化

这些变化使稀疏处理返回正确的类型,并努力使索引体验更加顺畅。

`SparseArray.take` 现在对标量输入返回标量,对其他输入返回 `SparseArray`。此外,它处理负索引器的规则与 `Index` 相同([GH 10560](https://github.com/pandas-dev/pandas/issues/10560), [GH 12796](https://github.com/pandas-dev/pandas/issues/12796))

```py
s = pd.SparseArray([np.nan, np.nan, 1, 2, 3, np.nan, 4, 5, np.nan, 6])
s.take(0)
s.take([1, 2, 3]) 
  • SparseSeries[] 在使用 Ellipsis 索引时出现 KeyError 错误(GH 9467

  • SparseArray[] 在使用元组索引时未正确处理的错误已修复(GH 12966

  • SparseSeries.loc[] 在类似列表的输入时引发 TypeError 错误的问题已修复(GH 10560

  • SparseSeries.iloc[] 在标量输入时可能引发 IndexError 错误的问题已修复(GH 10560

  • SparseSeries.loc[], .iloc[] 中使用 slice 时返回 SparseArray 而不是 SparseSeries 的错误已修复(GH 10560

  • SparseDataFrame.loc[], .iloc[] 中的 Bug 可能导致密集的 Series,而不是 SparseSeriesGH 12787

  • SparseArray 中的加法 Bug 忽略了右侧的 fill_valueGH 12910

  • SparseArray mod 中的 Bug 引发 AttributeErrorGH 12910

  • SparseArray 中的 pow Bug 计算 1 ** np.nannp.nan,应为 1(GH 12910

  • SparseArray 比较输出中的 Bug 可能会产生不正确的结果或引发 ValueErrorGH 12971

  • SparseSeries.__repr__ 中的 Bug 在长度超过 max_rows 时引发 TypeErrorGH 10560

  • SparseSeries.shape 中的 Bug 忽略了 fill_valueGH 10452

  • SparseSeriesSparseArray 中的 Bug 可能与其密集值的 dtype 不同(GH 12908

  • SparseSeries.reindex 中的 Bug 错误地处理了 fill_valueGH 12797

  • SparseArray.to_frame() 中的 Bug 导致了 DataFrame,而不是 SparseDataFrameGH 9850

  • SparseSeries.value_counts() 中的 Bug 不计算 fill_valueGH 6749

  • SparseArray.to_dense() 中的 Bug 不保留 dtypeGH 10648

  • SparseArray.to_dense() 中的 Bug 错误地处理了 fill_valueGH 12797

  • SparseSeriespd.concat() 中的 Bug 导致结果是密集的(GH 10536

  • SparseDataFramepd.concat() 中的 Bug 错误地处理了 fill_valueGH 9765

  • SparseDataFramepd.concat() 中的 Bug 可能引发 AttributeErrorGH 12174

  • SparseArray.shift() 中的 Bug 可能会引发 NameErrorTypeErrorGH 12908) ## API 变更

方法 .groupby(..).nth() 变更

当传递 as_index 参数时,.groupby(..).nth() 输出中的索引现在更加一致(GH 11039):

In [29]: df = pd.DataFrame({"A": ["a", "b", "a"], "B": [1, 2, 3]})

In [30]: df
Out[30]: 
 A  B
0  a  1
1  b  2
2  a  3

[3 rows x 2 columns] 

先前的行为:

In [3]: df.groupby('A', as_index=True)['B'].nth(0)
Out[3]:
0    1
1    2
Name: B, dtype: int64

In [4]: df.groupby('A', as_index=False)['B'].nth(0)
Out[4]:
0    1
1    2
Name: B, dtype: int64 

新行为:

In [31]: df.groupby("A", as_index=True)["B"].nth(0)
Out[31]: 
0    1
1    2
Name: B, Length: 2, dtype: int64

In [32]: df.groupby("A", as_index=False)["B"].nth(0)
Out[32]: 
0    1
1    2
Name: B, Length: 2, dtype: int64 

此外,以前,.groupby 总是会排序,无论是否使用 .nth() 传递了 sort=False

In [33]: np.random.seed(1234)

In [34]: df = pd.DataFrame(np.random.randn(100, 2), columns=["a", "b"])

In [35]: df["c"] = np.random.randint(0, 4, 100) 

先前的行为:

In [4]: df.groupby('c', sort=True).nth(1)
Out[4]:
 a         b
c
0 -0.334077  0.002118
1  0.036142 -2.074978
2 -0.720589  0.887163
3  0.859588 -0.636524

In [5]: df.groupby('c', sort=False).nth(1)
Out[5]:
 a         b
c
0 -0.334077  0.002118
1  0.036142 -2.074978
2 -0.720589  0.887163
3  0.859588 -0.636524 

新行为:

In [36]: df.groupby("c", sort=True).nth(1)
Out[36]: 
 a         b  c
2  -0.720589  0.887163  2
3   0.859588 -0.636524  3
7  -0.334077  0.002118  0
21  0.036142 -2.074978  1

[4 rows x 3 columns]

In [37]: df.groupby("c", sort=False).nth(1)
Out[37]: 
 a         b  c
2  -0.720589  0.887163  2
3   0.859588 -0.636524  3
7  -0.334077  0.002118  0
21  0.036142 -2.074978  1

[4 rows x 3 columns] 
```  ### NumPy 函数兼容性

通过增加`pandas`方法的签名,使其能够接受从`numpy`传入的参数,即使在`pandas`实现中并不一定使用这些参数,大大增加了`pandas`数组方法(例如`sum`和`take`)与它们的`numpy`对应方法之间的兼容性([GH 12644](https://github.com/pandas-dev/pandas/issues/12644), [GH 12638](https://github.com/pandas-dev/pandas/issues/12638), [GH 12687](https://github.com/pandas-dev/pandas/issues/12687))

+   `Index`和`TimedeltaIndex`的`.searchsorted()`现在接受一个`sorter`参数,以保持与 numpy 的`searchsorted`函数的兼容性([GH 12238](https://github.com/pandas-dev/pandas/issues/12238))

+   在`Series`上`np.round()`的 numpy 兼容性 bug([GH 12600](https://github.com/pandas-dev/pandas/issues/12600))

下面是一个签名增强的示例:

```py
sp = pd.SparseDataFrame([1, 2, 3])
sp 

先前行为:

In [2]: np.cumsum(sp, axis=0)
...
TypeError: cumsum() takes at most 2 arguments (4 given) 

新行为:

np.cumsum(sp, axis=0) 
```  ### 在 GroupBy 重新采样上使用`.apply`

在对`pd.TimeGrouper`进行重新采样分组操作(使用`apply`)时,现在具有与其他 groupby 操作上类似`apply`调用相同的输出类型。([GH 11742](https://github.com/pandas-dev/pandas/issues/11742)).

```py
In [38]: df = pd.DataFrame(
 ....:    {"date": pd.to_datetime(["10/10/2000", "11/10/2000"]), "value": [10, 13]}
 ....: )
 ....: 

In [39]: df
Out[39]: 
 date  value
0 2000-10-10     10
1 2000-11-10     13

[2 rows x 2 columns] 

先前行为:

In [1]: df.groupby(pd.TimeGrouper(key='date',
 ...:                          freq='M')).apply(lambda x: x.value.sum())
Out[1]:
...
TypeError: cannot concatenate a non-NDFrame object

# Output is a Series
In [2]: df.groupby(pd.TimeGrouper(key='date',
 ...:                          freq='M')).apply(lambda x: x[['value']].sum())
Out[2]:
date
2000-10-31  value    10
2000-11-30  value    13
dtype: int64 

新行为:

# Output is a Series
In [55]: df.groupby(pd.TimeGrouper(key='date',
 ...:                           freq='M')).apply(lambda x: x.value.sum())
Out[55]:
date
2000-10-31    10
2000-11-30    13
Freq: M, dtype: int64

# Output is a DataFrame
In [56]: df.groupby(pd.TimeGrouper(key='date',
 ...:                           freq='M')).apply(lambda x: x[['value']].sum())
Out[56]:
 value
date
2000-10-31     10
2000-11-30     13 
```  ### `read_csv`异常更改

为了使`read_csv` API 在`c`和`python`引擎上标准化,现在两者在遇到空列或标题时都会引发`EmptyDataError`,这是`ValueError`的子类([GH 12493](https://github.com/pandas-dev/pandas/issues/12493), [GH 12506](https://github.com/pandas-dev/pandas/issues/12506))

先前行为:

```py
In [1]: import io

In [2]: df = pd.read_csv(io.StringIO(''), engine='c')
...
ValueError: No columns to parse from file

In [3]: df = pd.read_csv(io.StringIO(''), engine='python')
...
StopIteration 

新行为:

In [1]: df = pd.read_csv(io.StringIO(''), engine='c')
...
pandas.io.common.EmptyDataError: No columns to parse from file

In [2]: df = pd.read_csv(io.StringIO(''), engine='python')
...
pandas.io.common.EmptyDataError: No columns to parse from file 

除了这个错误更改之外,还进行了其他几项更改:

  • CParserError现在是ValueError的子类,而不仅仅是ExceptionGH 12551)

  • c引擎无法解析列时,在read_csv中现在会引发CParserError而不是通用的ExceptionGH 12506)

  • c引擎在整数列中遇到NaN值时,read_csv现在会引发ValueError而不是通用的ExceptionGH 12506)

  • 当指定true_values时,在c引擎遇到包含无法编码字节的列中的元素时,read_csv现在会引发ValueError而不是通用的ExceptionGH 12506)

  • pandas.parser.OverflowError异常已被移除,并已被 Python 内置的OverflowError异常替换(GH 12506)

  • pd.read_csv()不再允许在usecols参数中组合字符串和整数(GH 12678) ### to_datetime方法错误更改

在传递可转换条目的 uniterrors='coerce'errors='ignore' 时,pd.to_datetime() 中存在错误。此外,当遇到超出范围的值时,将引发 OutOfBoundsDateime 异常,errors='raise'。 (GH 11758, GH 13052, GH 13059)

先前的行为:

In [27]: pd.to_datetime(1420043460, unit='s', errors='coerce')
Out[27]: NaT

In [28]: pd.to_datetime(11111111, unit='D', errors='ignore')
OverflowError: Python int too large to convert to C long

In [29]: pd.to_datetime(11111111, unit='D', errors='raise')
OverflowError: Python int too large to convert to C long 

新行为:

In [2]: pd.to_datetime(1420043460, unit='s', errors='coerce')
Out[2]: Timestamp('2014-12-31 16:31:00')

In [3]: pd.to_datetime(11111111, unit='D', errors='ignore')
Out[3]: 11111111

In [4]: pd.to_datetime(11111111, unit='D', errors='raise')
OutOfBoundsDatetime: cannot convert input with unit 'D' 
```  ### 其他 API 更改

+   对于 `Series`、`DataFrame`、`Panel` 和 `MultiIndex` 的 `.swaplevel()` 现在具有其前两个参数 `i` 和 `j` 的默认值,这两个参数交换索引的最内层级别。 ([GH 12934](https://github.com/pandas-dev/pandas/issues/12934))

+   `.searchsorted()` 对于 `Index` 和 `TimedeltaIndex` 现在接受一个 `sorter` 参数,以保持与 numpy 的 `searchsorted` 函数的兼容性 ([GH 12238](https://github.com/pandas-dev/pandas/issues/12238))

+   `Period` 和 `PeriodIndex` 现在会引发 `IncompatibleFrequency` 错误,该错误继承自 `ValueError` 而不是原始的 `ValueError` ([GH 12615](https://github.com/pandas-dev/pandas/issues/12615))

+   `Series.apply` 对于类别 dtype 现在将传递的函数应用于每个 `.categories`(而不是 `.codes`),并在可能的情况下返回 `category` dtype ([GH 12473](https://github.com/pandas-dev/pandas/issues/12473))

+   如果 `parse_dates` 不是布尔值、列表或字典(与文档字符串匹配),`read_csv` 现在会引发 `TypeError` ([GH 5636](https://github.com/pandas-dev/pandas/issues/5636))

+   `.query()/.eval()` 的默认值现在是 `engine=None`,如果安装了 `numexpr`,则会使用 `numexpr`;否则,它将回退到 `python` 引擎。这模仿了在 0.18.1 之前如果安装了 `numexpr` 的行为(以及以前,如果未安装 `numexpr`,`.query()/.eval()` 将引发异常)。 ([GH 12749](https://github.com/pandas-dev/pandas/issues/12749))

+   `pd.show_versions()` 现在包括 `pandas_datareader` 版本 ([GH 12740](https://github.com/pandas-dev/pandas/issues/12740))

+   为通用函数提供适当的 `__name__` 和 `__qualname__` 属性 ([GH 12021](https://github.com/pandas-dev/pandas/issues/12021))

+   `pd.concat(ignore_index=True)` 现在默认使用 `RangeIndex` ([GH 12695](https://github.com/pandas-dev/pandas/issues/12695))

+   当将单级与多级数据框合并/连接时,`pd.merge()` 和 `DataFrame.join()` 将显示 `UserWarning` 警告 ([GH 9455](https://github.com/pandas-dev/pandas/issues/9455), [GH 12219](https://github.com/pandas-dev/pandas/issues/12219))

+   与 `scipy` > 0.17 兼容的已弃用的 `piecewise_polynomial` 插值方法;支持替换的 `from_derivatives` 方法 ([GH 12887](https://github.com/pandas-dev/pandas/issues/12887))  ### 弃用

+   方法名 `Index.sym_diff()` 已弃用,可以用 `Index.symmetric_difference()` 替换 ([GH 12591](https://github.com/pandas-dev/pandas/issues/12591))

+   方法名`Categorical.sort()`已被弃用,推荐使用`Categorical.sort_values()` ([GH 12882](https://github.com/pandas-dev/pandas/issues/12882))  ## 性能改进

+   提升了 SAS 读取器的速度 ([GH 12656](https://github.com/pandas-dev/pandas/issues/12656), [GH 12961](https://github.com/pandas-dev/pandas/issues/12961))

+   在`.groupby(..).cumcount()`中的性能改进 ([GH 11039](https://github.com/pandas-dev/pandas/issues/11039))

+   在使用`skiprows=an_integer`时,改进了`pd.read_csv()`的内存使用情况 ([GH 13005](https://github.com/pandas-dev/pandas/issues/13005))

+   在检查表的大小写敏感性时,改进了`DataFrame.to_sql`的性能。现在只有在表名不是小写时才检查表是否已正确创建。 ([GH 12876](https://github.com/pandas-dev/pandas/issues/12876))

+   改进了`Period`构造和时间序列绘图的性能 ([GH 12903](https://github.com/pandas-dev/pandas/issues/12903), [GH 11831](https://github.com/pandas-dev/pandas/issues/11831))

+   提升了`.str.encode()`和`.str.decode()`方法的性能 ([GH 13008](https://github.com/pandas-dev/pandas/issues/13008))

+   如果输入是数值类型,则提升了`to_numeric`的性能 ([GH 12777](https://github.com/pandas-dev/pandas/issues/12777))

+   通过`IntIndex`进行稀疏运算的性能改进 ([GH 13036](https://github.com/pandas-dev/pandas/issues/13036))  ## Bug 修复

+   现在即使 CSV 文件的行数不均匀,`pd.read_csv`中的`usecols`参数也会被尊重 ([GH 12203](https://github.com/pandas-dev/pandas/issues/12203))

+   当指定`axis=1`且具有非单调有序索引时,`groupby.transform(..)`中的 bug 已被修复 ([GH 12713](https://github.com/pandas-dev/pandas/issues/12713))

+   如果指定`freq="Minute"`,则创建`Period`和`PeriodIndex`时会引发`KeyError`的 bug 已被修复。请注意,“Minute”频率在 v0.17.0 中已被弃用,建议改用`freq="T"` ([GH 11854](https://github.com/pandas-dev/pandas/issues/11854))

+   在使用`PeriodIndex`时,`.resample(...).count()`总是引发`TypeError`的 bug 已被修复 ([GH 12774](https://github.com/pandas-dev/pandas/issues/12774))

+   修复了当为空时,`.resample(...)`在将`PeriodIndex`转换为`DatetimeIndex`时的 bug ([GH 12868](https://github.com/pandas-dev/pandas/issues/12868))

+   修复了在将`PeriodIndex`重新采样到现有频率时,`.resample(...)`中的 bug ([GH 12770](https://github.com/pandas-dev/pandas/issues/12770))

+   包含不同`freq`的`Period`数据打印时引发`ValueError`的 bug 已被修复 ([GH 12615](https://github.com/pandas-dev/pandas/issues/12615))

+   修复了当指定`dtype='category'`时,使用`Categorical`构造`Series`时的 bug ([GH 12574](https://github.com/pandas-dev/pandas/issues/12574))

+   在具有可强制转换 dtype 的连接中存在错误,过于激进,导致当对象长于`display.max_rows`时,在输出格式化中出现不同的 dtype([GH 12411](https://github.com/pandas-dev/pandas/issues/12411), [GH 12045](https://github.com/pandas-dev/pandas/issues/12045), [GH 11594](https://github.com/pandas-dev/pandas/issues/11594), [GH 10571](https://github.com/pandas-dev/pandas/issues/10571), [GH 12211](https://github.com/pandas-dev/pandas/issues/12211))

+   在`float_format`选项中,选项未被验证为可调用的错误。([GH 12706](https://github.com/pandas-dev/pandas/issues/12706))

+   在`GroupBy.filter`中,当`dropna=False`且没有组满足条件时存在错误([GH 12768](https://github.com/pandas-dev/pandas/issues/12768))

+   在`.cum*`函数的`__name__`中存在错误([GH 12021](https://github.com/pandas-dev/pandas/issues/12021))

+   在将`Float64Inde/Int64Index`转换为`Int64Index`的`.astype()`中存在错误([GH 12881](https://github.com/pandas-dev/pandas/issues/12881))

+   在`.to_json()/.read_json()`中整数索引的往返处理中存在错误,当`orient='index'`(默认)时([GH 12866](https://github.com/pandas-dev/pandas/issues/12866))

+   在绘制`Categorical` dtypes 时,当尝试堆叠条形图时导致错误([GH 13019](https://github.com/pandas-dev/pandas/issues/13019))

+   与`numpy` 1.11 兼容,用于`NaT`比较([GH 12969](https://github.com/pandas-dev/pandas/issues/12969))

+   在具有非唯一`MultiIndex`的`.drop()`中存在的错误。([GH 12701](https://github.com/pandas-dev/pandas/issues/12701))

+   在具有 datetime tz-aware 和 naive DataFrames 的`.concat`中存在错误([GH 12467](https://github.com/pandas-dev/pandas/issues/12467))

+   在传递非字符串时,在`.resample(..).fillna(..)`中正确引发`ValueError`的错误([GH 12952](https://github.com/pandas-dev/pandas/issues/12952))

+   在`pd.read_sas()`中存在各种编码和标题处理问题的错误修复([GH 12659](https://github.com/pandas-dev/pandas/issues/12659), [GH 12654](https://github.com/pandas-dev/pandas/issues/12654), [GH 12647](https://github.com/pandas-dev/pandas/issues/12647), [GH 12809](https://github.com/pandas-dev/pandas/issues/12809))

+   在`pd.crosstab()`中,如果`values=None`,则会悄悄忽略`aggfunc`([GH 12569](https://github.com/pandas-dev/pandas/issues/12569)).

+   在序列化`datetime.time`时,在`DataFrame.to_json`中存在潜在段错误([GH 11473](https://github.com/pandas-dev/pandas/issues/11473)).

+   在尝试序列化 0d 数组时,在`DataFrame.to_json`中存在潜在段错误([GH 11299](https://github.com/pandas-dev/pandas/issues/11299)).

+   在尝试序列化具有非 ndarray 值的`DataFrame`或`Series`时,在`to_json`中出现段错误;现在支持`category`、`sparse`和`datetime64[ns, tz]` dtypes 的序列化([GH 10778](https://github.com/pandas-dev/pandas/issues/10778))。

+   在不支持的 dtype 未传递给默认处理程序的`DataFrame.to_json`中存在错误([GH 12554](https://github.com/pandas-dev/pandas/issues/12554)).

+   `.align` 中的 Bug,未返回子类 ([GH 12983](https://github.com/pandas-dev/pandas/issues/12983))

+   将 `Series` 与 `DataFrame` 对齐时的 Bug ([GH 13037](https://github.com/pandas-dev/pandas/issues/13037))

+   `ABCPanel` 中的 Bug,`Panel4D` 未被视为该泛型类型的有效实例 ([GH 12810](https://github.com/pandas-dev/pandas/issues/12810))

+   `.groupby(..).apply(..)` 情况下 `.name` 的一致性 Bug ([GH 12363](https://github.com/pandas-dev/pandas/issues/12363))

+   `Timestamp.__repr__` 中的 Bug,导致嵌套结构中的 `pprint` 失败 ([GH 12622](https://github.com/pandas-dev/pandas/issues/12622))

+   `Timedelta.min` 和 `Timedelta.max` 中的 Bug,这些属性现在报告 pandas 认可的真正最小/最大 `timedeltas`。参见文档 ([GH 12727](https://github.com/pandas-dev/pandas/issues/12727))

+   `.quantile()` 中的 Bug,在插值时可能意外转换为 `float` ([GH 12772](https://github.com/pandas-dev/pandas/issues/12772))

+   `.quantile()` 中的 Bug,当 `Series` 为空时可能返回标量而不是空的 `Series` ([GH 12772](https://github.com/pandas-dev/pandas/issues/12772))

+   `.loc` 中的 Bug,在大型索引器中的越界会引发 `IndexError` 而不是 `KeyError` ([GH 12527](https://github.com/pandas-dev/pandas/issues/12527))

+   在使用 `TimedeltaIndex` 和 `.asfreq()` 进行重新采样时的 Bug,以前不包括最后一个标杆点 ([GH 12926](https://github.com/pandas-dev/pandas/issues/12926))

+   在 `DataFrame` 中使用 `Categorical` 进行相等性测试的 Bug ([GH 12564](https://github.com/pandas-dev/pandas/issues/12564))

+   `GroupBy.first()` 中的 Bug,当使用 `TimeGrouper` 时,`.last()` 返回错误行 ([GH 7453](https://github.com/pandas-dev/pandas/issues/7453))

+   在使用 `c` 引擎的 `pd.read_csv()` 中,当在引号项中指定 `skiprows` 时出现换行符 ([GH 10911](https://github.com/pandas-dev/pandas/issues/10911), [GH 12775](https://github.com/pandas-dev/pandas/issues/12775))

+   `DataFrame` 在赋值时丢失时区信息的 Bug,当赋值为带时区信息的 datetime `Series` 时出现对齐问题 ([GH 12981](https://github.com/pandas-dev/pandas/issues/12981))

+   `.value_counts()` 中的 Bug,在 `normalize=True` 和 `dropna=True` 时,null 仍然会对规范化计数产生影响 ([GH 12558](https://github.com/pandas-dev/pandas/issues/12558))

+   `Series.value_counts()` 中的 Bug,在其 dtype 为 `category` 时会丢失名称 ([GH 12835](https://github.com/pandas-dev/pandas/issues/12835))

+   `Series.value_counts()` 中的 Bug,丢失时区信息 ([GH 12835](https://github.com/pandas-dev/pandas/issues/12835))

+   `Series.value_counts(normalize=True)` 中的 Bug,当 `Categorical` 时会引发 `UnboundLocalError` ([GH 12835](https://github.com/pandas-dev/pandas/issues/12835))

+   `Panel.fillna()` 中的 Bug,忽略了 `inplace=True` ([GH 12633](https://github.com/pandas-dev/pandas/issues/12633))

+   在使用 `c` 引擎同时指定 `names`、`usecols` 和 `parse_dates` 时,`pd.read_csv()` 中的错误([GH 9755](https://github.com/pandas-dev/pandas/issues/9755))

+   在使用 `c` 引擎同时指定 `delim_whitespace=True` 和 `lineterminator` 时,`pd.read_csv()` 中的错误([GH 12912](https://github.com/pandas-dev/pandas/issues/12912))

+   `Series.rename`、`DataFrame.rename` 和 `DataFrame.rename_axis` 中的错误,不将 `Series` 视为映射以重新标记([GH 12623](https://github.com/pandas-dev/pandas/issues/12623))

+   在 `.rolling.min` 和 `.rolling.max` 中进行清理以增强 dtype 处理([GH 12373](https://github.com/pandas-dev/pandas/issues/12373))

+   在 `groupby` 中,复杂类型被强制转换为浮点数的错误([GH 12902](https://github.com/pandas-dev/pandas/issues/12902))

+   如果 `Series.map` 的 dtype 为 `category` 或 tz-aware `datetime`,则会引发 `TypeError` 的错误([GH 12473](https://github.com/pandas-dev/pandas/issues/12473))

+   一些测试比较在 32 位平台上的错误([GH 12972](https://github.com/pandas-dev/pandas/issues/12972))

+   从 `RangeIndex` 构造中回退时的索引强制转换错误([GH 12893](https://github.com/pandas-dev/pandas/issues/12893))

+   在窗口函数中传递无效参数(例如浮点窗口)时提供更好的错误消息([GH 12669](https://github.com/pandas-dev/pandas/issues/12669))

+   在定义为返回子类化 `Series` 的子类化 `DataFrame` 中切片时可能返回普通 `Series` 的错误([GH 11559](https://github.com/pandas-dev/pandas/issues/11559))

+   `.str` 访问器方法中的错误可能会在输入具有 `name` 且结果为 `DataFrame` 或 `MultiIndex` 时引发 `ValueError`([GH 12617](https://github.com/pandas-dev/pandas/issues/12617))

+   在空框架上的 `DataFrame.last_valid_index()` 和 `DataFrame.first_valid_index()` 中的错误([GH 12800](https://github.com/pandas-dev/pandas/issues/12800))

+   `CategoricalIndex.get_loc` 中的错误返回与常规 `Index` 不同([GH 12531](https://github.com/pandas-dev/pandas/issues/12531))

+   `PeriodIndex.resample` 中的错误,名称未传播([GH 12769](https://github.com/pandas-dev/pandas/issues/12769))

+   `date_range` 中 `closed` 关键字和时区的错误([GH 12684](https://github.com/pandas-dev/pandas/issues/12684))

+   当输入数据包含 tz-aware datetime 和 timedelta 时,`pd.concat` 中引发 `AttributeError` 的错误([GH 12620](https://github.com/pandas-dev/pandas/issues/12620))

+   `pd.concat` 未正确处理空 `Series` 的错误([GH 11082](https://github.com/pandas-dev/pandas/issues/11082))

+   当使用 `int` 指定 `width` 时,`.plot.bar` 对齐的错误([GH 12979](https://github.com/pandas-dev/pandas/issues/12979))

+   如果二元运算符的参数是常量,则忽略 `fill_value` 的错误([GH 12723](https://github.com/pandas-dev/pandas/issues/12723))

+   使用 bs4 风格和解析具有标题和仅一列的表时,`pd.read_html()` 中的错误([GH 9178](https://github.com/pandas-dev/pandas/issues/9178))

+   修复了当 `margins=True` 和 `dropna=True` 时 `.pivot_table` 中空值仍然会影响边际计数的错误([GH 12577](https://github.com/pandas-dev/pandas/issues/12577))

+   修复了当 `dropna=False` 时 `.pivot_table` 中表索引/列名称消失的错误([GH 12133](https://github.com/pandas-dev/pandas/issues/12133))

+   修复了当 `margins=True` 和 `dropna=False` 时 `pd.crosstab()` 中引发的错误([GH 12642](https://github.com/pandas-dev/pandas/issues/12642))

+   修复了当 `name` 属性可以是可哈希类型时 `Series.name` 的错误([GH 12610](https://github.com/pandas-dev/pandas/issues/12610))

+   修复了 `.describe()` 重置分类列信息的错误([GH 11558](https://github.com/pandas-dev/pandas/issues/11558))

+   修复了在时间序列上调用 `resample().count()` 时未应用 `loffset` 参数的错误([GH 12725](https://github.com/pandas-dev/pandas/issues/12725))

+   `pd.read_excel()` 现在接受与关键字参数 `names` 关联的列名([GH 12870](https://github.com/pandas-dev/pandas/issues/12870))

+   修复了 `pd.to_numeric()` 在返回 `np.ndarray` 而不是 `Index` 时的错误([GH 12777](https://github.com/pandas-dev/pandas/issues/12777))

+   修复了 `pd.to_numeric()` 在类似日期时间的情况下可能引发 `TypeError` 的错误([GH 12777](https://github.com/pandas-dev/pandas/issues/12777))

+   修复了当标量使用 `pd.to_numeric()` 时引发 `ValueError` 的错误([GH 12777](https://github.com/pandas-dev/pandas/issues/12777))  ## 贡献者

总共有 60 人为此版本贡献了补丁。名字后面带有“+”的人是第一次贡献补丁。

+   Andrew Fiore-Gartland +

+   Bastiaan +

+   Benoît Vinot +

+   Brandon Rhodes +

+   DaCoEx +

+   Drew Fustin +

+   Ernesto Freitas +

+   Filip Ter +

+   Gregory Livschitz +

+   Gábor Lipták

+   Hassan Kibirige +

+   Iblis Lin

+   Israel Saeta Pérez +

+   Jason Wolosonovich +

+   Jeff Reback

+   Joe Jevnik

+   Joris Van den Bossche

+   Joshua Storck +

+   Ka Wo Chen

+   Kerby Shedden

+   Kieran O’Mahony

+   Leif Walsh +

+   Mahmoud Lababidi +

+   Maoyuan Liu +

+   Mark Roth +

+   Matt Wittmann

+   MaxU +

+   Maximilian Roos

+   Michael Droettboom +

+   Nick Eubank

+   Nicolas Bonnotte

+   OXPHOS +

+   Pauli Virtanen +

+   Peter Waller +

+   Pietro Battiston

+   Prabhjot Singh +

+   Robin Wilson

+   Roger Thomas +

+   Sebastian Bank

+   Stephen Hoover

+   Tim Hopper +

+   Tom Augspurger

+   王爱勇

+   Wes Turner

+   Winand +

+   Xbar +

+   Yan Facai +

+   adneu +

+   ajenkins-cargometrics +

+   behzad nouri

+   chinskiy +

+   gfyoung

+   jeps-journal +

+   jonaslb +

+   kotrfa +

+   nileracecrew +

+   onesandzeroes

+   rs2 +

+   sinhrks

+   tsdlovell +  ## 新功能

### 自定义营业时间

`CustomBusinessHour` 是 `BusinessHour` 和 `CustomBusinessDay` 的混合体,允许您指定任意假期。详情请参阅自定义营业时间([GH 11514](https://github.com/pandas-dev/pandas/issues/11514))

```py
In [1]: from pandas.tseries.offsets import CustomBusinessHour

In [2]: from pandas.tseries.holiday import USFederalHolidayCalendar

In [3]: bhour_us = CustomBusinessHour(calendar=USFederalHolidayCalendar()) 

马丁路德金日前的星期五

In [4]: import datetime

In [5]: dt = datetime.datetime(2014, 1, 17, 15)

In [6]: dt + bhour_us
Out[6]: Timestamp('2014-01-17 16:00:00') 

马丁路德金日后的星期二(星期一被跳过,因为那是一个假期)

In [7]: dt + bhour_us * 2
Out[7]: Timestamp('2014-01-20 09:00:00') 
```  ### 方法 `.groupby(..)` 语法与窗口和重采样操作

`.groupby(...)` 已经增强,以提供在每个分组上使用 `.rolling(..)`、`.expanding(..)` 和 `.resample(..)` 时方便的语法,请参见 ([GH 12486](https://github.com/pandas-dev/pandas/issues/12486), [GH 12738](https://github.com/pandas-dev/pandas/issues/12738))。

你现在可以在分组上使用 `.rolling(..)` 和 `.expanding(..)` 作为方法。这些返回另一个延迟对象(类似于在未分组的 pandas 对象上所做的 `.rolling()` 和 `.expanding()`)。然后,你可以以类似的方式操作这些 `RollingGroupby` 对象。

以前,你必须这样做才能得到每个分组的滚动窗口均值:

```py
In [8]: df = pd.DataFrame({"A": [1] * 20 + [2] * 12 + [3] * 8, "B": np.arange(40)})

In [9]: df
Out[9]: 
 A   B
0   1   0
1   1   1
2   1   2
3   1   3
4   1   4
.. ..  ..
35  3  35
36  3  36
37  3  37
38  3  38
39  3  39

[40 rows x 2 columns] 
In [1]: df.groupby("A").apply(lambda x: x.rolling(4).B.mean())
Out[1]:
A
1  0      NaN
 1      NaN
 2      NaN
 3      1.5
 4      2.5
 5      3.5
 6      4.5
 7      5.5
 8      6.5
 9      7.5
 10     8.5
 11     9.5
 12    10.5
 13    11.5
 14    12.5
 15    13.5
 16    14.5
 17    15.5
 18    16.5
 19    17.5
2  20     NaN
 21     NaN
 22     NaN
 23    21.5
 24    22.5
 25    23.5
 26    24.5
 27    25.5
 28    26.5
 29    27.5
 30    28.5
 31    29.5
3  32     NaN
 33     NaN
 34     NaN
 35    33.5
 36    34.5
 37    35.5
 38    36.5
 39    37.5
Name: B, dtype: float64 

现在你可以这样做:

In [10]: df.groupby("A").rolling(4).B.mean()
Out[10]: 
A 
1  0      NaN
 1      NaN
 2      NaN
 3      1.5
 4      2.5
 ... 
3  35    33.5
 36    34.5
 37    35.5
 38    36.5
 39    37.5
Name: B, Length: 40, dtype: float64 

对于 .resample(..) 类型的操作,以前你必须:

In [11]: df = pd.DataFrame(
 ....:    {
 ....:        "date": pd.date_range(start="2016-01-01", periods=4, freq="W"),
 ....:        "group": [1, 1, 2, 2],
 ....:        "val": [5, 6, 7, 8],
 ....:    }
 ....: ).set_index("date")
 ....: 

In [12]: df
Out[12]: 
 group  val
date 
2016-01-03      1    5
2016-01-10      1    6
2016-01-17      2    7
2016-01-24      2    8

[4 rows x 2 columns] 
In[1]: df.groupby("group").apply(lambda x: x.resample("1D").ffill())
Out[1]:
                  group  val
group date
1     2016-01-03      1    5
      2016-01-04      1    5
      2016-01-05      1    5
      2016-01-06      1    5
      2016-01-07      1    5
      2016-01-08      1    5
      2016-01-09      1    5
      2016-01-10      1    6
2     2016-01-17      2    7
      2016-01-18      2    7
      2016-01-19      2    7
      2016-01-20      2    7
      2016-01-21      2    7
      2016-01-22      2    7
      2016-01-23      2    7
      2016-01-24      2    8 

现在你可以这样做:

In[1]: df.groupby("group").resample("1D").ffill()
Out[1]:
                  group  val
group date
1     2016-01-03      1    5
      2016-01-04      1    5
      2016-01-05      1    5
      2016-01-06      1    5
      2016-01-07      1    5
      2016-01-08      1    5
      2016-01-09      1    5
      2016-01-10      1    6
2     2016-01-17      2    7
      2016-01-18      2    7
      2016-01-19      2    7
      2016-01-20      2    7
      2016-01-21      2    7
      2016-01-22      2    7
      2016-01-23      2    7
      2016-01-24      2    8 
```  ### 方法链接改进

下列方法 / 索引器现在接受一个 `callable`。这意在使它们在方法链中更加有用,详见文档。 ([GH 11485](https://github.com/pandas-dev/pandas/issues/11485), [GH 12533](https://github.com/pandas-dev/pandas/issues/12533))

+   `.where()` 和 `.mask()`

+   `.loc[]`、`iloc[]` 和 `.ix[]`

+   `[]` 索引

#### 方法 `.where()` 和 `.mask()`

这些可以接受一个可调用函数作为条件和 `other` 参数。

```py
In [13]: df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})

In [14]: df.where(lambda x: x > 4, lambda x: x + 10)
Out[14]: 
 A   B  C
0  11  14  7
1  12   5  8
2  13   6  9

[3 rows x 3 columns] 

方法 .loc[].iloc[].ix[]

这些可以接受一个可调用函数,以及一个可调用函数的元组作为切片器。可调用函数可以返回一个有效的布尔索引器或对于这些索引器的输入有效的任何内容。

# callable returns bool indexer
In [15]: df.loc[lambda x: x.A >= 2, lambda x: x.sum() > 10]
Out[15]: 
 B  C
1  5  8
2  6  9

[2 rows x 2 columns]

# callable returns list of labels
In [16]: df.loc[lambda x: [1, 2], lambda x: ["A", "B"]]
Out[16]: 
 A  B
1  2  5
2  3  6

[2 rows x 2 columns] 

使用 [] 进行索引

最后,你可以在 Series、DataFrame 和 Panel 的 [] 索引中使用可调用的函数。这个可调用函数必须根据其类和索引类型返回一个有效的 [] 索引的输入。

In [17]: df[lambda x: "A"]
Out[17]: 
0    1
1    2
2    3
Name: A, Length: 3, dtype: int64 

使用这些方法 / 索引器,你可以在不使用临时变量的情况下链式进行数据选择操作。

In [18]: bb = pd.read_csv("data/baseball.csv", index_col="id")

In [19]: (bb.groupby(["year", "team"]).sum(numeric_only=True).loc[lambda df: df.r > 100])
Out[19]: 
 stint    g    ab    r    h  X2b  ...     so   ibb   hbp    sh    sf  gidp
year team                                   ... 
2007 CIN       6  379   745  101  203   35  ...  127.0  14.0   1.0   1.0  15.0  18.0
 DET       5  301  1062  162  283   54  ...  176.0   3.0  10.0   4.0   8.0  28.0
 HOU       4  311   926  109  218   47  ...  212.0   3.0   9.0  16.0   6.0  17.0
 LAN      11  413  1021  153  293   61  ...  141.0   8.0   9.0   3.0   8.0  29.0
 NYN      13  622  1854  240  509  101  ...  310.0  24.0  23.0  18.0  15.0  48.0
 SFN       5  482  1305  198  337   67  ...  188.0  51.0   8.0  16.0   6.0  41.0
 TEX       2  198   729  115  200   40  ...  140.0   4.0   5.0   2.0   8.0  16.0
 TOR       4  459  1408  187  378   96  ...  265.0  16.0  12.0   4.0  16.0  38.0

[8 rows x 18 columns] 
```  ### 在 `MultiIndex` 的一部分是 `DatetimeIndex` 上的部分字符串索引

部分字符串索引现在匹配 `MultiIndex` 的一部分是 `DateTimeIndex` ([GH 10331](https://github.com/pandas-dev/pandas/issues/10331))

```py
In [20]: dft2 = pd.DataFrame(
 ....:    np.random.randn(20, 1),
 ....:    columns=["A"],
 ....:    index=pd.MultiIndex.from_product(
 ....:        [pd.date_range("20130101", periods=10, freq="12H"), ["a", "b"]]
 ....:    ),
 ....: )
 ....:

In [21]: dft2
Out[21]:
 A
2013-01-01 00:00:00 a  0.469112
 b -0.282863
2013-01-01 12:00:00 a -1.509059
 b -1.135632
2013-01-02 00:00:00 a  1.212112
...                         ...
2013-01-04 12:00:00 b  0.271860
2013-01-05 00:00:00 a -0.424972
 b  0.567020
2013-01-05 12:00:00 a  0.276232
 b -1.087401

[20 rows x 1 columns]

In [22]: dft2.loc["2013-01-05"]
Out[22]:
 A
2013-01-05 00:00:00 a -0.424972
 b  0.567020
2013-01-05 12:00:00 a  0.276232
 b -1.087401

[4 rows x 1 columns] 

在其他级别上

In [26]: idx = pd.IndexSlice

In [27]: dft2 = dft2.swaplevel(0, 1).sort_index()

In [28]: dft2
Out[28]:
 A
a 2013-01-01 00:00:00  0.469112
 2013-01-01 12:00:00 -1.509059
 2013-01-02 00:00:00  1.212112
 2013-01-02 12:00:00  0.119209
 2013-01-03 00:00:00 -0.861849
...                         ...
b 2013-01-03 12:00:00  1.071804
 2013-01-04 00:00:00 -0.706771
 2013-01-04 12:00:00  0.271860
 2013-01-05 00:00:00  0.567020
 2013-01-05 12:00:00 -1.087401

[20 rows x 1 columns]

In [29]: dft2.loc[idx[:, "2013-01-05"], :]
Out[29]:
 A
a 2013-01-05 00:00:00 -0.424972
 2013-01-05 12:00:00  0.276232
b 2013-01-05 00:00:00  0.567020
 2013-01-05 12:00:00 -1.087401

[4 rows x 1 columns] 
```  ### 组装日期时间

`pd.to_datetime()` 现在具有从传递的 `DataFrame` 或字典中组装日期时间的能力 ([GH 8158](https://github.com/pandas-dev/pandas/issues/8158)).

```py
In [20]: df = pd.DataFrame(
 ....:    {"year": [2015, 2016], "month": [2, 3], "day": [4, 5], "hour": [2, 3]}
 ....: )
 ....: 

In [21]: df
Out[21]: 
 year  month  day  hour
0  2015      2    4     2
1  2016      3    5     3

[2 rows x 4 columns] 

使用传递的框架进行组装。

In [22]: pd.to_datetime(df)
Out[22]: 
0   2015-02-04 02:00:00
1   2016-03-05 03:00:00
Length: 2, dtype: datetime64[ns] 

你只需要传递你需要组装的列。

In [23]: pd.to_datetime(df[["year", "month", "day"]])
Out[23]: 
0   2015-02-04
1   2016-03-05
Length: 2, dtype: datetime64[ns] 
```  ### 其他增强

+   `pd.read_csv()` 现在支持 Python 引擎的 `delim_whitespace=True` ([GH 12958](https://github.com/pandas-dev/pandas/issues/12958))

+   `pd.read_csv()` 现在支持打开包含单个 CSV 的 ZIP 文件,通过扩展推断或明确指定 `compression='zip'` ([GH 12175](https://github.com/pandas-dev/pandas/issues/12175))

+   `pd.read_csv()` 现在支持使用 xz 压缩打开文件,通过扩展推断或明确指定 `compression='xz'`;`xz` 压缩也同样被 `DataFrame.to_csv` 支持,方式相同 ([GH 11852](https://github.com/pandas-dev/pandas/issues/11852))

+   `pd.read_msgpack()`现在即使使用压缩,也始终返回可写入的 ndarrays ([GH 12359](https://github.com/pandas-dev/pandas/issues/12359)).

+   `pd.read_msgpack()`现在支持使用 msgpack 序列化和反序列化分类变量 ([GH 12573](https://github.com/pandas-dev/pandas/issues/12573))

+   `.to_json()`现在支持包含分类和稀疏数据的`NDFrames` ([GH 10778](https://github.com/pandas-dev/pandas/issues/10778))

+   `interpolate()`现在支持`method='akima'` ([GH 7588](https://github.com/pandas-dev/pandas/issues/7588)).

+   `pd.read_excel()`现在接受路径对象(例如`pathlib.Path`、`py.path.local`)作为文件路径,与其他`read_*`函数保持一致 ([GH 12655](https://github.com/pandas-dev/pandas/issues/12655))

+   添加了`.weekday_name`属性作为`DatetimeIndex`和`.dt`访问器的组成部分。 ([GH 11128](https://github.com/pandas-dev/pandas/issues/11128))

+   `Index.take`现在一致处理`allow_fill`和`fill_value` ([GH 12631](https://github.com/pandas-dev/pandas/issues/12631))

    ```py
    In [24]: idx = pd.Index([1.0, 2.0, 3.0, 4.0], dtype="float")

    # default, allow_fill=True, fill_value=None
    In [25]: idx.take([2, -1])
    Out[25]: Index([3.0, 4.0], dtype='float64')

    In [26]: idx.take([2, -1], fill_value=True)
    Out[26]: Index([3.0, nan], dtype='float64') 
    ```

+   `Index`现在支持`.str.get_dummies()`,返回`MultiIndex`,参见 Creating Indicator Variables ([GH 10008](https://github.com/pandas-dev/pandas/issues/10008), [GH 10103](https://github.com/pandas-dev/pandas/issues/10103))

    ```py
    In [27]: idx = pd.Index(["a|b", "a|c", "b|c"])

    In [28]: idx.str.get_dummies("|")
    Out[28]: 
    MultiIndex([(1, 1, 0),
     (1, 0, 1),
     (0, 1, 1)],
     names=['a', 'b', 'c']) 
    ```

+   `pd.crosstab()`增加了一个`normalize`参数,用于规范化频率表 ([GH 12569](https://github.com/pandas-dev/pandas/issues/12569)). 更新文档中的示例在这里.

+   `.resample(..).interpolate()`现在受支持 ([GH 12925](https://github.com/pandas-dev/pandas/issues/12925))

+   `.isin()`现在接受传递的`sets` ([GH 12988](https://github.com/pandas-dev/pandas/issues/12988))  ### 自定义工作时间

`CustomBusinessHour`是`BusinessHour`和`CustomBusinessDay`的混合体,允许您指定任意假期。详情请参见 Custom Business Hour ([GH 11514](https://github.com/pandas-dev/pandas/issues/11514))

```py
In [1]: from pandas.tseries.offsets import CustomBusinessHour

In [2]: from pandas.tseries.holiday import USFederalHolidayCalendar

In [3]: bhour_us = CustomBusinessHour(calendar=USFederalHolidayCalendar()) 

MLK 日前的星期五

In [4]: import datetime

In [5]: dt = datetime.datetime(2014, 1, 17, 15)

In [6]: dt + bhour_us
Out[6]: Timestamp('2014-01-17 16:00:00') 

MLK 日后的星期二(星期一被跳过,因为那是个假日)

In [7]: dt + bhour_us * 2
Out[7]: Timestamp('2014-01-20 09:00:00') 

方法.groupby(..)语法与窗口和重新采样操作

.groupby(...)已经增强,提供了方便的语法,用于在每个组中使用.rolling(..).expanding(..).resample(..),参见(GH 12486, GH 12738).

现在您可以在 groupbys 上使用.rolling(..).expanding(..)作为方法。这些返回另一个延迟对象(类似于在未分组的 pandas 对象上执行的.rolling().expanding())。然后,您可以以类似的方式操作这些RollingGroupby对象。

以前你需要这样做才能获得��组的滚动窗口均值:

In [8]: df = pd.DataFrame({"A": [1] * 20 + [2] * 12 + [3] * 8, "B": np.arange(40)})

In [9]: df
Out[9]: 
 A   B
0   1   0
1   1   1
2   1   2
3   1   3
4   1   4
.. ..  ..
35  3  35
36  3  36
37  3  37
38  3  38
39  3  39

[40 rows x 2 columns] 
In [1]: df.groupby("A").apply(lambda x: x.rolling(4).B.mean())
Out[1]:
A
1  0      NaN
 1      NaN
 2      NaN
 3      1.5
 4      2.5
 5      3.5
 6      4.5
 7      5.5
 8      6.5
 9      7.5
 10     8.5
 11     9.5
 12    10.5
 13    11.5
 14    12.5
 15    13.5
 16    14.5
 17    15.5
 18    16.5
 19    17.5
2  20     NaN
 21     NaN
 22     NaN
 23    21.5
 24    22.5
 25    23.5
 26    24.5
 27    25.5
 28    26.5
 29    27.5
 30    28.5
 31    29.5
3  32     NaN
 33     NaN
 34     NaN
 35    33.5
 36    34.5
 37    35.5
 38    36.5
 39    37.5
Name: B, dtype: float64 

现在你可以这样做:

In [10]: df.groupby("A").rolling(4).B.mean()
Out[10]: 
A 
1  0      NaN
 1      NaN
 2      NaN
 3      1.5
 4      2.5
 ... 
3  35    33.5
 36    34.5
 37    35.5
 38    36.5
 39    37.5
Name: B, Length: 40, dtype: float64 

对于.resample(..)类型的操作,以前你需要:

In [11]: df = pd.DataFrame(
 ....:    {
 ....:        "date": pd.date_range(start="2016-01-01", periods=4, freq="W"),
 ....:        "group": [1, 1, 2, 2],
 ....:        "val": [5, 6, 7, 8],
 ....:    }
 ....: ).set_index("date")
 ....: 

In [12]: df
Out[12]: 
 group  val
date 
2016-01-03      1    5
2016-01-10      1    6
2016-01-17      2    7
2016-01-24      2    8

[4 rows x 2 columns] 
In[1]: df.groupby("group").apply(lambda x: x.resample("1D").ffill())
Out[1]:
                  group  val
group date
1     2016-01-03      1    5
      2016-01-04      1    5
      2016-01-05      1    5
      2016-01-06      1    5
      2016-01-07      1    5
      2016-01-08      1    5
      2016-01-09      1    5
      2016-01-10      1    6
2     2016-01-17      2    7
      2016-01-18      2    7
      2016-01-19      2    7
      2016-01-20      2    7
      2016-01-21      2    7
      2016-01-22      2    7
      2016-01-23      2    7
      2016-01-24      2    8 

现在你可以这样做:

In[1]: df.groupby("group").resample("1D").ffill()
Out[1]:
                  group  val
group date
1     2016-01-03      1    5
      2016-01-04      1    5
      2016-01-05      1    5
      2016-01-06      1    5
      2016-01-07      1    5
      2016-01-08      1    5
      2016-01-09      1    5
      2016-01-10      1    6
2     2016-01-17      2    7
      2016-01-18      2    7
      2016-01-19      2    7
      2016-01-20      2    7
      2016-01-21      2    7
      2016-01-22      2    7
      2016-01-23      2    7
      2016-01-24      2    8 

方法链改进

以下方法/索引器现在接受 callable。旨在使它们在方法链中更加实用,详见文档(GH 11485, GH 12533)。

  • .where().mask()

  • .loc[]iloc[].ix[]

  • [] 索引

方法 .where().mask()

这些可以接受条件和 other 参数的可调用对象。

In [13]: df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})

In [14]: df.where(lambda x: x > 4, lambda x: x + 10)
Out[14]: 
 A   B  C
0  11  14  7
1  12   5  8
2  13   6  9

[3 rows x 3 columns] 

方法 .loc[].iloc[].ix[]

这些可以接受一个可调用对象,以及一个切片器的元组。可调用对象可以返回有效的布尔索引器或适用于这些索引器输入的任何内容。

# callable returns bool indexer
In [15]: df.loc[lambda x: x.A >= 2, lambda x: x.sum() > 10]
Out[15]: 
 B  C
1  5  8
2  6  9

[2 rows x 2 columns]

# callable returns list of labels
In [16]: df.loc[lambda x: [1, 2], lambda x: ["A", "B"]]
Out[16]: 
 A  B
1  2  5
2  3  6

[2 rows x 2 columns] 

使用 [] 进行索引

最后,你可以在 Series、DataFrame 和 Panel 的 [] 索引中使用可调用对象。可调用对象必须根据其类别和索引类型返回 [] 索引的有效输入。

In [17]: df[lambda x: "A"]
Out[17]: 
0    1
1    2
2    3
Name: A, Length: 3, dtype: int64 

使用这些方法/索引器,你可以在不使用临时变量的情况下链接数据选择操作。

In [18]: bb = pd.read_csv("data/baseball.csv", index_col="id")

In [19]: (bb.groupby(["year", "team"]).sum(numeric_only=True).loc[lambda df: df.r > 100])
Out[19]: 
 stint    g    ab    r    h  X2b  ...     so   ibb   hbp    sh    sf  gidp
year team                                   ... 
2007 CIN       6  379   745  101  203   35  ...  127.0  14.0   1.0   1.0  15.0  18.0
 DET       5  301  1062  162  283   54  ...  176.0   3.0  10.0   4.0   8.0  28.0
 HOU       4  311   926  109  218   47  ...  212.0   3.0   9.0  16.0   6.0  17.0
 LAN      11  413  1021  153  293   61  ...  141.0   8.0   9.0   3.0   8.0  29.0
 NYN      13  622  1854  240  509  101  ...  310.0  24.0  23.0  18.0  15.0  48.0
 SFN       5  482  1305  198  337   67  ...  188.0  51.0   8.0  16.0   6.0  41.0
 TEX       2  198   729  115  200   40  ...  140.0   4.0   5.0   2.0   8.0  16.0
 TOR       4  459  1408  187  378   96  ...  265.0  16.0  12.0   4.0  16.0  38.0

[8 rows x 18 columns] 

方法 .where().mask()

这些可以接受条件和 other 参数的可调用对象。

In [13]: df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})

In [14]: df.where(lambda x: x > 4, lambda x: x + 10)
Out[14]: 
 A   B  C
0  11  14  7
1  12   5  8
2  13   6  9

[3 rows x 3 columns] 

方法 .loc[].iloc[].ix[]

这些可以接受一个可调用对象,以及一个切片器的元组。可调用对象可以返回有效的布尔索引器或适用于这些索引器输入的任何内容。

# callable returns bool indexer
In [15]: df.loc[lambda x: x.A >= 2, lambda x: x.sum() > 10]
Out[15]: 
 B  C
1  5  8
2  6  9

[2 rows x 2 columns]

# callable returns list of labels
In [16]: df.loc[lambda x: [1, 2], lambda x: ["A", "B"]]
Out[16]: 
 A  B
1  2  5
2  3  6

[2 rows x 2 columns] 

使用 [] 进行索引

最后,你可以在 Series、DataFrame 和 Panel 的 [] 索引中使用可调用对象。可调用对象必须根据其类别和索引类型返回 [] 索引的有效输入。

In [17]: df[lambda x: "A"]
Out[17]: 
0    1
1    2
2    3
Name: A, Length: 3, dtype: int64 

使用这些方法/索引器,你可以在不使用临时变量的情况下链接数据选择操作。

In [18]: bb = pd.read_csv("data/baseball.csv", index_col="id")

In [19]: (bb.groupby(["year", "team"]).sum(numeric_only=True).loc[lambda df: df.r > 100])
Out[19]: 
 stint    g    ab    r    h  X2b  ...     so   ibb   hbp    sh    sf  gidp
year team                                   ... 
2007 CIN       6  379   745  101  203   35  ...  127.0  14.0   1.0   1.0  15.0  18.0
 DET       5  301  1062  162  283   54  ...  176.0   3.0  10.0   4.0   8.0  28.0
 HOU       4  311   926  109  218   47  ...  212.0   3.0   9.0  16.0   6.0  17.0
 LAN      11  413  1021  153  293   61  ...  141.0   8.0   9.0   3.0   8.0  29.0
 NYN      13  622  1854  240  509  101  ...  310.0  24.0  23.0  18.0  15.0  48.0
 SFN       5  482  1305  198  337   67  ...  188.0  51.0   8.0  16.0   6.0  41.0
 TEX       2  198   729  115  200   40  ...  140.0   4.0   5.0   2.0   8.0  16.0
 TOR       4  459  1408  187  378   96  ...  265.0  16.0  12.0   4.0  16.0  38.0

[8 rows x 18 columns] 

部分字符串索引在 DatetimeIndex 的一部分时

当作为 MultiIndex 的一部分时,部分字符串索引现在匹配 DateTimeIndexGH 10331)。

In [20]: dft2 = pd.DataFrame(
 ....:    np.random.randn(20, 1),
 ....:    columns=["A"],
 ....:    index=pd.MultiIndex.from_product(
 ....:        [pd.date_range("20130101", periods=10, freq="12H"), ["a", "b"]]
 ....:    ),
 ....: )
 ....:

In [21]: dft2
Out[21]:
 A
2013-01-01 00:00:00 a  0.469112
 b -0.282863
2013-01-01 12:00:00 a -1.509059
 b -1.135632
2013-01-02 00:00:00 a  1.212112
...                         ...
2013-01-04 12:00:00 b  0.271860
2013-01-05 00:00:00 a -0.424972
 b  0.567020
2013-01-05 12:00:00 a  0.276232
 b -1.087401

[20 rows x 1 columns]

In [22]: dft2.loc["2013-01-05"]
Out[22]:
 A
2013-01-05 00:00:00 a -0.424972
 b  0.567020
2013-01-05 12:00:00 a  0.276232
 b -1.087401

[4 rows x 1 columns] 

在其他级别上

In [26]: idx = pd.IndexSlice

In [27]: dft2 = dft2.swaplevel(0, 1).sort_index()

In [28]: dft2
Out[28]:
 A
a 2013-01-01 00:00:00  0.469112
 2013-01-01 12:00:00 -1.509059
 2013-01-02 00:00:00  1.212112
 2013-01-02 12:00:00  0.119209
 2013-01-03 00:00:00 -0.861849
...                         ...
b 2013-01-03 12:00:00  1.071804
 2013-01-04 00:00:00 -0.706771
 2013-01-04 12:00:00  0.271860
 2013-01-05 00:00:00  0.567020
 2013-01-05 12:00:00 -1.087401

[20 rows x 1 columns]

In [29]: dft2.loc[idx[:, "2013-01-05"], :]
Out[29]:
 A
a 2013-01-05 00:00:00 -0.424972
 2013-01-05 12:00:00  0.276232
b 2013-01-05 00:00:00  0.567020
 2013-01-05 12:00:00 -1.087401

[4 rows x 1 columns] 

组装日期时间

pd.to_datetime() 现在具有从传递的 DataFrame 或字典组装日期时间的能力(GH 8158)。

In [20]: df = pd.DataFrame(
 ....:    {"year": [2015, 2016], "month": [2, 3], "day": [4, 5], "hour": [2, 3]}
 ....: )
 ....: 

In [21]: df
Out[21]: 
 year  month  day  hour
0  2015      2    4     2
1  2016      3    5     3

[2 rows x 4 columns] 

使用传递的框架进行组装。

In [22]: pd.to_datetime(df)
Out[22]: 
0   2015-02-04 02:00:00
1   2016-03-05 03:00:00
Length: 2, dtype: datetime64[ns] 

你只需传递需要组装的列。

In [23]: pd.to_datetime(df[["year", "month", "day"]])
Out[23]: 
0   2015-02-04
1   2016-03-05
Length: 2, dtype: datetime64[ns] 

其他增强

  • pd.read_csv() 现在支持 Python 引擎的 delim_whitespace=TrueGH 12958)。

  • pd.read_csv() 现在支持通过扩展推断或明确指定 compression='zip' 来打开包含单个 CSV 的 ZIP 文件(GH 12175)。

  • pd.read_csv() 现在支持使用 xz 压缩打开文件,通过扩展推断或明确指定 compression='xz'xz 压缩也同样被 DataFrame.to_csv 支持(GH 11852)。

  • pd.read_msgpack() 现在即使使用了压缩,也总是返回可写入的 ndarrays(GH 12359)。

  • pd.read_msgpack() 现在支持使用 msgpack 序列化和反序列化分类数据(GH 12573

  • .to_json() 现在支持包含分类和稀疏数据的 NDFramesGH 10778

  • interpolate() 现在支持 method='akima'GH 7588

  • pd.read_excel() 现在接受路径对象(例如 pathlib.Pathpy.path.local)作为文件路径,与其他 read_* 函数保持一致(GH 12655

  • 增加了 .weekday_name 属性作为 DatetimeIndex.dt 访问器的组成部分(GH 11128

  • Index.take 现在一致地处理 allow_fillfill_valueGH 12631

    In [24]: idx = pd.Index([1.0, 2.0, 3.0, 4.0], dtype="float")
    
    # default, allow_fill=True, fill_value=None
    In [25]: idx.take([2, -1])
    Out[25]: Index([3.0, 4.0], dtype='float64')
    
    In [26]: idx.take([2, -1], fill_value=True)
    Out[26]: Index([3.0, nan], dtype='float64') 
    
  • Index 现在支持 .str.get_dummies(),返回 MultiIndex,详见 创建指示变量(GH 10008GH 10103

    In [27]: idx = pd.Index(["a|b", "a|c", "b|c"])
    
    In [28]: idx.str.get_dummies("|")
    Out[28]: 
    MultiIndex([(1, 1, 0),
     (1, 0, 1),
     (0, 1, 1)],
     names=['a', 'b', 'c']) 
    
  • pd.crosstab() 增加了 normalize 参数以对频率表进行归一化处理(GH 12569)。更新的文档示例在 这里。

  • .resample(..).interpolate() 现在受支持(GH 12925

  • .isin() 现在接受传递的 setsGH 12988

稀疏变化

这些变化使稀疏处理返回正确的类型,并努力使索引体验更加流畅。

SparseArray.take 现在对标量输入返回标量,对其他输入返回 SparseArray。此外,它以与 Index 相同的规则处理负索引器(GH 10560GH 12796

s = pd.SparseArray([np.nan, np.nan, 1, 2, 3, np.nan, 4, 5, np.nan, 6])
s.take(0)
s.take([1, 2, 3]) 
  • SparseSeries[] 使用 Ellipsis 进行索引时会引发 KeyError 的 Bug(GH 9467

  • SparseArray[] 对元组进行索引的 Bug 没有得到正确处理(GH 12966

  • SparseSeries.loc[] 中出现列表类似输入时引发 TypeError 的 Bug(GH 10560

  • SparseSeries.iloc[] 中出现标量输入可能引发 IndexError 的 Bug(GH 10560

  • SparseSeries.loc[].iloc[] 中使用 slice 返回 SparseArray,而不是 SparseSeries 的 Bug(GH 10560

  • SparseDataFrame.loc[].iloc[] 中出现的 Bug 可能导致密集 Series,而不是 SparseSeriesGH 12787

  • SparseArray 的加法中忽略右侧的 fill_value 的 Bug (GH 12910)

  • SparseArray 的 mod 函数中存在 Bug,会引发 AttributeError (GH 12910)

  • SparseArray 的 pow 函数中存在 Bug,将 1 ** np.nan 计算为 np.nan,应该是 1 (GH 12910)

  • SparseArray 比较输出的 Bug 可能会产生不正确的结果或引发 ValueError (GH 12971)

  • SparseSeries.__repr__ 中存在 Bug,当长度超过 max_rows 时会引发 TypeError (GH 10560)

  • SparseSeries.shape 中存在 Bug,忽略了 fill_value (GH 10452)

  • SparseSeriesSparseArray 中的 Bug 可能与其密集值的 dtype 不同 (GH 12908)

  • SparseSeries.reindex 中存在 Bug,不正确处理 fill_value (GH 12797)

  • SparseArray.to_frame() 中存在 Bug,结果是 DataFrame,而不是 SparseDataFrame (GH 9850)

  • SparseSeries.value_counts() 中存在 Bug,不计算 fill_value (GH 6749)

  • SparseArray.to_dense() 中存在 Bug,不保留 dtype (GH 10648)

  • SparseArray.to_dense() 中不正确处理 fill_value 的 Bug (GH 12797)

  • pd.concat() 中的 SparseSeries 导致密集化的 Bug (GH 10536)

  • pd.concat() 中的 SparseDataFrame 不正确处理 fill_value 的 Bug (GH 9765)

  • pd.concat() 中的 SparseDataFrame 可能会引发 AttributeError 的 Bug (GH 12174)

  • SparseArray.shift() 中存在 Bug,可能会引发 NameErrorTypeError (GH 12908)

API 变更

方法 .groupby(..).nth() 变更

当传递 as_index 参数时,.groupby(..).nth() 输出的索引现在更加一致了 (GH 11039):

In [29]: df = pd.DataFrame({"A": ["a", "b", "a"], "B": [1, 2, 3]})

In [30]: df
Out[30]: 
 A  B
0  a  1
1  b  2
2  a  3

[3 rows x 2 columns] 

之前的行为:

In [3]: df.groupby('A', as_index=True)['B'].nth(0)
Out[3]:
0    1
1    2
Name: B, dtype: int64

In [4]: df.groupby('A', as_index=False)['B'].nth(0)
Out[4]:
0    1
1    2
Name: B, dtype: int64 

新行为:

In [31]: df.groupby("A", as_index=True)["B"].nth(0)
Out[31]: 
0    1
1    2
Name: B, Length: 2, dtype: int64

In [32]: df.groupby("A", as_index=False)["B"].nth(0)
Out[32]: 
0    1
1    2
Name: B, Length: 2, dtype: int64 

此外,以前,.groupby 总是会排序,即使传递了 sort=False 也是如此,与 .nth() 一起。

In [33]: np.random.seed(1234)

In [34]: df = pd.DataFrame(np.random.randn(100, 2), columns=["a", "b"])

In [35]: df["c"] = np.random.randint(0, 4, 100) 

之前的行为:

In [4]: df.groupby('c', sort=True).nth(1)
Out[4]:
 a         b
c
0 -0.334077  0.002118
1  0.036142 -2.074978
2 -0.720589  0.887163
3  0.859588 -0.636524

In [5]: df.groupby('c', sort=False).nth(1)
Out[5]:
 a         b
c
0 -0.334077  0.002118
1  0.036142 -2.074978
2 -0.720589  0.887163
3  0.859588 -0.636524 

新行为:

In [36]: df.groupby("c", sort=True).nth(1)
Out[36]: 
 a         b  c
2  -0.720589  0.887163  2
3   0.859588 -0.636524  3
7  -0.334077  0.002118  0
21  0.036142 -2.074978  1

[4 rows x 3 columns]

In [37]: df.groupby("c", sort=False).nth(1)
Out[37]: 
 a         b  c
2  -0.720589  0.887163  2
3   0.859588 -0.636524  3
7  -0.334077  0.002118  0
21  0.036142 -2.074978  1

[4 rows x 3 columns] 
```  ### NumPy 函数兼容性

通过增加`pandas`方法的签名,使其接受可以从`numpy`传递的参数,即使它们在`pandas`实现中并不一定被使用,大大增加了`pandas`数组方法(例如`sum`和`take`)与它们的`numpy`对应方法之间的兼容性。([GH 12644](https://github.com/pandas-dev/pandas/issues/12644), [GH 12638](https://github.com/pandas-dev/pandas/issues/12638), [GH 12687](https://github.com/pandas-dev/pandas/issues/12687))

+   `.searchsorted()`对于`Index`和`TimedeltaIndex`现在接受一个`sorter`参数,以保持与 numpy 的`searchsorted`函数的兼容性([GH 12238](https://github.com/pandas-dev/pandas/issues/12238))

+   在`Series`上的`np.round()`的 numpy 兼容性中存在错误([GH 12600](https://github.com/pandas-dev/pandas/issues/12600))

一个此类签名增强的示例如下所示:

```py
sp = pd.SparseDataFrame([1, 2, 3])
sp 

先前行为:

In [2]: np.cumsum(sp, axis=0)
...
TypeError: cumsum() takes at most 2 arguments (4 given) 

新行为:

np.cumsum(sp, axis=0) 
```  ### 在 GroupBy 重新采样上使用`.apply`

使用`apply`在重新采样分组操作(使用`pd.TimeGrouper`)上,现在具有与其他分组操作上类似的`apply`调用相同的输出类型。([GH 11742](https://github.com/pandas-dev/pandas/issues/11742))。

```py
In [38]: df = pd.DataFrame(
 ....:    {"date": pd.to_datetime(["10/10/2000", "11/10/2000"]), "value": [10, 13]}
 ....: )
 ....: 

In [39]: df
Out[39]: 
 date  value
0 2000-10-10     10
1 2000-11-10     13

[2 rows x 2 columns] 

先前行为:

In [1]: df.groupby(pd.TimeGrouper(key='date',
 ...:                          freq='M')).apply(lambda x: x.value.sum())
Out[1]:
...
TypeError: cannot concatenate a non-NDFrame object

# Output is a Series
In [2]: df.groupby(pd.TimeGrouper(key='date',
 ...:                          freq='M')).apply(lambda x: x[['value']].sum())
Out[2]:
date
2000-10-31  value    10
2000-11-30  value    13
dtype: int64 

新行为:

# Output is a Series
In [55]: df.groupby(pd.TimeGrouper(key='date',
 ...:                           freq='M')).apply(lambda x: x.value.sum())
Out[55]:
date
2000-10-31    10
2000-11-30    13
Freq: M, dtype: int64

# Output is a DataFrame
In [56]: df.groupby(pd.TimeGrouper(key='date',
 ...:                           freq='M')).apply(lambda x: x[['value']].sum())
Out[56]:
 value
date
2000-10-31     10
2000-11-30     13 
```  ### `read_csv`异常的更改

为了使`read_csv` API 在`c`和`python`引擎上标准化,现在两者都将对空列或标题引发`EmptyDataError`,这是`ValueError`的子类。([GH 12493](https://github.com/pandas-dev/pandas/issues/12493), [GH 12506](https://github.com/pandas-dev/pandas/issues/12506))

先前行为:

```py
In [1]: import io

In [2]: df = pd.read_csv(io.StringIO(''), engine='c')
...
ValueError: No columns to parse from file

In [3]: df = pd.read_csv(io.StringIO(''), engine='python')
...
StopIteration 

新行为:

In [1]: df = pd.read_csv(io.StringIO(''), engine='c')
...
pandas.io.common.EmptyDataError: No columns to parse from file

In [2]: df = pd.read_csv(io.StringIO(''), engine='python')
...
pandas.io.common.EmptyDataError: No columns to parse from file 

除了这个错误更改之外,还进行了其他几个更改:

  • CParserError现在是ValueError的子类,而不仅仅是Exception(GH 12551)

  • c引擎无法解析列时,在read_csv中现在会引发CParserError而不是通用的Exception(GH 12506)

  • c引擎在整数列中遇到NaN值时,在read_csv中现在会引发ValueError而不是通用的Exception(GH 12506)

  • 当指定true_values并且c引擎遇到包含不可编码字节的列中的元素时,在read_csv中现在会引发ValueError而不是通用的Exception(GH 12506)

  • pandas.parser.OverflowError异常已被移除,并已被 Python 内置的OverflowError异常替换(GH 12506)

  • pd.read_csv()不再允许在usecols参数中组合字符串和整数。(GH 12678) ### 方法to_datetime错误更改

pd.to_datetime()中传递可转换条目和errors='coerce'或不可转换条目和errors='ignore'时存在错误。此外,当errors='raise'时遇到超出范围值时将引发OutOfBoundsDateime异常。(GH 11758, GH 13052, GH 13059)

先前的行为:

In [27]: pd.to_datetime(1420043460, unit='s', errors='coerce')
Out[27]: NaT

In [28]: pd.to_datetime(11111111, unit='D', errors='ignore')
OverflowError: Python int too large to convert to C long

In [29]: pd.to_datetime(11111111, unit='D', errors='raise')
OverflowError: Python int too large to convert to C long 

新行为:

In [2]: pd.to_datetime(1420043460, unit='s', errors='coerce')
Out[2]: Timestamp('2014-12-31 16:31:00')

In [3]: pd.to_datetime(11111111, unit='D', errors='ignore')
Out[3]: 11111111

In [4]: pd.to_datetime(11111111, unit='D', errors='raise')
OutOfBoundsDatetime: cannot convert input with unit 'D' 
```  ### 其他 API 更改

+   对于`Series`、`DataFrame`、`Panel`和`MultiIndex`的`.swaplevel()`现在具有其前两个参数`i`和`j`的默认值,这两个参数交换索引的最内层级别。([GH 12934](https://github.com/pandas-dev/pandas/issues/12934))

+   `.searchsorted()`对于`Index`和`TimedeltaIndex`现在接受一个`sorter`参数以保持与 numpy 的`searchsorted`函数的兼容性 ([GH 12238](https://github.com/pandas-dev/pandas/issues/12238))

+   `Period`和`PeriodIndex`现在引发`IncompatibleFrequency`错误,该错误继承自`ValueError`而不是原始的`ValueError` ([GH 12615](https://github.com/pandas-dev/pandas/issues/12615))

+   `Series.apply`对于类别 dtype 现在将传递的函数应用于每个`.categories`(而不是`.codes`),如果可能的话返回`category` dtype ([GH 12473](https://github.com/pandas-dev/pandas/issues/12473))

+   `read_csv`现在会在`parse_dates`既不是布尔值、列表或字典时引发`TypeError`(与文档字符串匹配)([GH 5636](https://github.com/pandas-dev/pandas/issues/5636))

+   `.query()/.eval()`的默认值现在是`engine=None`,如果安装了`numexpr`,则会使用`numexpr`;否则将回退到`python`引擎。如果安装了`numexpr`,则模仿了 0.18.1 之前的行为(以前,如果未安装`numexpr`,`.query()/.eval()`会引发异常)。([GH 12749](https://github.com/pandas-dev/pandas/issues/12749))

+   `pd.show_versions()`现在包括`pandas_datareader`版本 ([GH 12740](https://github.com/pandas-dev/pandas/issues/12740))

+   为通用函数提供适当的`__name__`和`__qualname__`属性 ([GH 12021](https://github.com/pandas-dev/pandas/issues/12021))

+   `pd.concat(ignore_index=True)`现在默认使用`RangeIndex` ([GH 12695](https://github.com/pandas-dev/pandas/issues/12695))

+   当将单级和多级数据框合并/连接时,`pd.merge()`和`DataFrame.join()`将显示`UserWarning` ([GH 9455](https://github.com/pandas-dev/pandas/issues/9455), [GH 12219](https://github.com/pandas-dev/pandas/issues/12219))

+   与`scipy` > 0.17 兼容的已弃用的`piecewise_polynomial`插值方法;支持替代的`from_derivatives`方法 ([GH 12887](https://github.com/pandas-dev/pandas/issues/12887))  ### 弃用

+   方法名`Index.sym_diff()`已弃用,可以替换为`Index.symmetric_difference()` ([GH 12591](https://github.com/pandas-dev/pandas/issues/12591))

+   方法名 `Categorical.sort()` 已被弃用,推荐使用 `Categorical.sort_values()` ([GH 12882](https://github.com/pandas-dev/pandas/issues/12882))  ### 方法 `.groupby(..).nth()` 的变化

当传递 `as_index` 参数时,`.groupby(..).nth()` 输出中的索引现在更加一致 ([GH 11039](https://github.com/pandas-dev/pandas/issues/11039)):

```py
In [29]: df = pd.DataFrame({"A": ["a", "b", "a"], "B": [1, 2, 3]})

In [30]: df
Out[30]: 
 A  B
0  a  1
1  b  2
2  a  3

[3 rows x 2 columns] 

先前的行为:

In [3]: df.groupby('A', as_index=True)['B'].nth(0)
Out[3]:
0    1
1    2
Name: B, dtype: int64

In [4]: df.groupby('A', as_index=False)['B'].nth(0)
Out[4]:
0    1
1    2
Name: B, dtype: int64 

新行为:

In [31]: df.groupby("A", as_index=True)["B"].nth(0)
Out[31]: 
0    1
1    2
Name: B, Length: 2, dtype: int64

In [32]: df.groupby("A", as_index=False)["B"].nth(0)
Out[32]: 
0    1
1    2
Name: B, Length: 2, dtype: int64 

此外,以前,.groupby 总是会排序,无论是否使用 .nth() 传递了 sort=False

In [33]: np.random.seed(1234)

In [34]: df = pd.DataFrame(np.random.randn(100, 2), columns=["a", "b"])

In [35]: df["c"] = np.random.randint(0, 4, 100) 

先前的行为:

In [4]: df.groupby('c', sort=True).nth(1)
Out[4]:
 a         b
c
0 -0.334077  0.002118
1  0.036142 -2.074978
2 -0.720589  0.887163
3  0.859588 -0.636524

In [5]: df.groupby('c', sort=False).nth(1)
Out[5]:
 a         b
c
0 -0.334077  0.002118
1  0.036142 -2.074978
2 -0.720589  0.887163
3  0.859588 -0.636524 

新行为:

In [36]: df.groupby("c", sort=True).nth(1)
Out[36]: 
 a         b  c
2  -0.720589  0.887163  2
3   0.859588 -0.636524  3
7  -0.334077  0.002118  0
21  0.036142 -2.074978  1

[4 rows x 3 columns]

In [37]: df.groupby("c", sort=False).nth(1)
Out[37]: 
 a         b  c
2  -0.720589  0.887163  2
3   0.859588 -0.636524  3
7  -0.334077  0.002118  0
21  0.036142 -2.074978  1

[4 rows x 3 columns] 

NumPy 函数兼容性

增加了 pandas 数组类方法(例如 sumtake)与它们的 numpy 对应方法之间的兼容性,通过增加 pandas 方法的签名,使其接受可以从 numpy 传递的参数,即使它们在 pandas 实现中并不一定会使用 (GH 12644, GH 12638, GH 12687)

  • .searchsorted() 用于 IndexTimedeltaIndex 现在接受一个 sorter 参数,以保持与 numpy 的 searchsorted 函数的兼容性 (GH 12238)

  • Seriesnp.round() 的 numpy 兼容性错误 (GH 12600)

此签名增强的示例如下:

sp = pd.SparseDataFrame([1, 2, 3])
sp 

先前的行为:

In [2]: np.cumsum(sp, axis=0)
...
TypeError: cumsum() takes at most 2 arguments (4 given) 

新行为:

np.cumsum(sp, axis=0) 

在 GroupBy 重采样上使用 .apply

在重采样 GroupBy 操作(使用 pd.TimeGrouper)上使用 apply 现在与其他 GroupBy 操作上的类似 apply 调用具有相同的输出类型。 (GH 11742).

In [38]: df = pd.DataFrame(
 ....:    {"date": pd.to_datetime(["10/10/2000", "11/10/2000"]), "value": [10, 13]}
 ....: )
 ....: 

In [39]: df
Out[39]: 
 date  value
0 2000-10-10     10
1 2000-11-10     13

[2 rows x 2 columns] 

先前的行为:

In [1]: df.groupby(pd.TimeGrouper(key='date',
 ...:                          freq='M')).apply(lambda x: x.value.sum())
Out[1]:
...
TypeError: cannot concatenate a non-NDFrame object

# Output is a Series
In [2]: df.groupby(pd.TimeGrouper(key='date',
 ...:                          freq='M')).apply(lambda x: x[['value']].sum())
Out[2]:
date
2000-10-31  value    10
2000-11-30  value    13
dtype: int64 

新行为:

# Output is a Series
In [55]: df.groupby(pd.TimeGrouper(key='date',
 ...:                           freq='M')).apply(lambda x: x.value.sum())
Out[55]:
date
2000-10-31    10
2000-11-30    13
Freq: M, dtype: int64

# Output is a DataFrame
In [56]: df.groupby(pd.TimeGrouper(key='date',
 ...:                           freq='M')).apply(lambda x: x[['value']].sum())
Out[56]:
 value
date
2000-10-31     10
2000-11-30     13 

read_csv 异常的变化

为了使 cpython 引擎的 read_csv API 标准化,现在两者都会在空列或标题的情况下引发 EmptyDataError,它是 ValueError 的子类 (GH 12493, GH 12506)

先前的行为:

In [1]: import io

In [2]: df = pd.read_csv(io.StringIO(''), engine='c')
...
ValueError: No columns to parse from file

In [3]: df = pd.read_csv(io.StringIO(''), engine='python')
...
StopIteration 

新行为:

In [1]: df = pd.read_csv(io.StringIO(''), engine='c')
...
pandas.io.common.EmptyDataError: No columns to parse from file

In [2]: df = pd.read_csv(io.StringIO(''), engine='python')
...
pandas.io.common.EmptyDataError: No columns to parse from file 

除了这个错误的更改之外,还进行了其他几个更改:

  • CParserError 现在子类化 ValueError 而不仅仅是 Exception (GH 12551)

  • c 引擎无法解析列时,read_csv 现在会引发 CParserError 而不是一般的 Exception (GH 12506)

  • c 引擎在整数列中遇到 NaN 值时,read_csv 现在会引发 ValueError 而不是一般的 Exception (GH 12506)

  • 当指定 true_values 时,现在在 read_csv 中抛出 ValueError 而不是通用的 Exception,并且 c 引擎在包含无法编码的字节的列中遇到一个元素时将会抛出异常(GH 12506

  • pandas.parser.OverflowError 异常已被移除,并已被 Python 的内置 OverflowError 异常取代(GH 12506

  • pd.read_csv() 现在不再允许在 usecols 参数中组合字符串和整数(GH 12678

to_datetime 方法错误变更

在传递可转换条目的 uniterrors='coerce' 或不可转换的 errors='ignore' 时,pd.to_datetime() 中存在错误。此外,当 errors='raise' 时遇到超出范围的值时,将引发 OutOfBoundsDateime 异常。(GH 11758, GH 13052, GH 13059)

之前的行为:

In [27]: pd.to_datetime(1420043460, unit='s', errors='coerce')
Out[27]: NaT

In [28]: pd.to_datetime(11111111, unit='D', errors='ignore')
OverflowError: Python int too large to convert to C long

In [29]: pd.to_datetime(11111111, unit='D', errors='raise')
OverflowError: Python int too large to convert to C long 

新行为:

In [2]: pd.to_datetime(1420043460, unit='s', errors='coerce')
Out[2]: Timestamp('2014-12-31 16:31:00')

In [3]: pd.to_datetime(11111111, unit='D', errors='ignore')
Out[3]: 11111111

In [4]: pd.to_datetime(11111111, unit='D', errors='raise')
OutOfBoundsDatetime: cannot convert input with unit 'D' 

其他 API 变更

  • 对于 SeriesDataFramePanelMultiIndex.swaplevel() 现在具有其前两个参数 ij 的默认值,用于交换索引的两个最内层级别。(GH 12934)

  • 对于 IndexTimedeltaIndex.searchsorted() 现在接受一个 sorter 参数以保持与 numpy 的 searchsorted 函数的兼容性(GH 12238

  • PeriodPeriodIndex 现在引发 IncompatibleFrequency 错误,该错误继承自 ValueError 而不是原始的 ValueErrorGH 12615

  • Series.apply 对于类别 dtype 现在将传递的函数应用于每个 .categories(而不是 .codes),并在可能的情况下返回一个 category dtype(GH 12473

  • 如果 parse_dates 不是布尔值、列表或字典(与文档字符串匹配),read_csv 现在会引发 TypeErrorGH 5636

  • .query()/.eval() 的默认值现在是 engine=None,如果安装了 numexpr,则会使用它;否则将退回到 python 引擎。如果安装了 numexpr,则这模仿了 0.18.1 之前的行为(如果未安装 numexpr.query()/.eval() 将引发异常)。(GH 12749)

  • pd.show_versions() 现在包括 pandas_datareader 版本(GH 12740

  • 为泛型函数提供适当的 __name____qualname__ 属性(GH 12021

  • pd.concat(ignore_index=True) 现在使用 RangeIndex 作为默认值(GH 12695

  • 在将单层与多层数据框合并/连接时,pd.merge()DataFrame.join()将显示UserWarning警告(GH 9455GH 12219

  • 对于已弃用的piecewise_polynomial插值方法与scipy > 0.17 兼容;支持替代方法from_derivativesGH 12887

废弃

  • 方法名Index.sym_diff()已弃用,可替换为Index.symmetric_difference()GH 12591

  • 方法名Categorical.sort()已弃用,改用Categorical.sort_values()GH 12882

性能改进

  • 提高了 SAS 阅读器的速度(GH 12656GH 12961

  • .groupby(..).cumcount()中的性能改进(GH 11039

  • 在使用skiprows=an_integer时,改进了pd.read_csv()的内存使用情况(GH 13005

  • 在检查表的大小写敏感性时,改进了DataFrame.to_sql的性能。现在只在表名不是小写时才检查表是否已正确创建。(GH 12876)

  • 改进了Period构造和时间序列绘图的性能(GH 12903GH 11831)。

  • 改进了.str.encode().str.decode()方法的性能(GH 13008

  • 如果输入是数字类型,则改进了to_numeric的性能(GH 12777

  • 通过IntIndex进行稀疏算术的性能改进(GH 13036

错误修复

  • 即使 CSV 文件的行数不均匀,pd.read_csv中的usecols参数现在也会受到尊重(GH 12203

  • 当指定axis=1时,groupby.transform(..)中的错误(axis=1)与非单调有序索引一起使用时出现错误(GH 12713

  • 如果指定freq="Minute",则在PeriodPeriodIndex创建中出现KeyError错误。请注意,“Minute”频率已在 v0.17.0 中弃用,建议改用freq="T"GH 11854

  • 始终引发TypeError.resample(...).count()PeriodIndex一起使用的错误(GH 12774

  • 当为空时,.resample(...)PeriodIndex转换为DatetimeIndex时的错误(GH 12868

  • 当对 PeriodIndex 进行重采样到现有频率时,.resample(...) 存在 Bug(GH 12770

  • 包含不同 freqPeriod 数据打印时引发 ValueError 的 Bug(GH 12615

  • 在指定 dtype='category' 的情况下,使用 Categorical 构建 Series 存在 Bug(GH 12574

  • 当对象长于 display.max_rows 时,具有可强制转换 dtype 的连接在输出格式化时过于激进,导致不同的 dtype(GH 12411, GH 12045, GH 11594, GH 10571, GH 12211

  • 选项 float_format 在未验证为可调用时出现的 Bug。(GH 12706)

  • GroupBy.filter 中,当 dropna=False 且没有组符合条件时存在 Bug (GH 12768)

  • .cum* 函数的 __name__ 中存在 Bug(GH 12021

  • Float64Inde/Int64Index 转换为 Int64Index 时存在 Bug 在 .astype() 中。 (GH 12881)

  • .to_json()/.read_json() 中,默认情况下orient='index',对整数型索引进行回环处理存在 Bug (GH 12866)

  • 在尝试堆叠条形图时,Categorical 数据类型绘图存在 Bug 导致错误(GH 13019

  • 兼容 numpy 版本 1.11 以上的 NaT 比较(GH 12969

  • 在非唯一的 MultiIndex 中使用 .drop() 存在 Bug。 (GH 12701)

  • .concat 方法在处理带时区和不带时区的 DataFrame 时存在 Bug(GH 12467

  • 在传递非字符串时,在 .resample(..).fillna(..) 中正确引发 ValueError 的 Bug(GH 12952

  • pd.read_sas() 中存在各种编码和头部处理问题的 Bug 修复(GH 12659, GH 12654, GH 12647, GH 12809

  • pd.crosstab() 中存在的 Bug:如果 values=None,则会静默忽略 aggfuncGH 12569

  • 在序列化 datetime.time 时,在 DataFrame.to_json 中存在潜在的段错误(GH 11473

  • 在尝试序列化 0d 数组时,DataFrame.to_json 中存在潜在的段错误 (GH 11299)。

  • 在尝试序列化具有非 ndarray 值的 DataFrameSeries 时,to_json 中存在的段错误;现在支持 categorysparsedatetime64[ns, tz] dtypes 的序列化 (GH 10778)。

  • DataFrame.to_json 中存在的 Bug,不支持的 dtype 未传递给默认处理程序 (GH 12554)。

  • .align 中存在的 Bug,未返回子类 (GH 12983)。

  • SeriesDataFrame 对齐时存在的 Bug (GH 13037)。

  • ABCPanel 中存在的 Bug,其中 Panel4D 不被视为此通用类型的有效实例 (GH 12810)。

  • .groupby(..).apply(..) 案例中 .name 一致性存在 Bug (GH 12363)。

  • 导致 pprint 在嵌套结构中失败的 Timestamp.__repr__ 中存在的 Bug (GH 12622)。

  • Timedelta.minTimedelta.max 中存在的 Bug,现在的属性报告 pandas 认可的真实最小/最大 timedeltas。参见 documentation。 (GH 12727)。

  • 使用插值的 .quantile() 中存在的 Bug,可能意外地强制转换为 float (GH 12772)。

  • 使用空 Series.quantile() 中存在的 Bug,可能返回标量而不是空 Series (GH 12772)。

  • 在大量索引器中越界的 .loc 中存在的 Bug,会引发 IndexError 而不是 KeyError (GH 12527)。

  • 使用 TimedeltaIndex.asfreq() 重新采样时存在 Bug,之前不会包含最终的围栏。 (GH 12926)。

  • DataFrame 中的 Categorical 中的相等性测试中存在 Bug (GH 12564)。

  • 使用 TimeGrouper 时,GroupBy.first().last() 返回的行不正确 (GH 7453)。

  • 使用 c 引擎的 pd.read_csv() 中存在的 Bug,当在引号中的项中指定 skiprows 时存在新行 (GH 10911, GH 12775)。

  • 在为具有对齐的时区感知日期时间 Series 分配时存在的 DataFrame 时区丢失的 Bug (GH 12981)。

  • normalize=Truedropna=True 时,.value_counts() 存在 Bug,其中空值仍然影响了归一化计数 (GH 12558)。

  • Series的 dtype 为category时,在Series.value_counts()中存在错误,会丢失名称 (GH 12835)

  • Series.value_counts()中存在错误,丢失时区信息 (GH 12835)

  • Series.value_counts(normalize=True)Categorical一起使用时,会引发UnboundLocalError (GH 12835)

  • Panel.fillna()中存在错误,忽略了inplace=True (GH 12633)

  • 当同时使用c引擎和namesusecols以及parse_dates来指定pd.read_csv()时出现错误 (GH 9755)

  • 当同时使用c引擎和delim_whitespace=True以及lineterminator来指定pd.read_csv()时出现错误 (GH 12912)

  • Series.renameDataFrame.renameDataFrame.rename_axis中存在错误,未将Series视为映射来重新标记 (GH 12623)

  • .rolling.min.rolling.max中进行清理以增强 dtype 处理 (GH 12373)

  • groupby中存在错误,复杂类型被强制转换为浮点数 (GH 12902)

  • 当其 dtype 为category或 tz-aware datetime时,Series.map存在错误,会引发TypeError (GH 12473)

  • 在某些测试比较中,32 位平台上存在错误 (GH 12972)

  • 当从RangeIndex构造中回退时,索引强制转换存在错误 (GH 12893)

  • 在窗口函数中改进了错误消息,当传递无效参数(例如浮点窗口)时 (GH 12669)

  • 在对子类化的DataFrame进行切片时存在错误,定义为返回子类化的Series可能返回普通的Series (GH 11559)

  • 在输入具有name并且结果为DataFrameMultiIndex的情况下,使用.str访问器方法可能会引发ValueError (GH 12617)

  • 在空框架上使用DataFrame.last_valid_index()DataFrame.first_valid_index()时存在错误 (GH 12800)

  • CategoricalIndex.get_loc中存在错误,与常规Index返回不同的结果 (GH 12531)

  • PeriodIndex.resample中存在错误,名称未传播 (GH 12769)

  • date_rangeclosed关键字和时区存在错误 (GH 12684)

  • 当输入数据包含 tz-aware datetime 和 timedelta 时,pd.concat存在错误,会引发AttributeError (GH 12620)

  • pd.concat 中存在 bug,未正确处理空 Series (GH 11082)

  • 当指定 width 时,.plot.bar 对齐存在 bug,其中 widthint (GH 12979)

  • 当二进制运算符的参数为常数时,fill_value 中的 bug 被忽略 (GH 12723)

  • 当使用 bs4 flavor 并解析只有一个标题列的表格时,pd.read_html() 存在 bug (GH 9178)

  • margins=Truedropna=True 时,.pivot_table 存在 bug,其中空值仍然会对边距计数有贡献 (GH 12577)

  • dropna=False 时,.pivot_table 中存在 bug,表格索引/列名消失 (GH 12133)

  • margins=Truedropna=False 时,pd.crosstab() 中存在 bug,会引发异常 (GH 12642)

  • name 属性可以是可哈希类型时,Series.name 存在 bug (GH 12610)

  • .describe() 中存在 bug,重置了分类列信息 (GH 11558)

  • 当在时间序列上调用 resample().count() 时,loffset 参数未被应用的 bug (GH 12725)

  • pd.read_excel() 现在接受与关键字参数 names 关联的列名 (GH 12870)

  • Index 作为参数时,pd.to_numeric() 存在 bug,返回 np.ndarray 而不是 Index (GH 12777)

  • 当类似日期时间的对象作为参数时,pd.to_numeric() 中存在 bug,可能引发 TypeError (GH 12777)

  • pd.to_numeric() 存在 bug,使用标量会引发 ValueError (GH 12777)

贡献者

这个版本共有 60 人贡献了补丁。带有“+”符号的人是首次贡献补丁的。

  • Andrew Fiore-Gartland +

  • Bastiaan +

  • Benoît Vinot +

  • Brandon Rhodes +

  • DaCoEx +

  • Drew Fustin +

  • Ernesto Freitas +

  • Filip Ter +

  • Gregory Livschitz +

  • Gábor Lipták

  • Hassan Kibirige +

  • Iblis Lin

  • Israel Saeta Pérez +

  • Jason Wolosonovich +

  • Jeff Reback

  • Joe Jevnik

  • Joris Van den Bossche

  • Joshua Storck +

  • Ka Wo Chen

  • Kerby Shedden

  • Kieran O’Mahony

  • Leif Walsh +

  • Mahmoud Lababidi +

  • Maoyuan Liu +

  • Mark Roth +

  • Matt Wittmann

  • MaxU +

  • Maximilian Roos

  • Michael Droettboom +

  • Nick Eubank

  • Nicolas Bonnotte

  • OXPHOS +

  • Pauli Virtanen +

  • Peter Waller +

  • Pietro Battiston

  • Prabhjot Singh +

  • Robin Wilson

  • Roger Thomas +

  • Sebastian Bank

  • Stephen Hoover

  • Tim Hopper +

  • Tom Augspurger

  • WANG Aiyong

  • Wes Turner

  • Winand +

  • Xbar +

  • Yan Facai +

  • adneu +

  • ajenkins-cargometrics +

  • behzad nouri

  • chinskiy +

  • gfyoung

  • jeps-journal +

  • jonaslb +

  • kotrfa +

  • nileracecrew +

  • onesandzeroes

  • rs2 +

  • sinhrks

  • tsdlovell +

版本 0.18.0(2016 年 3 月 13 日)

原文:pandas.pydata.org/docs/whatsnew/v0.18.0.html

这是从 0.17.1 版本开始的重大更新,包括少量的 API 更改、几个新功能、增强功能和性能改进,以及大量的 bug 修复。我们建议所有用户升级到此版本。

警告

pandas >= 0.18.0 不再支持与 Python 版本 2.6 和 3.3 的兼容性 (GH 7718GH 11273)

警告

numexpr 版本 2.4.4 现在会显示警告,并且不会作为 pandas 的计算后端使用,因为存在一些错误行为。这不会影响其他版本(>= 2.1 和 >= 2.4.6)。(GH 12489)

亮点包括:

  • 移动和扩展窗口函数现在是 Series 和 DataFrame 的方法,类似于 .groupby,详见此处。

  • 增加对 RangeIndex 的支持,作为 Int64Index 的一种专门形式,用于节省内存,详见此处。

  • .resample 方法的 API 破坏性更改,使其更像 .groupby,详见此处。

  • 删除了对浮点数的位置索引的支持,此功能自 0.14.0 版开始已弃用。现在会引发 TypeError,详见此处。

  • 已添加 .to_xarray() 函数,以与xarray 包兼容,详见此处。

  • read_sas 函数已增强,可读取 sas7bdat 文件,详见此处。

  • 添加了 .str.extractall() 方法,以及 .str.extract() 方法 和 .str.cat() 方法 的 API 更改。

  • pd.test() 顶级 nose 测试运行器可用 (GH 4327)。

在更新之前,请检查 API 更改 和 弃用。

v0.18.0 中的新内容

  • 新功能

    • 窗口函数现在是方法

    • 重命名的更改

    • 范围索引

    • str.extract 的更改

    • 添加 str.extractall

    • str.cat 的更改

    • 日期时间般的四舍五入

    • FloatIndex 中整数的格式化

    • dtype 分配行为的更改

    • to_xarray 方法

    • LaTeX 表示

    • pd.read_sas() 的更改

    • 其他增强

  • 向后不兼容的 API 更改

    • NaT 和 Timedelta 操作

    • msgpack 的更改

    • .rank 的签名更改

    • QuarterBegin with n=0 中的错误

    • 重新采样 API

      • 降采样

      • 上采样

      • 以前的 API 将工作,但会有弃用警告

    • eval 的更改

    • 其他 API 更改

    • 弃用

    • 删除已弃用的浮点索引

    • 删除之前版本的弃用/更改

  • 性能改进

  • 错误修复

  • 贡献者

新功能

窗口函数现在是方法

窗口函数已重构为 Series/DataFrame 对象上的方法,而不是顶级函数,顶级函数现已弃用。这允许这些窗口类型函数具有与 .groupby 类似的 API。详细文档请参阅 这里 (GH 11603, GH 12373)

In [1]: np.random.seed(1234)

In [2]: df = pd.DataFrame({'A': range(10), 'B': np.random.randn(10)})

In [3]: df
Out[3]: 
 A         B
0  0  0.471435
1  1 -1.190976
2  2  1.432707
3  3 -0.312652
4  4 -0.720589
5  5  0.887163
6  6  0.859588
7  7 -0.636524
8  8  0.015696
9  9 -2.242685

[10 rows x 2 columns] 

以前的行为:

In [8]: pd.rolling_mean(df, window=3)
 FutureWarning: pd.rolling_mean is deprecated for DataFrame and will be removed in a future version, replace with
 DataFrame.rolling(window=3,center=False).mean()
Out[8]:
 A         B
0 NaN       NaN
1 NaN       NaN
2   1  0.237722
3   2 -0.023640
4   3  0.133155
5   4 -0.048693
6   5  0.342054
7   6  0.370076
8   7  0.079587
9   8 -0.954504 

新行为:

In [4]: r = df.rolling(window=3) 

这些显示了描述性的 repr

In [5]: r
Out[5]: Rolling [window=3,center=False,axis=0,method=single] 

可以使用 tab 键自动补全可用方法和属性。

In [9]: r.<TAB>  # noqa E225, E999
r.A           r.agg         r.apply       r.count       r.exclusions  r.max         r.median      r.name        r.skew        r.sum
r.B           r.aggregate   r.corr        r.cov         r.kurt        r.mean        r.min         r.quantile    r.std         r.var 

这些方法在 Rolling 对象本身上操作

In [6]: r.mean()
Out[6]: 
 A         B
0  NaN       NaN
1  NaN       NaN
2  1.0  0.237722
3  2.0 -0.023640
4  3.0  0.133155
5  4.0 -0.048693
6  5.0  0.342054
7  6.0  0.370076
8  7.0  0.079587
9  8.0 -0.954504

[10 rows x 2 columns] 

它们提供了 getitem 访问器

In [7]: r['A'].mean()
Out[7]: 
0    NaN
1    NaN
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    6.0
8    7.0
9    8.0
Name: A, Length: 10, dtype: float64 

和多个聚合

In [8]: r.agg({'A': ['mean', 'std'],
 ...:       'B': ['mean', 'std']})
 ...: 
Out[8]: 
 A              B 
 mean  std      mean       std
0  NaN  NaN       NaN       NaN
1  NaN  NaN       NaN       NaN
2  1.0  1.0  0.237722  1.327364
3  2.0  1.0 -0.023640  1.335505
4  3.0  1.0  0.133155  1.143778
5  4.0  1.0 -0.048693  0.835747
6  5.0  1.0  0.342054  0.920379
7  6.0  1.0  0.370076  0.871850
8  7.0  1.0  0.079587  0.750099
9  8.0  1.0 -0.954504  1.162285

[10 rows x 4 columns] 
```  ### 重命名的更改

`Series.rename` 和 `NDFrame.rename_axis` 现在可以接受标量或类似列表的参数,以修改 Series 或轴的 *名称*,除了它们以前的修改标签的行为。 ([GH 9494](https://github.com/pandas-dev/pandas/issues/9494), [GH 11965](https://github.com/pandas-dev/pandas/issues/11965))

```py
In [9]: s = pd.Series(np.random.randn(5))

In [10]: s.rename('newname')
Out[10]: 
0    1.150036
1    0.991946
2    0.953324
3   -2.021255
4   -0.334077
Name: newname, Length: 5, dtype: float64 
In [11]: df = pd.DataFrame(np.random.randn(5, 2))

In [12]: (df.rename_axis("indexname")
 ....:   .rename_axis("columns_name", axis="columns"))
 ....: 
Out[12]: 
columns_name         0         1
indexname 
0             0.002118  0.405453
1             0.289092  1.321158
2            -1.546906 -0.202646
3            -0.655969  0.193421
4             0.553439  1.318152

[5 rows x 2 columns] 

新功能在方法链中运行良好。以前这些方法只接受函数或将 标签 映射到新标签的字典。对于函数或类似字典的值,这仍然像以前一样工作。 ### 范围索引

为了支持常见用例的内存节省替代方案,已将 Int64Index 子类添加了一个 RangeIndex。这与 Python range 对象(在 Python 2 中为 xrange)的实现类似,仅存储索引的起始、停止和步长值。它将与用户 API 透明交互,根据需要转换为 Int64Index

这现在将是 NDFrame 对象的默认构造索引,而不是以前的 Int64Index。(GH 939, GH 12070, GH 12071, GH 12109, GH 12888)

以前的行为:

In [3]: s = pd.Series(range(1000))

In [4]: s.index
Out[4]:
Int64Index([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
 ...
 990, 991, 992, 993, 994, 995, 996, 997, 998, 999], dtype='int64', length=1000)

In [6]: s.index.nbytes
Out[6]: 8000 

新行为:

In [13]: s = pd.Series(range(1000))

In [14]: s.index
Out[14]: RangeIndex(start=0, stop=1000, step=1)

In [15]: s.index.nbytes
Out[15]: 128 
```  ### str.extract 的更改

.str.extract 方法接受带有捕获组的正则表达式,在每个主题字符串中找到第一个匹配项,并返回捕获组的内容 ([GH 11386](https://github.com/pandas-dev/pandas/issues/11386))。

在 v0.18.0 中,向`extract`添加了`expand`参数。

+   `expand=False`:根据主题和正则表达式模式返回`Series`、`Index`或`DataFrame`,与 0.18.0 之前的行为相同。

+   `expand=True`:它始终返回一个`DataFrame`,从用户的角度来看更一致、更少令人困惑。

目前默认值是`expand=None`,会引发`FutureWarning`,并使用`expand=False`。为避免此警告,请明确指定`expand`。

```py
In [1]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=None)
FutureWarning: currently extract(expand=None) means expand=False (return Index/Series/DataFrame)
but in a future version of pandas this will be changed to expand=True (return DataFrame)

Out[1]:
0      1
1      2
2    NaN
dtype: object 

提取带有一个组的正则表达式,如果expand=False,则返回一个 Series。

In [16]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=False)
Out[16]: 
0      1
1      2
2    NaN
Length: 3, dtype: object 

如果expand=True,则返回一个列的DataFrame

In [17]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=True)
Out[17]: 
 0
0    1
1    2
2  NaN

[3 rows x 1 columns] 

用正则表达式调用Index,如果有正好一个捕获组,设置expand=False会返回一个Index

In [18]: s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"])

In [19]: s.index
Out[19]: Index(['A11', 'B22', 'C33'], dtype='object')

In [20]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=False)
Out[20]: Index(['A', 'B', 'C'], dtype='object', name='letter') 

如果expand=True,则返回一个列的DataFrame

In [21]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=True)
Out[21]: 
 letter
0      A
1      B
2      C

[3 rows x 1 columns] 

用正则表达式调用Index,如果有多个捕获组,设置expand=False会引发ValueError

>>> s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=False)
ValueError: only one regex group is supported with Index 

如果expand=True,则返回一个DataFrame

In [22]: s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=True)
Out[22]: 
 letter   1
0      A  11
1      B  22
2      C  33

[3 rows x 2 columns] 

总之,extract(expand=True)始终返回一个DataFrame,每个主题字符串一行,每个捕获组一列。### 添加 str.extractall

添加了.str.extractall 方法 (GH 11386)。与extract不同,它只返回第一个匹配项。

In [23]: s = pd.Series(["a1a2", "b1", "c1"], ["A", "B", "C"])

In [24]: s
Out[24]: 
A    a1a2
B      b1
C      c1
Length: 3, dtype: object

In [25]: s.str.extract(r"(?P<letter>[ab])(?P<digit>\d)", expand=False)
Out[25]: 
 letter digit
A      a     1
B      b     1
C    NaN   NaN

[3 rows x 2 columns] 

extractall方法返回所有匹配项。

In [26]: s.str.extractall(r"(?P<letter>[ab])(?P<digit>\d)")
Out[26]: 
 letter digit
 match 
A 0          a     1
 1          a     2
B 0          b     1

[3 rows x 2 columns] 
```  ### 对 str.cat 的更改

方法`.str.cat()`连接了`Series`的成员。以前,如果`Series`中存在`NaN`值,对其调用`.str.cat()`会返回`NaN`,与`Series.str.*`API 的其余部分不同。现在该行为已经更正,默认情况下忽略`NaN`值。([GH 11435](https://github.com/pandas-dev/pandas/issues/11435))。

添加了一个新的友好的`ValueError`,以防止将`sep`作为参数而不是关键字参数的错误。([GH 11334](https://github.com/pandas-dev/pandas/issues/11334))。

```py
In [27]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ')
Out[27]: 'a b c'

In [28]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ', na_rep='?')
Out[28]: 'a b ? c' 
In [2]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(' ')
ValueError: Did you mean to supply a ``sep`` keyword? 
```  ### 日期时间般的四舍五入

`DatetimeIndex`、`Timestamp`、`TimedeltaIndex`、`Timedelta`获得了用于日期时间般的四舍五入、向下取整和向上取整的`.round()`、`.floor()`和`.ceil()`方法。([GH 4314](https://github.com/pandas-dev/pandas/issues/4314), [GH 11963](https://github.com/pandas-dev/pandas/issues/11963))

朴素日期时间

```py
In [29]: dr = pd.date_range('20130101 09:12:56.1234', periods=3)

In [30]: dr
Out[30]: 
DatetimeIndex(['2013-01-01 09:12:56.123400', '2013-01-02 09:12:56.123400',
 '2013-01-03 09:12:56.123400'],
 dtype='datetime64[ns]', freq='D')

In [31]: dr.round('s')
Out[31]: 
DatetimeIndex(['2013-01-01 09:12:56', '2013-01-02 09:12:56',
 '2013-01-03 09:12:56'],
 dtype='datetime64[ns]', freq=None)

# Timestamp scalar
In [32]: dr[0]
Out[32]: Timestamp('2013-01-01 09:12:56.123400')

In [33]: dr[0].round('10s')
Out[33]: Timestamp('2013-01-01 09:13:00') 

Tz-aware 在本地时间中四舍五入、向下取整和向上取整

In [34]: dr = dr.tz_localize('US/Eastern')

In [35]: dr
Out[35]: 
DatetimeIndex(['2013-01-01 09:12:56.123400-05:00',
 '2013-01-02 09:12:56.123400-05:00',
 '2013-01-03 09:12:56.123400-05:00'],
 dtype='datetime64[ns, US/Eastern]', freq=None)

In [36]: dr.round('s')
Out[36]: 
DatetimeIndex(['2013-01-01 09:12:56-05:00', '2013-01-02 09:12:56-05:00',
 '2013-01-03 09:12:56-05:00'],
 dtype='datetime64[ns, US/Eastern]', freq=None) 

时间增量

In [37]: t = pd.timedelta_range('1 days 2 hr 13 min 45 us', periods=3, freq='d')

In [38]: t
Out[38]: 
TimedeltaIndex(['1 days 02:13:00.000045', '2 days 02:13:00.000045',
 '3 days 02:13:00.000045'],
 dtype='timedelta64[ns]', freq='D')

In [39]: t.round('10min')
Out[39]: TimedeltaIndex(['1 days 02:10:00', '2 days 02:10:00', '3 days 02:10:00'], dtype='timedelta64[ns]', freq=None)

# Timedelta scalar
In [40]: t[0]
Out[40]: Timedelta('1 days 02:13:00.000045')

In [41]: t[0].round('2h')
Out[41]: Timedelta('1 days 02:00:00') 

另外,.round().floor().ceil()将通过Series.dt访问器可用。

In [42]: s = pd.Series(dr)

In [43]: s
Out[43]: 
0   2013-01-01 09:12:56.123400-05:00
1   2013-01-02 09:12:56.123400-05:00
2   2013-01-03 09:12:56.123400-05:00
Length: 3, dtype: datetime64[ns, US/Eastern]

In [44]: s.dt.round('D')
Out[44]: 
0   2013-01-01 00:00:00-05:00
1   2013-01-02 00:00:00-05:00
2   2013-01-03 00:00:00-05:00
Length: 3, dtype: datetime64[ns, US/Eastern] 

在 FloatIndex 中的整数格式

FloatIndex 中的整数,例如 1.,现在以小数点和 0 数位的形式格式化,例如 1.0 (GH 11713) 此更改不仅影响控制台的显示,还影响诸如 .to_csv.to_html 等 IO 方法的输出。

以前的行为:

In [2]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [3]: s
Out[3]:
0    1
1    2
2    3
dtype: int64

In [4]: s.index
Out[4]: Float64Index([0.0, 1.0, 2.0], dtype='float64')

In [5]: print(s.to_csv(path=None))
0,1
1,2
2,3 

新行为:

In [45]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [46]: s
Out[46]: 
0.0    1
1.0    2
2.0    3
Length: 3, dtype: int64

In [47]: s.index
Out[47]: Index([0.0, 1.0, 2.0], dtype='float64')

In [48]: print(s.to_csv(path_or_buf=None, header=False))
0.0,1
1.0,2
2.0,3 

dtype 分配行为的更改

当 DataFrame 的切片用相同 dtype 的新切片更新时,DataFrame 的 dtype 现在将保持不变。(GH 10503)

以前的行为:

In [5]: df = pd.DataFrame({'a': [0, 1, 1],
 'b': pd.Series([100, 200, 300], dtype='uint32')})

In [7]: df.dtypes
Out[7]:
a     int64
b    uint32
dtype: object

In [8]: ix = df['a'] == 1

In [9]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [11]: df.dtypes
Out[11]:
a    int64
b    int64
dtype: object 

新行为:

In [49]: df = pd.DataFrame({'a': [0, 1, 1],
 ....:                   'b': pd.Series([100, 200, 300], dtype='uint32')})
 ....: 

In [50]: df.dtypes
Out[50]: 
a     int64
b    uint32
Length: 2, dtype: object

In [51]: ix = df['a'] == 1

In [52]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [53]: df.dtypes
Out[53]: 
a     int64
b    uint32
Length: 2, dtype: object 

当 DataFrame 的整数切片部分地用可能被降级为整数而不会丢失精度的新浮点数切片更新时,切片的 dtype 将设置为浮点数而不是整数。

以前的行为:

In [4]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
 columns=list('abc'),
 index=[[4,4,8], [8,10,12]])

In [5]: df
Out[5]:
 a  b  c
4 8   1  2  3
 10  4  5  6
8 12  7  8  9

In [7]: df.ix[4, 'c'] = np.array([0., 1.])

In [8]: df
Out[8]:
 a  b  c
4 8   1  2  0
 10  4  5  1
8 12  7  8  9 

新行为:

In [54]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
 ....:                  columns=list('abc'),
 ....:                  index=[[4,4,8], [8,10,12]])
 ....: 

In [55]: df
Out[55]: 
 a  b  c
4 8   1  2  3
 10  4  5  6
8 12  7  8  9

[3 rows x 3 columns]

In [56]: df.loc[4, 'c'] = np.array([0., 1.])

In [57]: df
Out[57]: 
 a  b  c
4 8   1  2  0
 10  4  5  1
8 12  7  8  9

[3 rows x 3 columns] 

方法 to_xarray

在 pandas 的未来版本中,我们将停用 Panel 和其他 > 2 维对象。为了提供连续性,所有 NDFrame 对象都添加了 .to_xarray() 方法,以将其转换为具有 pandas-like 接口的 xarray 对象,该接口适用于 > 2 维。(GH 11972)

请参阅xarray 的完整文档

In [1]: p = Panel(np.arange(2*3*4).reshape(2,3,4))

In [2]: p.to_xarray()
Out[2]:
<xarray.DataArray (items: 2, major_axis: 3, minor_axis: 4)>
array([[[ 0,  1,  2,  3],
 [ 4,  5,  6,  7],
 [ 8,  9, 10, 11]],

 [[12, 13, 14, 15],
 [16, 17, 18, 19],
 [20, 21, 22, 23]]])
Coordinates:
 * items       (items) int64 0 1
 * major_axis  (major_axis) int64 0 1 2
 * minor_axis  (minor_axis) int64 0 1 2 3 

Latex 表示

DataFrame 现在具有一个 ._repr_latex_() 方法,以允许在 ipython/jupyter 笔记本中使用 nbconvert 转换为 latex。(GH 11778)

请注意,必须通过设置选项 pd.display.latex.repr=True 来激活此功能。(GH 12182)

例如,如果你有一个要使用 nbconvert 转换为 latex 的 jupyter 笔记本,请在第一个单元格中放置语句 pd.display.latex.repr=True,以便将包含的 DataFrame 输出也存储为 latex。

选项 display.latex.escapedisplay.latex.longtable 也已添加到配置中,并且会被 to_latex 方法自动使用。有关更多信息,请参见可用选项文档。

pd.read_sas() 更改

read_sas 现在具有读取 SAS7BDAT 文件的能力,包括压缩文件。这些文件可以全部读取,也可以逐步读取。有关详细信息,请参见这里。(GH 4052) ### 其他增强功能

  • 处理 SAS xport 文件中的截断浮点数 (GH 11713)

  • Series.to_string 中添加隐藏索引的选项 (GH 11729)

  • read_excel 现在支持格式为 s3://bucketname/filename 的 s3 url。(GH 11447)

  • 在从 s3 读取时添加对 AWS_S3_HOST 环境变量的支持 (GH 12198)

  • 简化版本的 Panel.round() 现已实现。(GH 11763)

  • 对于 Python 3.x,round(DataFrame)round(Series)round(Panel) 将起作用。(GH 11763)

  • sys.getsizeof(obj) 返回 pandas 对象的内存使用情况,包括其包含的值。(GH 11597)

  • Series 增加了 is_unique 属性。(GH 11946)

  • DataFrame.quantileSeries.quantile 现在接受 interpolation 关键字参数。(GH 10174)

  • 添加了 DataFrame.style.format 以更灵活地格式化单元格值。(GH 11692)

  • DataFrame.select_dtypes 现在允许 np.float16 类型代码。(GH 11990)

  • pivot_table() 现在接受大多数可迭代对象作为 values 参数。(GH 12017)

  • 添加了 Google BigQuery 服务帐户认证支持,可在远程服务器上进行身份验证。(GH 11881, GH 12572)。更多详情请参见这里

  • HDFStore 现在可迭代:for k in store 等同于 for k in store.keys()。(GH 12221)

  • Period.dt 中添加了缺失的方法/字段。(GH 8848)

  • 整个代码库已遵循 PEP 标准。(GH 12096) ## 不兼容的 API 更改

  • .to_string(index=False) 方法的输出中已移除前导空格。(GH 11833)

  • Series.round() 方法中的 out 参数已被移除。(GH 11763)

  • DataFrame.round() 在返回中保留非数值列,而不是引发异常。(GH 11885)

  • DataFrame.head(0)DataFrame.tail(0) 返回空框架,而不是 self。(GH 11937)

  • Series.head(0)Series.tail(0) 返回空序列,而不是 self。(GH 11937)

  • to_msgpackread_msgpack 的编码现在默认为 'utf-8'。(GH 12170)

  • 文本文件解析函数(.read_csv().read_table().read_fwf())的关键字参数顺序已更改以分组相关参数。(GH 11555)

  • NaTType.isoformat 现在返回字符串 'NaT,以允许结果传递给 Timestamp 的构造函数。 (GH 12300)

NaTTimedelta 的操作

NaTTimedelta 具有扩展的算术运算,适用于 Series 算术。为 datetime64[ns]timedelta64[ns] 定义的操作现在也适用于 NaT (GH 11564)。

NaT 现在支持与整数和浮点数的算术运算。

In [58]: pd.NaT * 1
Out[58]: NaT

In [59]: pd.NaT * 1.5
Out[59]: NaT

In [60]: pd.NaT / 2
Out[60]: NaT

In [61]: pd.NaT * np.nan
Out[61]: NaT 

NaT 定义了更多与 datetime64[ns]timedelta64[ns] 的算术运算。

In [62]: pd.NaT / pd.NaT
Out[62]: nan

In [63]: pd.Timedelta('1s') / pd.NaT
Out[63]: nan 

NaT 可能表示 datetime64[ns] 的空值,也可能表示 timedelta64[ns] 的空值。鉴于存在歧义,它被视为 timedelta64[ns],这样可以使更多操作成功。

In [64]: pd.NaT + pd.NaT
Out[64]: NaT

# same as
In [65]: pd.Timedelta('1s') + pd.Timedelta('1s')
Out[65]: Timedelta('0 days 00:00:02') 

In [3]: pd.Timestamp('19900315') + pd.Timestamp('19900315')
TypeError: unsupported operand type(s) for +: 'Timestamp' and 'Timestamp' 

但是,当包装在 dtypedatetime64[ns]timedelta64[ns]Series 中时,将尊重 dtype 信息。

In [1]: pd.Series([pd.NaT], dtype='<M8[ns]') + pd.Series([pd.NaT], dtype='<M8[ns]')
TypeError: can only operate on a datetimes for subtraction,
 but the operator [__add__] was passed 
In [66]: pd.Series([pd.NaT], dtype='<m8[ns]') + pd.Series([pd.NaT], dtype='<m8[ns]')
Out[66]: 
0   NaT
Length: 1, dtype: timedelta64[ns] 

Timedelta 除以 floats 现在有效。

In [67]: pd.Timedelta('1s') / 2.0
Out[67]: Timedelta('0 days 00:00:00.500000') 

通过 TimedeltaSeries 中减去 Timestamp 是有效的 (GH 11925)

In [68]: ser = pd.Series(pd.timedelta_range('1 day', periods=3))

In [69]: ser
Out[69]: 
0   1 days
1   2 days
2   3 days
Length: 3, dtype: timedelta64[ns]

In [70]: pd.Timestamp('2012-01-01') - ser
Out[70]: 
0   2011-12-31
1   2011-12-30
2   2011-12-29
Length: 3, dtype: datetime64[ns] 

NaT.isoformat() 现在返回 'NaT'。这个改变允许 pd.Timestamp 从其 isoformat 重新生成任何时间戳对象 (GH 12300)。

对 msgpack 的更改

在 0.17.0 和 0.18.0 中对 msgpack 写入格式进行了不向前兼容的更改;旧版本的 pandas 无法读取由新版本打包的文件 (GH 12129, GH 10527)

0.17.0 中引入的 to_msgpackread_msgpack 中的错误,在 0.18.0 中得到修复,导致 Python 2 打包的文件无法被 Python 3 读取 (GH 12142)。以下表格描述了 msgpack 的向后和向前兼容性。

警告

打包于 可以解包于
pre-0.17 / Python 2 任何
pre-0.17 / Python 3 任何
0.17 / Python 2
  • ==0.17 / Python 2

  • =0.18 / 任何 Python

|

0.17 / Python 3 >=0.18 / 任何 Python
0.18 >= 0.18

0.18.0 对于读取由旧版本打包的文件是向后兼容的,除了在 Python 2 中使用 0.17 打包的文件,这种情况下只能在 Python 2 中解包。

.rank 的签名更改

Series.rankDataFrame.rank 现在具有相同的签名 (GH 11759)

先前的签名

In [3]: pd.Series([0,1]).rank(method='average', na_option='keep',
 ascending=True, pct=False)
Out[3]:
0    1
1    2
dtype: float64

In [4]: pd.DataFrame([0,1]).rank(axis=0, numeric_only=None,
 method='average', na_option='keep',
 ascending=True, pct=False)
Out[4]:
 0
0  1
1  2 

新签名

In [71]: pd.Series([0,1]).rank(axis=0, method='average', numeric_only=False,
 ....:                      na_option='keep', ascending=True, pct=False)
 ....: 
Out[71]: 
0    1.0
1    2.0
Length: 2, dtype: float64

In [72]: pd.DataFrame([0,1]).rank(axis=0, method='average', numeric_only=False,
 ....:                         na_option='keep', ascending=True, pct=False)
 ....: 
Out[72]: 
 0
0  1.0
1  2.0

[2 rows x 1 columns] 

QuarterBeginn=0 时的错误

在先前的版本中,QuarterBegin 偏移的行为取决于 n 参数为 0 时的日期是不一致的。 (GH 11406)

对于 n=0 的锚定偏移的一般语义是,当它是一个锚点(例如,一个季度开始日期)时不移动日期,否则向前滚动到下一个锚点。

In [73]: d = pd.Timestamp('2014-02-01')

In [74]: d
Out[74]: Timestamp('2014-02-01 00:00:00')

In [75]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[75]: Timestamp('2014-02-01 00:00:00')

In [76]: d + pd.offsets.QuarterBegin(n=0, startingMonth=1)
Out[76]: Timestamp('2014-04-01 00:00:00') 

对于之前版本中的 QuarterBegin 偏移量,如果日期与季度开始日期在同一个月,则日期会向滚动。

In [3]: d = pd.Timestamp('2014-02-15')

In [4]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[4]: Timestamp('2014-02-01 00:00:00') 

在版本 0.18.0 中已更正此行为,与 MonthBeginYearBegin 等其他锚定偏移一致。

In [77]: d = pd.Timestamp('2014-02-15')

In [78]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[78]: Timestamp('2014-05-01 00:00:00') 

重采样 API

像窗口函数 API 中的变化 上文 一样,.resample(...) 正在改变为更类似于 groupby 的 API。(GH 11732, GH 12702, GH 12202, GH 12332, GH 12334, GH 12348, GH 12448)。

In [79]: np.random.seed(1234)

In [80]: df = pd.DataFrame(np.random.rand(10,4),
 ....:                  columns=list('ABCD'),
 ....:                  index=pd.date_range('2010-01-01 09:00:00',
 ....:                                      periods=10, freq='s'))
 ....: 

In [81]: df
Out[81]: 
 A         B         C         D
2010-01-01 09:00:00  0.191519  0.622109  0.437728  0.785359
2010-01-01 09:00:01  0.779976  0.272593  0.276464  0.801872
2010-01-01 09:00:02  0.958139  0.875933  0.357817  0.500995
2010-01-01 09:00:03  0.683463  0.712702  0.370251  0.561196
2010-01-01 09:00:04  0.503083  0.013768  0.772827  0.882641
2010-01-01 09:00:05  0.364886  0.615396  0.075381  0.368824
2010-01-01 09:00:06  0.933140  0.651378  0.397203  0.788730
2010-01-01 09:00:07  0.316836  0.568099  0.869127  0.436173
2010-01-01 09:00:08  0.802148  0.143767  0.704261  0.704581
2010-01-01 09:00:09  0.218792  0.924868  0.442141  0.909316

[10 rows x 4 columns] 

以前的 API:

您将编写一个立即执行的重采样操作。如果未提供 how 参数,则默认为 how='mean'

In [6]: df.resample('2s')
Out[6]:
 A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949 

您还可以直接指定一个 how

In [7]: df.resample('2s', how='sum')
Out[7]:
 A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897 

新的 API:

现在,您可以将 .resample(..) 写成类似于 .groupby(...) 的 2 阶段操作,从而产生一个 Resampler

In [82]: r = df.resample('2s')

In [83]: r
Out[83]: <pandas.core.resample.DatetimeIndexResampler object at 0x7ff230e71c30> 

下采样

然后,您可以使用此对象执行操作。这些是下采样操作 (从较高频率到较低频率)。

In [84]: r.mean()
Out[84]: 
 A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949

[5 rows x 4 columns] 
In [85]: r.sum()
Out[85]: 
 A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897

[5 rows x 4 columns] 

此外,现在重采样还支持 getitem 操作,以在特定列上执行重采样。

In [86]: r[['A','C']].mean()
Out[86]: 
 A         C
2010-01-01 09:00:00  0.485748  0.357096
2010-01-01 09:00:02  0.820801  0.364034
2010-01-01 09:00:04  0.433985  0.424104
2010-01-01 09:00:06  0.624988  0.633165
2010-01-01 09:00:08  0.510470  0.573201

[5 rows x 2 columns] 

.aggregate 类型的操作。

In [87]: r.agg({'A' : 'mean', 'B' : 'sum'})
Out[87]: 
 A         B
2010-01-01 09:00:00  0.485748  0.894701
2010-01-01 09:00:02  0.820801  1.588635
2010-01-01 09:00:04  0.433985  0.629165
2010-01-01 09:00:06  0.624988  1.219477
2010-01-01 09:00:08  0.510470  1.068634

[5 rows x 2 columns] 

当然,这些访问器可以组合

In [88]: r[['A','B']].agg(['mean','sum'])
Out[88]: 
 A                   B 
 mean       sum      mean       sum
2010-01-01 09:00:00  0.485748  0.971495  0.447351  0.894701
2010-01-01 09:00:02  0.820801  1.641602  0.794317  1.588635
2010-01-01 09:00:04  0.433985  0.867969  0.314582  0.629165
2010-01-01 09:00:06  0.624988  1.249976  0.609738  1.219477
2010-01-01 09:00:08  0.510470  1.020940  0.534317  1.068634

[5 rows x 4 columns] 

上采样

上采样操作将频率从较低的转换为较高的。现在使用 Resampler 对象和 backfill()ffill()fillna()asfreq() 方法执行这些操作。

In [89]: s = pd.Series(np.arange(5, dtype='int64'),
 index=pd.date_range('2010-01-01', periods=5, freq='Q'))

In [90]: s
Out[90]:
2010-03-31    0
2010-06-30    1
2010-09-30    2
2010-12-31    3
2011-03-31    4
Freq: Q-DEC, Length: 5, dtype: int64 

以前

In [6]: s.resample('M', fill_method='ffill')
Out[6]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, dtype: int64 

新 API

In [91]: s.resample('M').ffill()
Out[91]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, Length: 13, dtype: int64 

注意

在新的 API 中,您可以进行下采样或上采样。以前的实现允许您传递聚合函数 (如 mean),即使您在上采样,也会造成一些混乱。

以前的 API 将继续工作,但会有弃用警告

警告

这种重采样的新 API 包括一些内部更改,以与 0.18.0 之前的 API 兼容,大多数情况下都会出现弃用警告,因为重采样操作返回了一个延迟对象。我们可以截获操作并像 (pre 0.18.0) API 一样执行它们 (带有警告)。这是一个典型的用例:

In [4]: r = df.resample('2s')

In [6]: r*10
pandas/tseries/resample.py:80: FutureWarning: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...)

Out[6]:
 A         B         C         D
2010-01-01 09:00:00  4.857476  4.473507  3.570960  7.936154
2010-01-01 09:00:02  8.208011  7.943173  3.640340  5.310957
2010-01-01 09:00:04  4.339846  3.145823  4.241039  6.257326
2010-01-01 09:00:06  6.249881  6.097384  6.331650  6.124518
2010-01-01 09:00:08  5.104699  5.343172  5.732009  8.069486 

然而,直接在 Resampler 上进行获取和赋值操作将引发 ValueError

In [7]: r.iloc[0] = 5
ValueError: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...) 

有一种情况是,当使用原始代码时,新 API 无法执行所有操作。这段代码意在对数据进行 2s 重采样,然后取 mean 再取这些结果的 min

In [4]: df.resample('2s').min()
Out[4]:
A    0.433985
B    0.314582
C    0.357096
D    0.531096
dtype: float64 

新的 API 将:

In [89]: df.resample('2s').min()
Out[89]: 
 A         B         C         D
2010-01-01 09:00:00  0.191519  0.272593  0.276464  0.785359
2010-01-01 09:00:02  0.683463  0.712702  0.357817  0.500995
2010-01-01 09:00:04  0.364886  0.013768  0.075381  0.368824
2010-01-01 09:00:06  0.316836  0.568099  0.397203  0.436173
2010-01-01 09:00:08  0.218792  0.143767  0.442141  0.704581

[5 rows x 4 columns] 

好消息是,新 API 和旧 API 的返回维度将不同,因此这应该会引发异常。

复制原始操作

In [90]: df.resample('2s').mean().min()
Out[90]: 
A    0.433985
B    0.314582
C    0.357096
D    0.531096
Length: 4, dtype: float64 

对 eval 的更改

在之前的版本中,在 eval 表达式中进行新列赋值会导致对 DataFrame 的原地更改。 (GH 9297, GH 8664, GH 10486)

In [91]: df = pd.DataFrame({'a': np.linspace(0, 10, 5), 'b': range(5)})

In [92]: df
Out[92]: 
 a  b
0   0.0  0
1   2.5  1
2   5.0  2
3   7.5  3
4  10.0  4

[5 rows x 2 columns] 
In [12]: df.eval('c = a + b')
FutureWarning: eval expressions containing an assignment currentlydefault to operating inplace.
This will change in a future version of pandas, use inplace=True to avoid this warning.

In [13]: df
Out[13]:
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0 

在版本 0.18.0 中,新增了一个 inplace 关键字,用于选择是否应该原地进行赋值还是返回一个副本。

In [93]: df
Out[93]: 
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [94]: df.eval('d = c - b', inplace=False)
Out[94]: 
 a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns]

In [95]: df
Out[95]: 
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [96]: df.eval('d = c - b', inplace=True)

In [97]: df
Out[97]: 
 a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns] 

警告

为了向后兼容,如果未指定,默认情况下 inplaceTrue。这将在未来的 pandas 版本中更改。如果您的代码依赖于原地赋值,应更新为显式设置 inplace=True

query 方法还添加了 inplace 关键字参数。

In [98]: df.query('a > 5')
Out[98]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [99]: df.query('a > 5', inplace=True)

In [100]: df
Out[100]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns] 

警告

请注意,在 queryinplace 的默认值为 False,与之前的版本保持一致。

eval 也已更新,允许多行表达式进行多个赋值。这些表达式将按顺序逐个进行评估。只有赋值对于多行表达式是有效的。

In [101]: df
Out[101]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [102]: df.eval("""
 .....: e = d + a
 .....: f = e - 22
 .....: g = f / 2.0""", inplace=True)
 .....: 

In [103]: df
Out[103]: 
 a  b     c     d     e    f    g
3   7.5  3  10.5   7.5  15.0 -7.0 -3.5
4  10.0  4  14.0  10.0  20.0 -2.0 -1.0

[2 rows x 7 columns] 

其他 API 更改

  • DataFrame.between_timeSeries.between_time 现在只解析一组固定的时间字符串。不再支持日期字符串的解析,会引发 ValueError。 (GH 11818)

    In [107]: s = pd.Series(range(10), pd.date_range('2015-01-01', freq='H', periods=10))
    
    In [108]: s.between_time("7:00am", "9:00am")
    Out[108]:
    2015-01-01 07:00:00    7
    2015-01-01 08:00:00    8
    2015-01-01 09:00:00    9
    Freq: H, Length: 3, dtype: int64 
    

    现在会引发错误。

    In [2]: s.between_time('20150101 07:00:00','20150101 09:00:00')
    ValueError: Cannot convert arg ['20150101 07:00:00'] to a time. 
    
  • .memory_usage() 现在包括索引中的值,.info() 中的 memory_usage 也是如此。 (GH 11597)

  • DataFrame.to_latex() 现在支持在 Python 2 中使用 encoding 参数进行非 ASCII 编码(例如 utf-8) (GH 7061)

  • 当尝试与不是 DataFrame 或其子类的对象进行合并时,pandas.merge()DataFrame.merge() 将显示特定的错误消息 (GH 12081)

  • DataFrame.unstackSeries.unstack 现在接受 fill_value 关键字,以允许在解除堆叠导致结果 DataFrame 中出现缺失值时直接替换缺失值。另一个好处是,指定 fill_value 将保留原始堆叠数据的数据类型。 (GH 9746)

  • 作为 窗口函数 和 重采样 的新 API 的一部分,聚合函数已经得到澄清,在无效的聚合上提供更具信息性的错误消息。 (GH 9052)。在 groupby 中提供了一整套示例。

  • NDFrame 对象的统计函数(如 sum(), mean(), min())现在会在传递给 **kwargs 的非 numpy 兼容参数时引发错误。 (GH 12301)

  • .to_latex.to_html 增加了一个 decimal 参数,类似于 .to_csv;默认值为 '.' (GH 12031)

  • 构造带有空数据但具有索引的DataFrame时,显示更有帮助的错误消息(GH 8020

  • .describe()现在将正确处理布尔类型作为分类类型(GH 6625

  • 使用自定义输入时,.transform出现无效时,错误消息更具帮助性(GH 10165

  • 现在,指数加权函数允许直接指定 alpha(GH 10789),并且如果参数违反0 < alpha <= 1,则会引发ValueErrorGH 12492) ### 弃用

  • 函数 pd.rolling_*pd.expanding_*pd.ewm* 已弃用,并由相应的方法调用替换。请注意,新建议的语法包括所有参数(即使是默认值)(GH 11603

    In [1]: s = pd.Series(range(3))
    
    In [2]: pd.rolling_mean(s,window=2,min_periods=1)
     FutureWarning: pd.rolling_mean is deprecated for Series and
     will be removed in a future version, replace with
     Series.rolling(min_periods=1,window=2,center=False).mean()
    Out[2]:
     0    0.0
     1    0.5
     2    1.5
     dtype: float64
    
    In [3]: pd.rolling_cov(s, s, window=2)
     FutureWarning: pd.rolling_cov is deprecated for Series and
     will be removed in a future version, replace with
     Series.rolling(window=2).cov(other=<Series>)
    Out[3]:
     0    NaN
     1    0.5
     2    0.5
     dtype: float64 
    
  • .rolling.expanding.ewm(新)函数的freqhow参数已弃用,并将在将来的版本中移除。您可以在创建窗口函数之前简单地重新采样输入。(GH 11603)。

    例如,不再使用 s.rolling(window=5,freq='D').max() 来获取滚动 5 天窗口的最大值,可以使用 s.resample('D').mean().rolling(window=5).max(),它首先将数据重新采样为每日数据,然后提供一个滚动 5 天的窗口。

  • pd.tseries.frequencies.get_offset_name函数已弃用。使用偏移的.freqstr属性作为替代(GH 11192

  • pandas.stats.fama_macbeth例程已弃用,并将在将来的版本中移除(GH 6077

  • pandas.stats.olspandas.stats.plmpandas.stats.var例程已弃用,并将在将来的版本中移除(GH 6077

  • HDFStore.select中使用长时间弃用的语法时,显示一个FutureWarning而不是一个DeprecationWarning,其中where子句不是字符串类似的(GH 12027

  • pandas.options.display.mpl_style配置已弃用,并将在将来的版本中移除 pandas。此功能更好地由 matplotlib 的样式表处理(GH 11783)。 ### 移除已弃用的浮点索引器

GH 4892 中,对非Float64Index的浮点数进行索引已弃用(在版本 0.14.0 中)。在 0.18.0 中,此弃用警告已被移除,现在将引发TypeError。(GH 12165GH 12333

In [104]: s = pd.Series([1, 2, 3], index=[4, 5, 6])

In [105]: s
Out[105]: 
4    1
5    2
6    3
Length: 3, dtype: int64

In [106]: s2 = pd.Series([1, 2, 3], index=list('abc'))

In [107]: s2
Out[107]: 
a    1
b    2
c    3
Length: 3, dtype: int64 

之前的行为:

# this is label indexing
In [2]: s[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[2]: 2

# this is positional indexing
In [3]: s.iloc[1.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[3]: 2

# this is label indexing
In [4]: s.loc[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[4]: 2

# .ix would coerce 1.0 to the positional 1, and index
In [5]: s2.ix[1.0] = 10
FutureWarning: scalar indexers for index type Index should be integers and not floating point

In [6]: s2
Out[6]:
a     1
b    10
c     3
dtype: int64 

新行为:

对于 iloc,通过浮点标量进行获取和设置将始终引发异常。

In [3]: s.iloc[2.0]
TypeError: cannot do label indexing on <class 'pandas.indexes.numeric.Int64Index'> with these indexers [2.0] of <type 'float'> 

其他索引器将对获取和设置都强制转换为相似的整数。 对于.loc.ix[]FutureWarning已被删除。

In [108]: s[5.0]
Out[108]: 2

In [109]: s.loc[5.0]
Out[109]: 2 

和设置

In [110]: s_copy = s.copy()

In [111]: s_copy[5.0] = 10

In [112]: s_copy
Out[112]: 
4     1
5    10
6     3
Length: 3, dtype: int64

In [113]: s_copy = s.copy()

In [114]: s_copy.loc[5.0] = 10

In [115]: s_copy
Out[115]: 
4     1
5    10
6     3
Length: 3, dtype: int64 

使用.ix和浮点索引器进行位置设置将将此值添加到索引中,而不是先前根据位置设置值。

In [3]: s2.ix[1.0] = 10
In [4]: s2
Out[4]:
a       1
b       2
c       3
1.0    10
dtype: int64 

对于非Float64Index,切片还将整数样式的浮点数强制转换为整数。

In [116]: s.loc[5.0:6]
Out[116]: 
5    2
6    3
Length: 2, dtype: int64 

请注意,对于不能强制转换为整数的浮点数,基于标签的边界将被排除

In [117]: s.loc[5.1:6]
Out[117]: 
6    3
Length: 1, dtype: int64 

浮点索引在Float64Index上保持不变。

In [118]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [119]: s[1.0]
Out[119]: 2

In [120]: s[1.0:2.5]
Out[120]: 
1.0    2
2.0    3
Length: 2, dtype: int64 
```  ### 删除先前版本的过时/更改

+   改用`.rolling().corr(pairwise=True)`替代`rolling_corr_pairwise`([GH 4950](https://github.com/pandas-dev/pandas/issues/4950))

+   改用`.expanding().corr(pairwise=True)`替代`expanding_corr_pairwise`([GH 4950](https://github.com/pandas-dev/pandas/issues/4950))

+   删除了`DataMatrix`模块。 这在任何情况下都没有被导入到 pandas 命名空间中([GH 12111](https://github.com/pandas-dev/pandas/issues/12111))

+   删除了`DataFrame.duplicated()`和`DataFrame.drop_duplicates()`中的`cols`关键字,而使用`subset`([GH 6680](https://github.com/pandas-dev/pandas/issues/6680))

+   在`pd.io.sql`命名空间中,删除了自 0.14.0 起被弃用的`read_frame`和`frame_query`(均为`pd.read_sql`的别名)以及`write_frame`(`to_sql`的别名)函数([GH 6292](https://github.com/pandas-dev/pandas/issues/6292))。

+   从`.factorize()`中删除了`order`关键字([GH 6930](https://github.com/pandas-dev/pandas/issues/6930))  ## 性能改进

+   改进了`andrews_curves`的性能([GH 11534](https://github.com/pandas-dev/pandas/issues/11534))

+   改进了大型`DatetimeIndex`、`PeriodIndex`和`TimedeltaIndex`的操作性能,包括`NaT`([GH 10277](https://github.com/pandas-dev/pandas/issues/10277))

+   改进了`pandas.concat`的性能([GH 11958](https://github.com/pandas-dev/pandas/issues/11958))

+   改进了`StataReader`的性能([GH 11591](https://github.com/pandas-dev/pandas/issues/11591))

+   改进了包含`NaT`的日期时间的`Series`构造`Categoricals`的性能([GH 12077](https://github.com/pandas-dev/pandas/issues/12077))

+   改进了没有分隔符的 ISO 8601 日期解析的性能([GH 11899](https://github.com/pandas-dev/pandas/issues/11899)),在时间戳之前有前导零([GH 11871](https://github.com/pandas-dev/pandas/issues/11871))以及具有空白区域的时区([GH 9714](https://github.com/pandas-dev/pandas/issues/9714))  ## Bug 修复

+   当数据框为空时,`GroupBy.size`中存在错误。 ([GH 11699](https://github.com/pandas-dev/pandas/issues/11699))

+   在请求多个时间段的`Period.end_time`中存在错误([GH 11738](https://github.com/pandas-dev/pandas/issues/11738))

+   在具有时区感知日期时间的`.clip`中存在回归([GH 11838](https://github.com/pandas-dev/pandas/issues/11838))

+   当边界落在频率上时,`date_range`存在错误([GH 11804](https://github.com/pandas-dev/pandas/issues/11804),[GH 12409](https://github.com/pandas-dev/pandas/issues/12409))

+   将嵌套字典传递给`.groupby(...).agg(...)`时存在一致性错误([GH 9052](https://github.com/pandas-dev/pandas/issues/9052))

+   接受`Timedelta`构造函数中的 Unicode([GH 11995](https://github.com/pandas-dev/pandas/issues/11995))

+   在逐步读取时,对`StataReader`的值标签读取存在错误([GH 12014](https://github.com/pandas-dev/pandas/issues/12014))

+   当`n`参数为`0`时,向量化`DateOffset`存在错误([GH 11370](https://github.com/pandas-dev/pandas/issues/11370))

+   关于 numpy 1.11 的兼容性,涉及到`NaT`比较的更改([GH 12049](https://github.com/pandas-dev/pandas/issues/12049))

+   在线程中从`StringIO`读取时,`read_csv`存在错误([GH 11790](https://github.com/pandas-dev/pandas/issues/11790))

+   在对 datetimelikes 进行因子化且使用`Categoricals`时,未将`NaT`视为缺失值时存在错误([GH 12077](https://github.com/pandas-dev/pandas/issues/12077))

+   当`Series`的值带有时区时,getitem 存在错误([GH 12089](https://github.com/pandas-dev/pandas/issues/12089))

+   当其中一个变量为'name'时,`Series.str.get_dummies`存在错误([GH 12180](https://github.com/pandas-dev/pandas/issues/12180))

+   在连接时,`pd.concat`存在错误,同时连接带有时区的 NaT 系列。([GH 11693](https://github.com/pandas-dev/pandas/issues/11693),[GH 11755](https://github.com/pandas-dev/pandas/issues/11755),[GH 12217](https://github.com/pandas-dev/pandas/issues/12217))

+   在版本<= 108 文件中使用`pd.read_stata`存在错误([GH 12232](https://github.com/pandas-dev/pandas/issues/12232))

+   当索引为`DatetimeIndex`且包含非零纳秒部分时,使用`Nano`频率进行`Series.resample`存在错误([GH 12037](https://github.com/pandas-dev/pandas/issues/12037))

+   在稀疏索引中使用`.nunique`进行重新采样存在错误([GH 12352](https://github.com/pandas-dev/pandas/issues/12352))

+   删除了一些编译器警告([GH 12471](https://github.com/pandas-dev/pandas/issues/12471))

+   解决了 python 3.5 中`boto`的兼容问题([GH 11915](https://github.com/pandas-dev/pandas/issues/11915))

+   在带有时区的`Timestamp`或`DatetimeIndex`中减去`NaT`时存在错误([GH 11718](https://github.com/pandas-dev/pandas/issues/11718))

+   在单个带时区的`Timestamp`的`Series`减法中存在错误([GH 12290](https://github.com/pandas-dev/pandas/issues/12290))

+   在 PY2 中使用兼容迭代器来支持`.next()`([GH 12299](https://github.com/pandas-dev/pandas/issues/12299))

+   对负值进行`Timedelta.round`时的错误([GH 11690](https://github.com/pandas-dev/pandas/issues/11690))

+   在`CategoricalIndex`上针对`.loc`可能导致普通`Index`的错误([GH 11586](https://github.com/pandas-dev/pandas/issues/11586))

+   当存在重复列名时,`DataFrame.info`存在错误([GH 11761](https://github.com/pandas-dev/pandas/issues/11761))

+   在具有时区感知对象的`.copy`中存在的错误([GH 11794](https://github.com/pandas-dev/pandas/issues/11794))

+   `Series.apply`和`Series.map`中存在的错误,`timedelta64`未被包装([GH 11349](https://github.com/pandas-dev/pandas/issues/11349))

+   `DataFrame.set_index()`中存在的错误,带有 tz-aware `Series`([GH 12358](https://github.com/pandas-dev/pandas/issues/12358))

+   `DataFrame`的子类中存��的错误,`AttributeError`未传播([GH 11808](https://github.com/pandas-dev/pandas/issues/11808))

+   在 tz-aware 数据上进行 groupby 时,选择不返回`Timestamp`的错误([GH 11616](https://github.com/pandas-dev/pandas/issues/11616))

+   `pd.read_clipboard`和`pd.to_clipboard`函数中存在不支持 Unicode 的错误;升级包括`pyperclip`到 v1.5.15([GH 9263](https://github.com/pandas-dev/pandas/issues/9263))

+   包含赋值的`DataFrame.query`中存在的错误([GH 8664](https://github.com/pandas-dev/pandas/issues/8664))

+   在`from_msgpack`中存在的错误,如果`DataFrame`具有对象列,则解压缩的`DataFrame`的列的`__contains__()`失败。 ([GH 11880](https://github.com/pandas-dev/pandas/issues/11880))

+   在具有`TimedeltaIndex`的分类数据上进行`.resample`时存在的错误([GH 12169](https://github.com/pandas-dev/pandas/issues/12169))

+   在将标量日期时间广播到`DataFrame`时,时区信息丢失的错误([GH 11682](https://github.com/pandas-dev/pandas/issues/11682))

+   从带有混合 tz 的`Timestamp`创建`Index`时,强制转换为 UTC 的错误([GH 11488](https://github.com/pandas-dev/pandas/issues/11488))

+   `to_numeric`中存在的错误,如果输入超过一个维度,则不会引发错误([GH 11776](https://github.com/pandas-dev/pandas/issues/11776))

+   解析具有非零分钟的时区偏移字符串时存在的错误([GH 11708](https://github.com/pandas-dev/pandas/issues/11708))

+   在 matplotlib 1.5+下,`df.plot`中的错误导致条形图使用不正确的颜色([GH 11614](https://github.com/pandas-dev/pandas/issues/11614))

+   使用关键字参数时,`groupby` `plot`方法中存在错误([GH 11805](https://github.com/pandas-dev/pandas/issues/11805))。

+   在设置`keep=False`时,`DataFrame.duplicated`和`drop_duplicates`中存在错误导致虚假匹配([GH 11864](https://github.com/pandas-dev/pandas/issues/11864))

+   具有重复键的`.loc`结果可能具有不正确 dtype 的`Index`([GH 11497](https://github.com/pandas-dev/pandas/issues/11497))

+   `pd.rolling_median`中存在的错误,即使内存充足也会导致内存分配失败([GH 11696](https://github.com/pandas-dev/pandas/issues/11696))

+   `DataFrame.style`中存在虚假零值的错误([GH 12134](https://github.com/pandas-dev/pandas/issues/12134))

+   `DataFrame.style`中存在的错误,整数列不从 0 开始([GH 12125](https://github.com/pandas-dev/pandas/issues/12125))

+   `.style.bar`中的错误可能在特定浏览器中无法正确渲染([GH 11678](https://github.com/pandas-dev/pandas/issues/11678))

+   `Timedelta` 类型与 `numpy.array` 中的 `Timedelta` 进行丰富比较时出现无限递归的错误([GH 11835](https://github.com/pandas-dev/pandas/issues/11835))

+   `DataFrame.round` 函数存在删除列索引名称的错误([GH 11986](https://github.com/pandas-dev/pandas/issues/11986))

+   在替换混合类型 `Dataframe` 中的值时,`df.replace` 函数存在错误([GH 11698](https://github.com/pandas-dev/pandas/issues/11698))

+   当没有提供新名称时,`Index` 类的复制名称存在错误([GH 11193](https://github.com/pandas-dev/pandas/issues/11193))

+   `read_excel` 函数在存在空表且 `sheetname=None` 时无法读取任何非空表的错误([GH 11711](https://github.com/pandas-dev/pandas/issues/11711))

+   `read_excel` 函数在提供 `parse_dates` 和 `date_parser` 关键字时未能引发 `NotImplemented` 错误([GH 11544](https://github.com/pandas-dev/pandas/issues/11544))

+   `pymysql` 连接中 `read_sql` 函数存在错误,无法返回分块数据([GH 11522](https://github.com/pandas-dev/pandas/issues/11522))

+   `.to_csv` 函数忽略浮点索引的格式化参数 `decimal`、`na_rep`、`float_format` 的错误([GH 11553](https://github.com/pandas-dev/pandas/issues/11553))

+   `Int64Index` 和 `Float64Index` 函数中无法使用取模运算符的错误([GH 9244](https://github.com/pandas-dev/pandas/issues/9244))

+   `MultiIndex.drop` 函数对未按词典顺序排列的多级索引存在错误([GH 12078](https://github.com/pandas-dev/pandas/issues/12078))

+   当遮蔽一个空的 `DataFrame` 时出现错误([GH 11859](https://github.com/pandas-dev/pandas/issues/11859))

+   当列数与提供的系列数不匹配时,`.plot` 函数可能修改 `colors` 输入的错误([GH 12039](https://github.com/pandas-dev/pandas/issues/12039))

+   当索引具有 `CustomBusinessDay` 频率时,`Series.plot` 函数无法绘制的错误([GH 7222](https://github.com/pandas-dev/pandas/issues/7222))

+   使用 sqlite 回退时,`.to_sql` 函数存在 `datetime.time` 值的错误([GH 8341](https://github.com/pandas-dev/pandas/issues/8341))

+   `read_excel` 函数在 `squeeze=True` 时无法读取只有一列数据的错误([GH 12157](https://github.com/pandas-dev/pandas/issues/12157))

+   `read_excel` 函数存在无法读取一个空列的错误([GH 12292](https://github.com/pandas-dev/pandas/issues/12292),[GH 9002](https://github.com/pandas-dev/pandas/issues/9002))

+   `.groupby` 函数在数据框中只有一行时,如果列名错误未引发 `KeyError` 的错误([GH 11741](https://github.com/pandas-dev/pandas/issues/11741))

+   在指定空数据上指定 dtype 时,`.read_csv` 函数产生错误的错误([GH 12048](https://github.com/pandas-dev/pandas/issues/12048))

+   `.read_csv` 函数将字符串如 `'2E'` 视为有效浮点数的错误([GH 12237](https://github.com/pandas-dev/pandas/issues/12237))

+   使用调试符号构建 *pandas* 出现错误([GH 12123](https://github.com/pandas-dev/pandas/issues/12123))

+   移除了`DatetimeIndex`的`millisecond`属性。这将始终引发`ValueError` ([GH 12019](https://github.com/pandas-dev/pandas/issues/12019)).

+   在具有只读数据的`Series`构造函数中出现的错误 ([GH 11502](https://github.com/pandas-dev/pandas/issues/11502))

+   移除了`pandas._testing.choice()`。应该使用`np.random.choice()`代替。 ([GH 12386](https://github.com/pandas-dev/pandas/issues/12386))

+   在`.loc` setitem 索引器中阻止使用 TZ-aware DatetimeIndex 的错误 ([GH 12050](https://github.com/pandas-dev/pandas/issues/12050))

+   在`.style`中索引和 MultiIndexes 未显示的错误 ([GH 11655](https://github.com/pandas-dev/pandas/issues/11655))

+   在`to_msgpack`和`from_msgpack`中,未正确序列化或反序列化`NaT`的错误 ([GH 12307](https://github.com/pandas-dev/pandas/issues/12307)).

+   由于高度相似值的四舍五入误差,导致`.skew`和`.kurt`中的错误 ([GH 11974](https://github.com/pandas-dev/pandas/issues/11974))

+   在`Timestamp`构造函数中,如果 HHMMSS 没有用‘:’分隔,微秒分辨率会丢失的错误 ([GH 10041](https://github.com/pandas-dev/pandas/issues/10041))

+   在`buffer_rd_bytes`中,如果读取失败,src->buffer 可能会被释放多次,导致段错误的错误 ([GH 12098](https://github.com/pandas-dev/pandas/issues/12098))

+   在`crosstab`中,具有不重叠索引的参数会返回`KeyError`的错误 ([GH 10291](https://github.com/pandas-dev/pandas/issues/10291))

+   在`DataFrame.apply`中,如果`dtype`不是 numpy dtype,则未阻止缩减的错误 ([GH 12244](https://github.com/pandas-dev/pandas/issues/12244))

+   初始化分类系列时出现的错误。([GH 12336](https://github.com/pandas-dev/pandas/issues/12336))

+   在`.to_datetime`中通过设置`utc=True`指定 UTC `DatetimeIndex`时出现的错误 ([GH 11934](https://github.com/pandas-dev/pandas/issues/11934))

+   在`read_csv`中增加 CSV 读取器缓冲区大小时出现的错误 ([GH 12494](https://github.com/pandas-dev/pandas/issues/12494))

+   在设置具有重复列名的`DataFrame`的列时出现的错误 ([GH 12344](https://github.com/pandas-dev/pandas/issues/12344))  ## 贡献者

总共有 101 人为这个版本贡献了补丁。名字后面带有“+”的人第一次贡献了补丁。

+   ARF +

+   Alex Alekseyev +

+   Andrew McPherson +

+   Andrew Rosenfeld

+   Andy Hayden

+   Anthonios Partheniou

+   Anton I. Sipos

+   Ben +

+   Ben North +

+   Bran Yang +

+   Chris

+   Chris Carroux +

+   Christopher C. Aycock +

+   Christopher Scanlin +

+   Cody +

+   Da Wang +

+   Daniel Grady +

+   Dorozhko Anton +

+   Dr-Irv +

+   Erik M. Bray +

+   Evan Wright

+   Francis T. O’Donovan +

+   Frank Cleary +

+   Gianluca Rossi

+   Graham Jeffries +

+   Guillaume Horel

+   Henry Hammond +

+   Isaac Schwabacher +

+   Jean-Mathieu Deschenes

+   Jeff Reback

+   Joe Jevnik +

+   John Freeman +

+   John Fremlin +

+   Jonas Hoersch +

+   Joris Van den Bossche

+   Joris Vankerschaver

+   Justin Lecher

+   Justin Lin +

+   Ka Wo Chen

+   Keming Zhang +

+   Kerby Shedden

+   Kyle +

+   Marco Farrugia +

+   MasonGallo +

+   MattRijk +

+   Matthew Lurie +

+   Maximilian Roos

+   Mayank Asthana +

+   Mortada Mehyar

+   Moussa Taifi +

+   Navreet Gill +

+   Nicolas Bonnotte

+   Paul Reiners +

+   Philip Gura +

+   Pietro Battiston

+   RahulHP +

+   Randy Carnevale

+   Rinoc Johnson

+   Rishipuri +

+   Sangmin Park +

+   Scott E Lasley

+   Sereger13 +

+   Shannon Wang +

+   Skipper Seabold

+   Thierry Moisan

+   Thomas A Caswell

+   Toby Dylan Hocking +

+   Tom Augspurger

+   Travis +

+   Trent Hauck

+   Tux1

+   Varun

+   Wes McKinney

+   Will Thompson +

+   Yoav Ram

+   Yoong Kang Lim +

+   Yoshiki Vázquez Baeza

+   Young Joong Kim +

+   Younggun Kim

+   Yuval Langer +

+   alex argunov +

+   behzad nouri

+   boombard +

+   brian-pantano +

+   chromy +

+   daniel +

+   dgram0 +

+   gfyoung +

+   hack-c +

+   hcontrast +

+   jfoo +

+   kaustuv deolal +

+   llllllllll

+   ranarag +

+   rockg

+   scls19fr

+   seales +

+   sinhrks

+   srib +

+   surveymedia.ca +

+   tworec +  ## 新功能

### 窗口函数现在是方法

窗口函数已重构为`Series/DataFrame`对象的方法,而不是顶层函数,后者现已弃用。这允许这些窗口类型函数具有与`.groupby`相似的 API。请参阅完整文档此处 ([GH 11603](https://github.com/pandas-dev/pandas/issues/11603), [GH 12373](https://github.com/pandas-dev/pandas/issues/12373))

```py
In [1]: np.random.seed(1234)

In [2]: df = pd.DataFrame({'A': range(10), 'B': np.random.randn(10)})

In [3]: df
Out[3]: 
 A         B
0  0  0.471435
1  1 -1.190976
2  2  1.432707
3  3 -0.312652
4  4 -0.720589
5  5  0.887163
6  6  0.859588
7  7 -0.636524
8  8  0.015696
9  9 -2.242685

[10 rows x 2 columns] 

以前的行为:

In [8]: pd.rolling_mean(df, window=3)
 FutureWarning: pd.rolling_mean is deprecated for DataFrame and will be removed in a future version, replace with
 DataFrame.rolling(window=3,center=False).mean()
Out[8]:
 A         B
0 NaN       NaN
1 NaN       NaN
2   1  0.237722
3   2 -0.023640
4   3  0.133155
5   4 -0.048693
6   5  0.342054
7   6  0.370076
8   7  0.079587
9   8 -0.954504 

新的行为:

In [4]: r = df.rolling(window=3) 

这些显示了描述性 repr

In [5]: r
Out[5]: Rolling [window=3,center=False,axis=0,method=single] 

可用方法和属性的 Tab 补全。

In [9]: r.<TAB>  # noqa E225, E999
r.A           r.agg         r.apply       r.count       r.exclusions  r.max         r.median      r.name        r.skew        r.sum
r.B           r.aggregate   r.corr        r.cov         r.kurt        r.mean        r.min         r.quantile    r.std         r.var 

这些方法作用于Rolling对象本身

In [6]: r.mean()
Out[6]: 
 A         B
0  NaN       NaN
1  NaN       NaN
2  1.0  0.237722
3  2.0 -0.023640
4  3.0  0.133155
5  4.0 -0.048693
6  5.0  0.342054
7  6.0  0.370076
8  7.0  0.079587
9  8.0 -0.954504

[10 rows x 2 columns] 

它们提供 getitem 访问器

In [7]: r['A'].mean()
Out[7]: 
0    NaN
1    NaN
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    6.0
8    7.0
9    8.0
Name: A, Length: 10, dtype: float64 

和多重聚合

In [8]: r.agg({'A': ['mean', 'std'],
 ...:       'B': ['mean', 'std']})
 ...: 
Out[8]: 
 A              B 
 mean  std      mean       std
0  NaN  NaN       NaN       NaN
1  NaN  NaN       NaN       NaN
2  1.0  1.0  0.237722  1.327364
3  2.0  1.0 -0.023640  1.335505
4  3.0  1.0  0.133155  1.143778
5  4.0  1.0 -0.048693  0.835747
6  5.0  1.0  0.342054  0.920379
7  6.0  1.0  0.370076  0.871850
8  7.0  1.0  0.079587  0.750099
9  8.0  1.0 -0.954504  1.162285

[10 rows x 4 columns] 
```  ### 更改名称

`Series.rename`和`NDFrame.rename_axis`现在可以接受标量或类似列表的参数来更改 Series 或轴的*名称*,以及它们以前的更改标签的行为。([GH 9494](https://github.com/pandas-dev/pandas/issues/9494), [GH 11965](https://github.com/pandas-dev/pandas/issues/11965))

```py
In [9]: s = pd.Series(np.random.randn(5))

In [10]: s.rename('newname')
Out[10]: 
0    1.150036
1    0.991946
2    0.953324
3   -2.021255
4   -0.334077
Name: newname, Length: 5, dtype: float64 
In [11]: df = pd.DataFrame(np.random.randn(5, 2))

In [12]: (df.rename_axis("indexname")
 ....:   .rename_axis("columns_name", axis="columns"))
 ....: 
Out[12]: 
columns_name         0         1
indexname 
0             0.002118  0.405453
1             0.289092  1.321158
2            -1.546906 -0.202646
3            -0.655969  0.193421
4             0.553439  1.318152

[5 rows x 2 columns] 

新功能现在在方法链中运行良好。以前,这些方法只接受将标签映射到新标签的函数或字典。对于函数或类似字典的值,这将继续像以前一样工作。 ### 范围索引

已将RangeIndex添加到Int64Index子类中,以支持常见用例的节省内存替代方法。这与 python range对象(在 python 2 中为xrange)有相似的实现,它只存储索引的开始、停止和步长值。它将与用户 API 透明地交互,必要时转换为Int64Index

现在这将成为NDFrame对象的默认构造索引,而不再是以前的Int64Index。(GH 939, GH 12070, GH 12071, GH 12109, GH 12888)

以前的行为:

In [3]: s = pd.Series(range(1000))

In [4]: s.index
Out[4]:
Int64Index([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
 ...
 990, 991, 992, 993, 994, 995, 996, 997, 998, 999], dtype='int64', length=1000)

In [6]: s.index.nbytes
Out[6]: 8000 

新的行为:

In [13]: s = pd.Series(range(1000))

In [14]: s.index
Out[14]: RangeIndex(start=0, stop=1000, step=1)

In [15]: s.index.nbytes
Out[15]: 128 
```  ### 更改为 str.extract

.str.extract 方法接受带有捕获组的正则表达式,在每个主题字符串中找到第一个匹配项,并返回捕获组的内容([GH 11386](https://github.com/pandas-dev/pandas/issues/11386))。

在 v0.18.0 中,添加了 `extract` 的 `expand` 参数。

+   `expand=False`:它根据主题和正则表达式模式的不同,返回一个 `Series`、`Index` 或 `DataFrame`(与 v0.18.0 之前的行为相同)。

+   `expand=True`:它始终返回一个 `DataFrame`,从用户的角度来看更一致且更少令人困惑。

目前默认为 `expand=None`,会产生 `FutureWarning`,并使用 `expand=False`。为避免此警告,请明确指定 `expand`。

```py
In [1]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=None)
FutureWarning: currently extract(expand=None) means expand=False (return Index/Series/DataFrame)
but in a future version of pandas this will be changed to expand=True (return DataFrame)

Out[1]:
0      1
1      2
2    NaN
dtype: object 

提取具有一个组的正则表达式,如果 expand=False,则返回一个 Series。

In [16]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=False)
Out[16]: 
0      1
1      2
2    NaN
Length: 3, dtype: object 

如果 expand=True,则返回一个只有一列的 DataFrame

In [17]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=True)
Out[17]: 
 0
0    1
1    2
2  NaN

[3 rows x 1 columns] 

使用具有正好一个捕获组的正则表达式调用 Index 时,如果 expand=False,则返回一个 Index

In [18]: s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"])

In [19]: s.index
Out[19]: Index(['A11', 'B22', 'C33'], dtype='object')

In [20]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=False)
Out[20]: Index(['A', 'B', 'C'], dtype='object', name='letter') 

如果 expand=True,则返回一个只有一列的 DataFrame

In [21]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=True)
Out[21]: 
 letter
0      A
1      B
2      C

[3 rows x 1 columns] 

使用具有多个捕获组的正则表达式调用 Index 时,如果 expand=False,则会引发 ValueError

>>> s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=False)
ValueError: only one regex group is supported with Index 

如果 expand=True,则返回一个 DataFrame

In [22]: s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=True)
Out[22]: 
 letter   1
0      A  11
1      B  22
2      C  33

[3 rows x 2 columns] 

总之,extract(expand=True)总是返回一个 DataFrame,其中每个主题字符串都有一行,每个捕获组都有一列。### str.extractall 的添加

添加了 .str.extractall 方法(GH 11386)。与 extract 不同,它返回所有匹配项。

In [23]: s = pd.Series(["a1a2", "b1", "c1"], ["A", "B", "C"])

In [24]: s
Out[24]: 
A    a1a2
B      b1
C      c1
Length: 3, dtype: object

In [25]: s.str.extract(r"(?P<letter>[ab])(?P<digit>\d)", expand=False)
Out[25]: 
 letter digit
A      a     1
B      b     1
C    NaN   NaN

[3 rows x 2 columns] 

extractall 方法返回所有匹配项。

In [26]: s.str.extractall(r"(?P<letter>[ab])(?P<digit>\d)")
Out[26]: 
 letter digit
 match 
A 0          a     1
 1          a     2
B 0          b     1

[3 rows x 2 columns] 
``` ### 对 str.cat 的更改

方法 `.str.cat()` 将 `Series` 的成员连接起来。以前,如果 `Series` 中存在 `NaN` 值,对其调用 `.str.cat()` 会返回 `NaN`,与 `Series.str.*` API 的其余部分不同。此行为已更正为默认忽略 `NaN` 值。([GH 11435](https://github.com/pandas-dev/pandas/issues/11435))。

添加了一个新的、更友好的 `ValueError`,以防止将 `sep` 错误地作为参数而不是关键字参数传递。([GH 11334](https://github.com/pandas-dev/pandas/issues/11334))。

```py
In [27]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ')
Out[27]: 'a b c'

In [28]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ', na_rep='?')
Out[28]: 'a b ? c' 
In [2]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(' ')
ValueError: Did you mean to supply a ``sep`` keyword? 
``` ### 日期时间舍入

`DatetimeIndex`、`Timestamp`、`TimedeltaIndex`、`Timedelta` 现在具有用于日期时间舍入、向下取整和向上取整的 `.round()`、`.floor()` 和 `.ceil()` 方法。([GH 4314](https://github.com/pandas-dev/pandas/issues/4314), [GH 11963](https://github.com/pandas-dev/pandas/issues/11963))

朴素日期时间

```py
In [29]: dr = pd.date_range('20130101 09:12:56.1234', periods=3)

In [30]: dr
Out[30]: 
DatetimeIndex(['2013-01-01 09:12:56.123400', '2013-01-02 09:12:56.123400',
 '2013-01-03 09:12:56.123400'],
 dtype='datetime64[ns]', freq='D')

In [31]: dr.round('s')
Out[31]: 
DatetimeIndex(['2013-01-01 09:12:56', '2013-01-02 09:12:56',
 '2013-01-03 09:12:56'],
 dtype='datetime64[ns]', freq=None)

# Timestamp scalar
In [32]: dr[0]
Out[32]: Timestamp('2013-01-01 09:12:56.123400')

In [33]: dr[0].round('10s')
Out[33]: Timestamp('2013-01-01 09:13:00') 

以本地时间为准的时区感知时间会被四舍五入、向下取整和向上取整。

In [34]: dr = dr.tz_localize('US/Eastern')

In [35]: dr
Out[35]: 
DatetimeIndex(['2013-01-01 09:12:56.123400-05:00',
 '2013-01-02 09:12:56.123400-05:00',
 '2013-01-03 09:12:56.123400-05:00'],
 dtype='datetime64[ns, US/Eastern]', freq=None)

In [36]: dr.round('s')
Out[36]: 
DatetimeIndex(['2013-01-01 09:12:56-05:00', '2013-01-02 09:12:56-05:00',
 '2013-01-03 09:12:56-05:00'],
 dtype='datetime64[ns, US/Eastern]', freq=None) 

时间增量

In [37]: t = pd.timedelta_range('1 days 2 hr 13 min 45 us', periods=3, freq='d')

In [38]: t
Out[38]: 
TimedeltaIndex(['1 days 02:13:00.000045', '2 days 02:13:00.000045',
 '3 days 02:13:00.000045'],
 dtype='timedelta64[ns]', freq='D')

In [39]: t.round('10min')
Out[39]: TimedeltaIndex(['1 days 02:10:00', '2 days 02:10:00', '3 days 02:10:00'], dtype='timedelta64[ns]', freq=None)

# Timedelta scalar
In [40]: t[0]
Out[40]: Timedelta('1 days 02:13:00.000045')

In [41]: t[0].round('2h')
Out[41]: Timedelta('1 days 02:00:00') 

此外,.round().floor().ceil() 将通过 Series.dt 访问器提供。

In [42]: s = pd.Series(dr)

In [43]: s
Out[43]: 
0   2013-01-01 09:12:56.123400-05:00
1   2013-01-02 09:12:56.123400-05:00
2   2013-01-03 09:12:56.123400-05:00
Length: 3, dtype: datetime64[ns, US/Eastern]

In [44]: s.dt.round('D')
Out[44]: 
0   2013-01-01 00:00:00-05:00
1   2013-01-02 00:00:00-05:00
2   2013-01-03 00:00:00-05:00
Length: 3, dtype: datetime64[ns, US/Eastern] 

FloatIndex 中整数的格式化

FloatIndex 中的整数,例如 1.,现在会以小数点和 0 数字的形式格式化,例如 1.0 (GH 11713) 此更改不仅影响控制台的显示,还影响 .to_csv.to_html 等 IO 方法的输出。

之前的行为:

In [2]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [3]: s
Out[3]:
0    1
1    2
2    3
dtype: int64

In [4]: s.index
Out[4]: Float64Index([0.0, 1.0, 2.0], dtype='float64')

In [5]: print(s.to_csv(path=None))
0,1
1,2
2,3 

新行为:

In [45]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [46]: s
Out[46]: 
0.0    1
1.0    2
2.0    3
Length: 3, dtype: int64

In [47]: s.index
Out[47]: Index([0.0, 1.0, 2.0], dtype='float64')

In [48]: print(s.to_csv(path_or_buf=None, header=False))
0.0,1
1.0,2
2.0,3 

更改 dtype 分配行为

当更新 DataFrame 的切片为相同 dtype 的新切片时,DataFrame 的 dtype 现在将保持不变。(GH 10503)

之前的行为:

In [5]: df = pd.DataFrame({'a': [0, 1, 1],
 'b': pd.Series([100, 200, 300], dtype='uint32')})

In [7]: df.dtypes
Out[7]:
a     int64
b    uint32
dtype: object

In [8]: ix = df['a'] == 1

In [9]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [11]: df.dtypes
Out[11]:
a    int64
b    int64
dtype: object 

新行为:

In [49]: df = pd.DataFrame({'a': [0, 1, 1],
 ....:                   'b': pd.Series([100, 200, 300], dtype='uint32')})
 ....: 

In [50]: df.dtypes
Out[50]: 
a     int64
b    uint32
Length: 2, dtype: object

In [51]: ix = df['a'] == 1

In [52]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [53]: df.dtypes
Out[53]: 
a     int64
b    uint32
Length: 2, dtype: object 

当 DataFrame 的整数切片部分更新为可能被降级为整数而不会丢失精度的新浮点数切片时,切片的 dtype 将设置为浮点数而不是整数。

之前的行为:

In [4]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
 columns=list('abc'),
 index=[[4,4,8], [8,10,12]])

In [5]: df
Out[5]:
 a  b  c
4 8   1  2  3
 10  4  5  6
8 12  7  8  9

In [7]: df.ix[4, 'c'] = np.array([0., 1.])

In [8]: df
Out[8]:
 a  b  c
4 8   1  2  0
 10  4  5  1
8 12  7  8  9 

新行为:

In [54]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
 ....:                  columns=list('abc'),
 ....:                  index=[[4,4,8], [8,10,12]])
 ....: 

In [55]: df
Out[55]: 
 a  b  c
4 8   1  2  3
 10  4  5  6
8 12  7  8  9

[3 rows x 3 columns]

In [56]: df.loc[4, 'c'] = np.array([0., 1.])

In [57]: df
Out[57]: 
 a  b  c
4 8   1  2  0
 10  4  5  1
8 12  7  8  9

[3 rows x 3 columns] 

to_xarray 方法

在 pandas 的未来版本中,我们将弃用 Panel 和其他 > 2 维对象。为了提供连续性,所有 NDFrame 对象都增加了 .to_xarray() 方法,以便转换为 xarray 对象,该对象具有类似于 pandas 的 > 2 维界面。(GH 11972)

请查看xarray 的完整文档

In [1]: p = Panel(np.arange(2*3*4).reshape(2,3,4))

In [2]: p.to_xarray()
Out[2]:
<xarray.DataArray (items: 2, major_axis: 3, minor_axis: 4)>
array([[[ 0,  1,  2,  3],
 [ 4,  5,  6,  7],
 [ 8,  9, 10, 11]],

 [[12, 13, 14, 15],
 [16, 17, 18, 19],
 [20, 21, 22, 23]]])
Coordinates:
 * items       (items) int64 0 1
 * major_axis  (major_axis) int64 0 1 2
 * minor_axis  (minor_axis) int64 0 1 2 3 

LaTeX 表示

DataFrame 已经增加了一个 ._repr_latex_() 方法,以便在 ipython/jupyter 笔记本中使用 nbconvert 转换为 LaTeX。(GH 11778)

请注意,必须通过设置选项 pd.display.latex.repr=True 来激活此功能(GH 12182

例如,如果您有一个 Jupyter 笔记本,计划使用 nbconvert 转换为 LaTeX,将语句 pd.display.latex.repr=True 放在第一个单元格中,以便将包含的 DataFrame 输出也存储为 LaTeX。

选项 display.latex.escapedisplay.latex.longtable 也已添加到配置中,并且会被 to_latex 方法自动使用。有关更多信息,请参阅可用选项文档。

pd.read_sas() 更改

read_sas 现在具有读取 SAS7BDAT 文件(包括压缩文件)的能力。文件可以完整读取,也可以增量读取。有关详细信息,请参见这里。(GH 4052) ### 其他增强

  • 处理 SAS xport 文件中截断的浮点数 (GH 11713)

  • 添加了在 Series.to_string 中隐藏索引的选项 (GH 11729)

  • read_excel 现在支持格式为 s3://bucketname/filename 的 s3 url。(GH 11447)

  • 在从 s3 读取时,添加对 AWS_S3_HOST 环境变量的支持 (GH 12198)

  • 简化版的 Panel.round() 现在已经实现了 (GH 11763)

  • 对于 Python 3.x,round(DataFrame)round(Series)round(Panel) 将起作用 (GH 11763)

  • sys.getsizeof(obj) 返回 pandas 对象的内存使用情况,包括它包含的值 (GH 11597)

  • Series 增加了一个 is_unique 属性 (GH 11946)

  • DataFrame.quantileSeries.quantile 现在接受 interpolation 关键词 (GH 10174).

  • 添加了 DataFrame.style.format 来更灵活地格式化单元格值 (GH 11692)

  • DataFrame.select_dtypes 现在允许 np.float16 类型代码 (GH 11990)

  • pivot_table() 现在接受大多数可迭代对象作为 values 参数 (GH 12017)

  • 添加了 Google BigQuery 服务账户认证支持,这使得在远程服务器上进行认证成为可能。 (GH 11881, GH 12572)。更多详情请参见 here

  • HDFStore 现在是可迭代的:for k in store 等效于 for k in store.keys() (GH 12221).

  • .dt 添加了缺失的方法/字段,用于 Period (GH 8848)

  • 整个代码库已经符合 PEP 规范化 (GH 12096) ### 窗口函数现在是方法

窗口函数已经重构为 Series/DataFrame 对象上的方法,而不是顶层函数,现在已经弃用。这使得这些窗口类型函数具有了与 .groupby 类似的 API。查看完整文档 here (GH 11603, GH 12373)

In [1]: np.random.seed(1234)

In [2]: df = pd.DataFrame({'A': range(10), 'B': np.random.randn(10)})

In [3]: df
Out[3]: 
 A         B
0  0  0.471435
1  1 -1.190976
2  2  1.432707
3  3 -0.312652
4  4 -0.720589
5  5  0.887163
6  6  0.859588
7  7 -0.636524
8  8  0.015696
9  9 -2.242685

[10 rows x 2 columns] 

先前的行为:

In [8]: pd.rolling_mean(df, window=3)
 FutureWarning: pd.rolling_mean is deprecated for DataFrame and will be removed in a future version, replace with
 DataFrame.rolling(window=3,center=False).mean()
Out[8]:
 A         B
0 NaN       NaN
1 NaN       NaN
2   1  0.237722
3   2 -0.023640
4   3  0.133155
5   4 -0.048693
6   5  0.342054
7   6  0.370076
8   7  0.079587
9   8 -0.954504 

新行为:

In [4]: r = df.rolling(window=3) 

这些显示了描述性的 repr

In [5]: r
Out[5]: Rolling [window=3,center=False,axis=0,method=single] 

具有可用方法和属性的选项卡完成。

In [9]: r.<TAB>  # noqa E225, E999
r.A           r.agg         r.apply       r.count       r.exclusions  r.max         r.median      r.name        r.skew        r.sum
r.B           r.aggregate   r.corr        r.cov         r.kurt        r.mean        r.min         r.quantile    r.std         r.var 

这些方法作用于 Rolling 对象本身

In [6]: r.mean()
Out[6]: 
 A         B
0  NaN       NaN
1  NaN       NaN
2  1.0  0.237722
3  2.0 -0.023640
4  3.0  0.133155
5  4.0 -0.048693
6  5.0  0.342054
7  6.0  0.370076
8  7.0  0.079587
9  8.0 -0.954504

[10 rows x 2 columns] 

它们提供了 getitem 访问器

In [7]: r['A'].mean()
Out[7]: 
0    NaN
1    NaN
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    6.0
8    7.0
9    8.0
Name: A, Length: 10, dtype: float64 

和多个聚合

In [8]: r.agg({'A': ['mean', 'std'],
 ...:       'B': ['mean', 'std']})
 ...: 
Out[8]: 
 A              B 
 mean  std      mean       std
0  NaN  NaN       NaN       NaN
1  NaN  NaN       NaN       NaN
2  1.0  1.0  0.237722  1.327364
3  2.0  1.0 -0.023640  1.335505
4  3.0  1.0  0.133155  1.143778
5  4.0  1.0 -0.048693  0.835747
6  5.0  1.0  0.342054  0.920379
7  6.0  1.0  0.370076  0.871850
8  7.0  1.0  0.079587  0.750099
9  8.0  1.0 -0.954504  1.162285

[10 rows x 4 columns] 

重命名更改

Series.renameNDFrame.rename_axis 现在可以接受标量或类似列表的参数来修改 Series 或轴的 名称,除了它们以前修改标签的行为。 (GH 9494, GH 11965)

In [9]: s = pd.Series(np.random.randn(5))

In [10]: s.rename('newname')
Out[10]: 
0    1.150036
1    0.991946
2    0.953324
3   -2.021255
4   -0.334077
Name: newname, Length: 5, dtype: float64 
In [11]: df = pd.DataFrame(np.random.randn(5, 2))

In [12]: (df.rename_axis("indexname")
 ....:   .rename_axis("columns_name", axis="columns"))
 ....: 
Out[12]: 
columns_name         0         1
indexname 
0             0.002118  0.405453
1             0.289092  1.321158
2            -1.546906 -0.202646
3            -0.655969  0.193421
4             0.553439  1.318152

[5 rows x 2 columns] 

新功能在方法链中运行良好。以前,这些方法只接受将标签映射到新标签的函数或字典。对于函数或类似字典的值,这仍然像以前一样工作。

范围索引

RangeIndex已添加到Int64Index子类中,以支持常见用例的节省内存的替代方案。这与 python 的range对象(在 python 2 中为xrange)具有类似的实现,因为它仅存储索引的起始、停止和步长值。如果需要,它将与用户 API 透明地交互,转换为Int64Index

现在,这将成为NDFrame对象的默认构建索引,而不是以前的Int64Index。(GH 939, GH 12070, GH 12071, GH 12109, GH 12888)

先前的行为:

In [3]: s = pd.Series(range(1000))

In [4]: s.index
Out[4]:
Int64Index([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
 ...
 990, 991, 992, 993, 994, 995, 996, 997, 998, 999], dtype='int64', length=1000)

In [6]: s.index.nbytes
Out[6]: 8000 

新行为:

In [13]: s = pd.Series(range(1000))

In [14]: s.index
Out[14]: RangeIndex(start=0, stop=1000, step=1)

In [15]: s.index.nbytes
Out[15]: 128 

str.extract的更改

.str.extract 方法使用具有捕获组的正则表达式,在每个主题字符串中找到第一个匹配项,并返回捕获组的内容(GH 11386)。

在 v0.18.0 中,添加了expand参数到extract

  • expand=False:根据主题和正则表达式模式,返回一个SeriesIndexDataFrame(与 0.18.0 之前的行为相同)。

  • expand=True:它始终返回一个DataFrame,这对用户来说更一致,更少令人困惑。

目前默认值为expand=None,会产生FutureWarning并使用expand=False。为避免此警告,请明确指定expand

In [1]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=None)
FutureWarning: currently extract(expand=None) means expand=False (return Index/Series/DataFrame)
but in a future version of pandas this will be changed to expand=True (return DataFrame)

Out[1]:
0      1
1      2
2    NaN
dtype: object 

当使用expand=False提取具有一个组的正则表达式时,返回一个Series

In [16]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=False)
Out[16]: 
0      1
1      2
2    NaN
Length: 3, dtype: object 

如果expand=True,则返回一个列的DataFrame

In [17]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'ab', expand=True)
Out[17]: 
 0
0    1
1    2
2  NaN

[3 rows x 1 columns] 

对具有正好一个捕获组的正则表达式的Index调用,如果expand=False,则返回一个Index

In [18]: s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"])

In [19]: s.index
Out[19]: Index(['A11', 'B22', 'C33'], dtype='object')

In [20]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=False)
Out[20]: Index(['A', 'B', 'C'], dtype='object', name='letter') 

如果expand=True,则返回一个列的DataFrame

In [21]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=True)
Out[21]: 
 letter
0      A
1      B
2      C

[3 rows x 1 columns] 

对具有多个捕获组的正则表达式的Index调用,如果expand=False,则引发ValueError

>>> s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=False)
ValueError: only one regex group is supported with Index 

如果expand=True,则返回一个DataFrame

In [22]: s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=True)
Out[22]: 
 letter   1
0      A  11
1      B  22
2      C  33

[3 rows x 2 columns] 

总之,extract(expand=True)始终返回一个DataFrame,每个主题字符串都有一行,每个捕获组都有一列。

添加str.extractall

添加了.str.extractall 方法(GH 11386)。与extract不同,它仅返回第一个匹配项。

In [23]: s = pd.Series(["a1a2", "b1", "c1"], ["A", "B", "C"])

In [24]: s
Out[24]: 
A    a1a2
B      b1
C      c1
Length: 3, dtype: object

In [25]: s.str.extract(r"(?P<letter>[ab])(?P<digit>\d)", expand=False)
Out[25]: 
 letter digit
A      a     1
B      b     1
C    NaN   NaN

[3 rows x 2 columns] 

extractall方法返回所有匹配项。

In [26]: s.str.extractall(r"(?P<letter>[ab])(?P<digit>\d)")
Out[26]: 
 letter digit
 match 
A 0          a     1
 1          a     2
B 0          b     1

[3 rows x 2 columns] 

str.cat的更改

方法.str.cat()连接Series的成员。以前,如果Series中存在NaN值,则调用.str.cat()会返回NaN,与Series.str.*API 的其余部分不同。这种行为已经被修改为默认忽略NaN值。(GH 11435)。

添加了一个新的友好ValueError,以防止错误地将sep作为参数而不是关键字参数。(GH 11334)。

In [27]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ')
Out[27]: 'a b c'

In [28]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ', na_rep='?')
Out[28]: 'a b ? c' 
In [2]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(' ')
ValueError: Did you mean to supply a ``sep`` keyword? 

日期时间四舍五入

DatetimeIndexTimestampTimedeltaIndexTimedelta已经获得了.round().floor().ceil()方法,用于日期时间四舍五入、向下取整和向上取整。(GH 4314GH 11963)

朴素日期时间

In [29]: dr = pd.date_range('20130101 09:12:56.1234', periods=3)

In [30]: dr
Out[30]: 
DatetimeIndex(['2013-01-01 09:12:56.123400', '2013-01-02 09:12:56.123400',
 '2013-01-03 09:12:56.123400'],
 dtype='datetime64[ns]', freq='D')

In [31]: dr.round('s')
Out[31]: 
DatetimeIndex(['2013-01-01 09:12:56', '2013-01-02 09:12:56',
 '2013-01-03 09:12:56'],
 dtype='datetime64[ns]', freq=None)

# Timestamp scalar
In [32]: dr[0]
Out[32]: Timestamp('2013-01-01 09:12:56.123400')

In [33]: dr[0].round('10s')
Out[33]: Timestamp('2013-01-01 09:13:00') 

时区感知在本地时间中四舍五入、向下取整和向上取整

In [34]: dr = dr.tz_localize('US/Eastern')

In [35]: dr
Out[35]: 
DatetimeIndex(['2013-01-01 09:12:56.123400-05:00',
 '2013-01-02 09:12:56.123400-05:00',
 '2013-01-03 09:12:56.123400-05:00'],
 dtype='datetime64[ns, US/Eastern]', freq=None)

In [36]: dr.round('s')
Out[36]: 
DatetimeIndex(['2013-01-01 09:12:56-05:00', '2013-01-02 09:12:56-05:00',
 '2013-01-03 09:12:56-05:00'],
 dtype='datetime64[ns, US/Eastern]', freq=None) 

时间增量

In [37]: t = pd.timedelta_range('1 days 2 hr 13 min 45 us', periods=3, freq='d')

In [38]: t
Out[38]: 
TimedeltaIndex(['1 days 02:13:00.000045', '2 days 02:13:00.000045',
 '3 days 02:13:00.000045'],
 dtype='timedelta64[ns]', freq='D')

In [39]: t.round('10min')
Out[39]: TimedeltaIndex(['1 days 02:10:00', '2 days 02:10:00', '3 days 02:10:00'], dtype='timedelta64[ns]', freq=None)

# Timedelta scalar
In [40]: t[0]
Out[40]: Timedelta('1 days 02:13:00.000045')

In [41]: t[0].round('2h')
Out[41]: Timedelta('1 days 02:00:00') 

此外,.round().floor().ceil()将通过Series.dt访问器可用。

In [42]: s = pd.Series(dr)

In [43]: s
Out[43]: 
0   2013-01-01 09:12:56.123400-05:00
1   2013-01-02 09:12:56.123400-05:00
2   2013-01-03 09:12:56.123400-05:00
Length: 3, dtype: datetime64[ns, US/Eastern]

In [44]: s.dt.round('D')
Out[44]: 
0   2013-01-01 00:00:00-05:00
1   2013-01-02 00:00:00-05:00
2   2013-01-03 00:00:00-05:00
Length: 3, dtype: datetime64[ns, US/Eastern] 

FloatIndex 中整数的格式化

FloatIndex中的整数,例如 1.,现在以带有小数点和0数字的形式进行格式化,例如1.0 (GH 11713) 这种变化不仅影响到控制台的显示,还影响到像.to_csv.to_html这样的 IO 方法的输出。

以前的行为:

In [2]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [3]: s
Out[3]:
0    1
1    2
2    3
dtype: int64

In [4]: s.index
Out[4]: Float64Index([0.0, 1.0, 2.0], dtype='float64')

In [5]: print(s.to_csv(path=None))
0,1
1,2
2,3 

新行为:

In [45]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [46]: s
Out[46]: 
0.0    1
1.0    2
2.0    3
Length: 3, dtype: int64

In [47]: s.index
Out[47]: Index([0.0, 1.0, 2.0], dtype='float64')

In [48]: print(s.to_csv(path_or_buf=None, header=False))
0.0,1
1.0,2
2.0,3 

更改了 dtype 分配行为

当 DataFrame 的切片用相同 dtype 的新切片更新时,DataFrame 的 dtype 现在将保持不变。(GH 10503)

以前的行为:

In [5]: df = pd.DataFrame({'a': [0, 1, 1],
 'b': pd.Series([100, 200, 300], dtype='uint32')})

In [7]: df.dtypes
Out[7]:
a     int64
b    uint32
dtype: object

In [8]: ix = df['a'] == 1

In [9]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [11]: df.dtypes
Out[11]:
a    int64
b    int64
dtype: object 

新行为:

In [49]: df = pd.DataFrame({'a': [0, 1, 1],
 ....:                   'b': pd.Series([100, 200, 300], dtype='uint32')})
 ....: 

In [50]: df.dtypes
Out[50]: 
a     int64
b    uint32
Length: 2, dtype: object

In [51]: ix = df['a'] == 1

In [52]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [53]: df.dtypes
Out[53]: 
a     int64
b    uint32
Length: 2, dtype: object 

当 DataFrame 的整数切片部分更新为可能被降级为整数而不会失去精度的浮点数切片时,切片的 dtype 将设置为浮点数而不是整数。

以前的行为:

In [4]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
 columns=list('abc'),
 index=[[4,4,8], [8,10,12]])

In [5]: df
Out[5]:
 a  b  c
4 8   1  2  3
 10  4  5  6
8 12  7  8  9

In [7]: df.ix[4, 'c'] = np.array([0., 1.])

In [8]: df
Out[8]:
 a  b  c
4 8   1  2  0
 10  4  5  1
8 12  7  8  9 

新行为:

In [54]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
 ....:                  columns=list('abc'),
 ....:                  index=[[4,4,8], [8,10,12]])
 ....: 

In [55]: df
Out[55]: 
 a  b  c
4 8   1  2  3
 10  4  5  6
8 12  7  8  9

[3 rows x 3 columns]

In [56]: df.loc[4, 'c'] = np.array([0., 1.])

In [57]: df
Out[57]: 
 a  b  c
4 8   1  2  0
 10  4  5  1
8 12  7  8  9

[3 rows x 3 columns] 

方法 to_xarray

在未来的 pandas 版本中,我们将废弃Panel和其他> 2 维对象。为了提供连续性,所有NDFrame对象已经获得了.to_xarray()方法,以便转换为xarray对象,该对象具有类似于 pandas 的> 2 维接口。(GH 11972)

查看xarray 完整文档

In [1]: p = Panel(np.arange(2*3*4).reshape(2,3,4))

In [2]: p.to_xarray()
Out[2]:
<xarray.DataArray (items: 2, major_axis: 3, minor_axis: 4)>
array([[[ 0,  1,  2,  3],
 [ 4,  5,  6,  7],
 [ 8,  9, 10, 11]],

 [[12, 13, 14, 15],
 [16, 17, 18, 19],
 [20, 21, 22, 23]]])
Coordinates:
 * items       (items) int64 0 1
 * major_axis  (major_axis) int64 0 1 2
 * minor_axis  (minor_axis) int64 0 1 2 3 

LaTeX 表示

DataFrame已经获得了一个._repr_latex_()方法,以便在 ipython/jupyter 笔记本中使用 nbconvert 转换为 latex。(GH 11778)

请注意,这必须通过设置选项pd.display.latex.repr=True来激活。(GH 12182)

例如,如果您有一个 jupyter 笔记本,计划使用 nbconvert 转换为 latex,请在第一个单元格中放置语句pd.display.latex.repr=True,以便包含的 DataFrame 输出也存储为 latex。

选项 display.latex.escapedisplay.latex.longtable 也已添加到配置中,并且会被 to_latex 方法自动使用。有关更多信息,请参阅可用选项文档。

pd.read_sas() 变更

read_sas 现在具有读取 SAS7BDAT 文件的能力,包括压缩文件。文件可以被整体或增量地读取。有关完整详情,请参阅这里。(GH 4052)

其他增强

  • 处理 SAS xport 文件中的截断浮点数 (GH 11713)

  • 添加了在 Series.to_string 中隐藏索引的选项 (GH 11729)

  • read_excel 现在支持形如 s3://bucketname/filename 的 s3 url (GH 11447)

  • 在从 s3 读取时添加了对 AWS_S3_HOST 环境变量的支持 (GH 12198)

  • 现在实现了 Panel.round() 的简化版本 (GH 11763)

  • 对于 Python 3.x,round(DataFrame)round(Series)round(Panel) 将起作用 (GH 11763)

  • sys.getsizeof(obj) 返回 pandas 对象的内存使用情况,包括其包含的值 (GH 11597)

  • Series 增加了 is_unique 属性 (GH 11946)

  • DataFrame.quantileSeries.quantile 现在接受 interpolation 关键字 (GH 10174).

  • 添加了 DataFrame.style.format 以更灵活地格式化单元格值 (GH 11692)

  • DataFrame.select_dtypes 现在允许 np.float16 类型码 (GH 11990)

  • pivot_table() 现在接受大多数可迭代对象作为 values 参数 (GH 12017)

  • 添加了对 Google BigQuery 服务账户身份验证的支持,这使得可以在远程服务器上进行身份验证。(GH 11881, GH 12572)。更多详细信息请参阅这里

  • HDFStore 现在是可迭代的:for k in store 等同于 for k in store.keys() (GH 12221).

  • 将缺失的方法/字段添加到 Period.dt 中 (GH 8848)

  • 整个代码库已经符合 PEP 标准化 (GH 12096)

不兼容的后向 API 更改

  • .to_string(index=False) 方法的输出中删除了前导空格 (GH 11833)

  • Series.round() 方法中的 out 参数已被移除。 (GH 11763)

  • DataFrame.round() 在返回中不再更改非数字列,而是保持不变。 (GH 11885)

  • DataFrame.head(0)DataFrame.tail(0) 返回空框架,而不是 self。 (GH 11937)

  • Series.head(0)Series.tail(0) 返回空系列,而不是 self。 (GH 11937)

  • to_msgpackread_msgpack 的编码现在默认为 'utf-8'。 (GH 12170)

  • 文本文件解析函数的关键字参数顺序 (.read_csv(), .read_table(), .read_fwf()) 已更改为分组相关参数。 (GH 11555)

  • NaTType.isoformat 现在返回字符串 'NaT',以允许结果传递给 Timestamp 的构造函数。 (GH 12300)

NaT 和 Timedelta 操作

NaTTimedelta 有了更多的算术操作,适用于 Series 的算术操作也进行了扩展。对于 datetime64[ns]timedelta64[ns] 定义的操作现在也适用于 NaT (GH 11564).

现在 NaT 支持与整数和浮点数的算术运算。

In [58]: pd.NaT * 1
Out[58]: NaT

In [59]: pd.NaT * 1.5
Out[59]: NaT

In [60]: pd.NaT / 2
Out[60]: NaT

In [61]: pd.NaT * np.nan
Out[61]: NaT 

NaTdatetime64[ns]timedelta64[ns] 定义了更多的算术操作。

In [62]: pd.NaT / pd.NaT
Out[62]: nan

In [63]: pd.Timedelta('1s') / pd.NaT
Out[63]: nan 

NaT 可能代表 datetime64[ns] 空值或 timedelta64[ns] 空值。鉴于模糊性,它被视为 timedelta64[ns],这允许更多的操作成功。

In [64]: pd.NaT + pd.NaT
Out[64]: NaT

# same as
In [65]: pd.Timedelta('1s') + pd.Timedelta('1s')
Out[65]: Timedelta('0 days 00:00:02') 

In [3]: pd.Timestamp('19900315') + pd.Timestamp('19900315')
TypeError: unsupported operand type(s) for +: 'Timestamp' and 'Timestamp' 

但是,当包装在 dtypedatetime64[ns]timedelta64[ns]Series 中时,将尊重 dtype 信息。

In [1]: pd.Series([pd.NaT], dtype='<M8[ns]') + pd.Series([pd.NaT], dtype='<M8[ns]')
TypeError: can only operate on a datetimes for subtraction,
 but the operator [__add__] was passed 
In [66]: pd.Series([pd.NaT], dtype='<m8[ns]') + pd.Series([pd.NaT], dtype='<m8[ns]')
Out[66]: 
0   NaT
Length: 1, dtype: timedelta64[ns] 

Timedelta 可以被 floats 除以。

In [67]: pd.Timedelta('1s') / 2.0
Out[67]: Timedelta('0 days 00:00:00.500000') 

Series 中通过 Timedelta 减去 Timestamp 的操作有效 (GH 11925)

In [68]: ser = pd.Series(pd.timedelta_range('1 day', periods=3))

In [69]: ser
Out[69]: 
0   1 days
1   2 days
2   3 days
Length: 3, dtype: timedelta64[ns]

In [70]: pd.Timestamp('2012-01-01') - ser
Out[70]: 
0   2011-12-31
1   2011-12-30
2   2011-12-29
Length: 3, dtype: datetime64[ns] 

NaT.isoformat() 现在返回 'NaT'。这个变化允许 pd.Timestamp 从其 isoformat 重新创建任何时间戳对象 (GH 12300).

msgpack 的更改

在 0.17.0 和 0.18.0 之间对 msgpack 写入格式进行了向前不兼容的更改;旧版本的 pandas 无法读取由新版本打包的文件 (GH 12129, GH 10527)

在 0.17.0 中引入的 to_msgpackread_msgpack 中的错误在 0.18.0 中已修复,导致 Python 2 中打包的文件无法被 Python 3 读取 (GH 12142). 以下表格描述了 msgpack 的向后兼容性和向前兼容性。

警告

打包版本 可以解包版本
0.17 版本之前 / Python 2 任何
0.17 版本之前 / Python 3 任何
0.17 版本之前 / Python 2
  • ==0.17 / Python 2

  • =0.18 / 任何 Python

|

0.17 版本之前 / Python 3 >=0.18 / 任何 Python
0.18 >= 0.18

0.18.0 对于由旧版本打包的文件是向后兼容的,但对于在 Python 2 中打包的 0.17 版本的文件,只能在 Python 2 中解包。

.rank的签名更改

Series.rankDataFrame.rank现在具有相同的签名 (GH 11759)

以前的签名

In [3]: pd.Series([0,1]).rank(method='average', na_option='keep',
 ascending=True, pct=False)
Out[3]:
0    1
1    2
dtype: float64

In [4]: pd.DataFrame([0,1]).rank(axis=0, numeric_only=None,
 method='average', na_option='keep',
 ascending=True, pct=False)
Out[4]:
 0
0  1
1  2 

新的签名

In [71]: pd.Series([0,1]).rank(axis=0, method='average', numeric_only=False,
 ....:                      na_option='keep', ascending=True, pct=False)
 ....: 
Out[71]: 
0    1.0
1    2.0
Length: 2, dtype: float64

In [72]: pd.DataFrame([0,1]).rank(axis=0, method='average', numeric_only=False,
 ....:                         na_option='keep', ascending=True, pct=False)
 ....: 
Out[72]: 
 0
0  1.0
1  2.0

[2 rows x 1 columns] 

当 n=0 时,QuarterBegin中的错误

在之前的版本中,如果日期在n参数为 0 时,QuarterBegin偏移量的行为是不一致的。 (GH 11406)

对于n=0的锚定偏移量的一般语义是在它是锚点时不移动日期(例如,季度开始日期),否则向前滚动到下一个锚点。

In [73]: d = pd.Timestamp('2014-02-01')

In [74]: d
Out[74]: Timestamp('2014-02-01 00:00:00')

In [75]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[75]: Timestamp('2014-02-01 00:00:00')

In [76]: d + pd.offsets.QuarterBegin(n=0, startingMonth=1)
Out[76]: Timestamp('2014-04-01 00:00:00') 

对于之前版本中的QuarterBegin偏移量,如果日期与季度开始日期在同一个月,则日期将被向滚动。

In [3]: d = pd.Timestamp('2014-02-15')

In [4]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[4]: Timestamp('2014-02-01 00:00:00') 

这种行为已在版本 0.18.0 中得到了纠正,与其他锚定偏移量(如MonthBeginYearBegin)保持一致。

In [77]: d = pd.Timestamp('2014-02-15')

In [78]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[78]: Timestamp('2014-05-01 00:00:00') 

重新采样 API

就像上面的窗口函数 API 更改一样,.resample(...)正在改变以具有更像groupby的 API。 (GH 11732, GH 12702, GH 12202, GH 12332, GH 12334, GH 12348, GH 12448)。

In [79]: np.random.seed(1234)

In [80]: df = pd.DataFrame(np.random.rand(10,4),
 ....:                  columns=list('ABCD'),
 ....:                  index=pd.date_range('2010-01-01 09:00:00',
 ....:                                      periods=10, freq='s'))
 ....: 

In [81]: df
Out[81]: 
 A         B         C         D
2010-01-01 09:00:00  0.191519  0.622109  0.437728  0.785359
2010-01-01 09:00:01  0.779976  0.272593  0.276464  0.801872
2010-01-01 09:00:02  0.958139  0.875933  0.357817  0.500995
2010-01-01 09:00:03  0.683463  0.712702  0.370251  0.561196
2010-01-01 09:00:04  0.503083  0.013768  0.772827  0.882641
2010-01-01 09:00:05  0.364886  0.615396  0.075381  0.368824
2010-01-01 09:00:06  0.933140  0.651378  0.397203  0.788730
2010-01-01 09:00:07  0.316836  0.568099  0.869127  0.436173
2010-01-01 09:00:08  0.802148  0.143767  0.704261  0.704581
2010-01-01 09:00:09  0.218792  0.924868  0.442141  0.909316

[10 rows x 4 columns] 

以前的 API

你会编写一个重新采样操作,它会立即执行。如果未提供how参数,则默认为how='mean'

In [6]: df.resample('2s')
Out[6]:
 A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949 

你也可以直接指定一个how

In [7]: df.resample('2s', how='sum')
Out[7]:
 A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897 

新 API

现在,你可以像.groupby(...)一样将.resample(..)写成一个两阶段的操作,产生一个Resampler

In [82]: r = df.resample('2s')

In [83]: r
Out[83]: <pandas.core.resample.DatetimeIndexResampler object at 0x7ff230e71c30> 

下采样

你可以使用这个对象来执行操作。这些是下采样操作(从更高的频率到更低的频率)。

In [84]: r.mean()
Out[84]: 
 A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949

[5 rows x 4 columns] 
In [85]: r.sum()
Out[85]: 
 A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897

[5 rows x 4 columns] 

此外,resample现在支持getitem操作以对特定列执行重新采样。

In [86]: r[['A','C']].mean()
Out[86]: 
 A         C
2010-01-01 09:00:00  0.485748  0.357096
2010-01-01 09:00:02  0.820801  0.364034
2010-01-01 09:00:04  0.433985  0.424104
2010-01-01 09:00:06  0.624988  0.633165
2010-01-01 09:00:08  0.510470  0.573201

[5 rows x 2 columns] 

.aggregate类型的操作。

In [87]: r.agg({'A' : 'mean', 'B' : 'sum'})
Out[87]: 
 A         B
2010-01-01 09:00:00  0.485748  0.894701
2010-01-01 09:00:02  0.820801  1.588635
2010-01-01 09:00:04  0.433985  0.629165
2010-01-01 09:00:06  0.624988  1.219477
2010-01-01 09:00:08  0.510470  1.068634

[5 rows x 2 columns] 

当然,这些访问器也可以结合使用

In [88]: r[['A','B']].agg(['mean','sum'])
Out[88]: 
 A                   B 
 mean       sum      mean       sum
2010-01-01 09:00:00  0.485748  0.971495  0.447351  0.894701
2010-01-01 09:00:02  0.820801  1.641602  0.794317  1.588635
2010-01-01 09:00:04  0.433985  0.867969  0.314582  0.629165
2010-01-01 09:00:06  0.624988  1.249976  0.609738  1.219477
2010-01-01 09:00:08  0.510470  1.020940  0.534317  1.068634

[5 rows x 4 columns] 

上采样

上采样操作将你从较低的频率带到较高的频率。现在,这些是通过带有backfill()ffill()fillna()asfreq()方法的Resampler对象执行的。

In [89]: s = pd.Series(np.arange(5, dtype='int64'),
 index=pd.date_range('2010-01-01', periods=5, freq='Q'))

In [90]: s
Out[90]:
2010-03-31    0
2010-06-30    1
2010-09-30    2
2010-12-31    3
2011-03-31    4
Freq: Q-DEC, Length: 5, dtype: int64 

以前

In [6]: s.resample('M', fill_method='ffill')
Out[6]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, dtype: int64 

新 API

In [91]: s.resample('M').ffill()
Out[91]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, Length: 13, dtype: int64 

注意

在新 API 中,你可以进行下采样或上采样。之前的实现允许你传递一个聚合函数(如mean),即使你是上采样,这会带来一些混淆。

以前的 API 将会继续工作,但会有弃用警告

警告

这个新的 resample API 包括一些内部更改,以适应 0.18.0 之前的 API,在大多数情况下会返回一个延迟对象的弃用警告。我们可以拦截操作并执行 (pre 0.18.0) API 所做的操作(带有警告)。以下是一个典型的用例:

In [4]: r = df.resample('2s')

In [6]: r*10
pandas/tseries/resample.py:80: FutureWarning: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...)

Out[6]:
 A         B         C         D
2010-01-01 09:00:00  4.857476  4.473507  3.570960  7.936154
2010-01-01 09:00:02  8.208011  7.943173  3.640340  5.310957
2010-01-01 09:00:04  4.339846  3.145823  4.241039  6.257326
2010-01-01 09:00:06  6.249881  6.097384  6.331650  6.124518
2010-01-01 09:00:08  5.104699  5.343172  5.732009  8.069486 

然而,直接在 Resampler 上进行获取和赋值操作将引发 ValueError

In [7]: r.iloc[0] = 5
ValueError: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...) 

在使用原始代码时,存在一种情况,新 API 无法执行所有操作。这段代码意在对每 2 秒重新采样,取 mean 然后取这些结果的 min

In [4]: df.resample('2s').min()
Out[4]:
A    0.433985
B    0.314582
C    0.357096
D    0.531096
dtype: float64 

新 API 将:

In [89]: df.resample('2s').min()
Out[89]: 
 A         B         C         D
2010-01-01 09:00:00  0.191519  0.272593  0.276464  0.785359
2010-01-01 09:00:02  0.683463  0.712702  0.357817  0.500995
2010-01-01 09:00:04  0.364886  0.013768  0.075381  0.368824
2010-01-01 09:00:06  0.316836  0.568099  0.397203  0.436173
2010-01-01 09:00:08  0.218792  0.143767  0.442141  0.704581

[5 rows x 4 columns] 

好消息是新 API 和旧 API 之间的返回维度将不同,因此这应该会引发异常。

为了复制原始操作

In [90]: df.resample('2s').mean().min()
Out[90]: 
A    0.433985
B    0.314582
C    0.357096
D    0.531096
Length: 4, dtype: float64 

eval 的更改

在之前的版本中,在 eval 表达式中对新列进行赋值会导致对 DataFrame 的原地更改。(GH 9297, GH 8664, GH 10486)

In [91]: df = pd.DataFrame({'a': np.linspace(0, 10, 5), 'b': range(5)})

In [92]: df
Out[92]: 
 a  b
0   0.0  0
1   2.5  1
2   5.0  2
3   7.5  3
4  10.0  4

[5 rows x 2 columns] 
In [12]: df.eval('c = a + b')
FutureWarning: eval expressions containing an assignment currentlydefault to operating inplace.
This will change in a future version of pandas, use inplace=True to avoid this warning.

In [13]: df
Out[13]:
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0 

在版本 0.18.0 中,添加了一个新的 inplace 关键字,用于选择赋值是原地进行还是返回一个副本。

In [93]: df
Out[93]: 
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [94]: df.eval('d = c - b', inplace=False)
Out[94]: 
 a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns]

In [95]: df
Out[95]: 
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [96]: df.eval('d = c - b', inplace=True)

In [97]: df
Out[97]: 
 a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns] 

警告

为了向后兼容,如果未指定,inplace 默认为 True。这将在 pandas 的将来版本中更改。如果您的代码依赖于原地赋值,您应该更新为显式设置 inplace=True

inplace 关键字参数也被添加到 query 方法中。

In [98]: df.query('a > 5')
Out[98]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [99]: df.query('a > 5', inplace=True)

In [100]: df
Out[100]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns] 

警告

请注意,在 queryinplace 的默认值为 False,这与之前的版本保持一致。

eval 也已更新,允许多行表达式进行多个赋值。这些表达式将按顺序逐个进行评估。多行表达式仅对赋值有效。

In [101]: df
Out[101]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [102]: df.eval("""
 .....: e = d + a
 .....: f = e - 22
 .....: g = f / 2.0""", inplace=True)
 .....: 

In [103]: df
Out[103]: 
 a  b     c     d     e    f    g
3   7.5  3  10.5   7.5  15.0 -7.0 -3.5
4  10.0  4  14.0  10.0  20.0 -2.0 -1.0

[2 rows x 7 columns] 

其他 API 更改

  • DataFrame.between_timeSeries.between_time 现在只解析一组固定的时间字符串。不再支持日期字符串的解析,并引发 ValueError。(GH 11818)

    In [107]: s = pd.Series(range(10), pd.date_range('2015-01-01', freq='H', periods=10))
    
    In [108]: s.between_time("7:00am", "9:00am")
    Out[108]:
    2015-01-01 07:00:00    7
    2015-01-01 08:00:00    8
    2015-01-01 09:00:00    9
    Freq: H, Length: 3, dtype: int64 
    

    现在会引发异常。

    In [2]: s.between_time('20150101 07:00:00','20150101 09:00:00')
    ValueError: Cannot convert arg ['20150101 07:00:00'] to a time. 
    
  • .memory_usage() 现在包括索引中的值,.info() 中的 memory_usage 也是如此 (GH 11597)

  • DataFrame.to_latex() 现在支持在 Python 2 中使用非 ASCII 编码(例如 utf-8)的参数 encoding([GH 7061](https://github.com/pandas-dev/pandas/issues/7061))

  • pandas.merge()DataFrame.merge() 在尝试与不是 DataFrame 或其子类的对象合并时将显示特定错误消息 (GH 12081)

  • DataFrame.unstackSeries.unstack 现在接受 fill_value 关键字,以允许在展开结果中出现缺失值时直接替换缺失值。另一个好处是,指定 fill_value 将保留原始堆叠数据的数据类型。 (GH 9746)

  • 作为窗口函数和重新采样的新 API 的一部分,聚合函数已经得到澄清,在无效的聚合上提供更具信息性的错误消息。 (GH 9052). 在 groupby 中提供了一整套示例。

  • NDFrame 对象的统计函数(如 sum(), mean(), min())现在会在传递非兼容的参数给 **kwargs 时引发错误 (GH 12301)

  • .to_latex.to_html 现在增加了一个 decimal 参数,类似于 .to_csv;默认值为 '.' (GH 12031)

  • 在使用空数据但具有索引构建 DataFrame 时提供更有帮助的错误消息 (GH 8020)

  • .describe() 现在将正确处理布尔类型作为分类变量 (GH 6625)

  • 在使用用户定义输入时,无效的.transform 现在会提供更有帮助的错误消息 (GH 10165)

  • 指数加权函数现在允许直接指定 alpha (GH 10789),并且如果参数违反 0 < alpha <= 1,将引发 ValueError (GH 12492) ### 弃用功能

  • 函数 pd.rolling_*, pd.expanding_*, 和 pd.ewm* 已被弃用,并由相应的方法调用替代。请注意,新建议的语法包括所有参数(即使是默认值) (GH 11603)

    In [1]: s = pd.Series(range(3))
    
    In [2]: pd.rolling_mean(s,window=2,min_periods=1)
     FutureWarning: pd.rolling_mean is deprecated for Series and
     will be removed in a future version, replace with
     Series.rolling(min_periods=1,window=2,center=False).mean()
    Out[2]:
     0    0.0
     1    0.5
     2    1.5
     dtype: float64
    
    In [3]: pd.rolling_cov(s, s, window=2)
     FutureWarning: pd.rolling_cov is deprecated for Series and
     will be removed in a future version, replace with
     Series.rolling(window=2).cov(other=<Series>)
    Out[3]:
     0    NaN
     1    0.5
     2    0.5
     dtype: float64 
    
  • .rolling, .expanding.ewm(新)函数的 freqhow 参数已被弃用,并将在将来的版本中移除。您可以在创建窗口函数之前简单地对输入进行重新采样。 (GH 11603).

    例如,不再使用 s.rolling(window=5,freq='D').max() 来获取滚动 5 天窗口上的最大值,可以使用 s.resample('D').mean().rolling(window=5).max(),首先将数据重新采样为每日数据,然后提供一个滚动 5 天窗口。

  • pd.tseries.frequencies.get_offset_name 函数已被弃用。使用偏移量的.freqstr属性作为替代方案 (GH 11192)

  • pandas.stats.fama_macbeth 例程已被弃用,并将在将来的版本中移除 (GH 6077)

  • pandas.stats.olspandas.stats.plmpandas.stats.var 程序已被弃用,并将在将来的版本中移除(GH 6077

  • HDFStore.select 中,如果 where 子句不是类似字符串的形式,则显示FutureWarning,而不是DeprecationWarning,表示长时间弃用的语法(GH 12027

  • pandas.options.display.mpl_style 配置已被弃用,并将在 pandas 的将来版本中移除。这个功能最好由 matplotlib 的样式表来处理(GH 11783)。### 移除弃用的浮点索引器

GH 4892 中,对非Float64Index上的浮点数进行索引已被弃用(在版本 0.14.0 中)。在 0.18.0 中,这个弃用警告已被移除,现在将引发 TypeErrorGH 12165GH 12333

In [104]: s = pd.Series([1, 2, 3], index=[4, 5, 6])

In [105]: s
Out[105]: 
4    1
5    2
6    3
Length: 3, dtype: int64

In [106]: s2 = pd.Series([1, 2, 3], index=list('abc'))

In [107]: s2
Out[107]: 
a    1
b    2
c    3
Length: 3, dtype: int64 

先前的行为:

# this is label indexing
In [2]: s[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[2]: 2

# this is positional indexing
In [3]: s.iloc[1.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[3]: 2

# this is label indexing
In [4]: s.loc[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[4]: 2

# .ix would coerce 1.0 to the positional 1, and index
In [5]: s2.ix[1.0] = 10
FutureWarning: scalar indexers for index type Index should be integers and not floating point

In [6]: s2
Out[6]:
a     1
b    10
c     3
dtype: int64 

新行为:

对于 iloc,通过浮点标量进行获取和设置将始终引发异常。

In [3]: s.iloc[2.0]
TypeError: cannot do label indexing on <class 'pandas.indexes.numeric.Int64Index'> with these indexers [2.0] of <type 'float'> 

其他索引器将在获取和设置时强制转换为类似整数的值。对于 .loc.ix[]FutureWarning 已被移除。

In [108]: s[5.0]
Out[108]: 2

In [109]: s.loc[5.0]
Out[109]: 2 

和设置

In [110]: s_copy = s.copy()

In [111]: s_copy[5.0] = 10

In [112]: s_copy
Out[112]: 
4     1
5    10
6     3
Length: 3, dtype: int64

In [113]: s_copy = s.copy()

In [114]: s_copy.loc[5.0] = 10

In [115]: s_copy
Out[115]: 
4     1
5    10
6     3
Length: 3, dtype: int64 

使用 .ix 和浮点索引器进行位置设置将向索引中添加此值,而不是以前按位置设置值。

In [3]: s2.ix[1.0] = 10
In [4]: s2
Out[4]:
a       1
b       2
c       3
1.0    10
dtype: int64 

对于非Float64Index,切片操作还会将类似整数的浮点数强制转换为整数。

In [116]: s.loc[5.0:6]
Out[116]: 
5    2
6    3
Length: 2, dtype: int64 

请注意,对于无法强制转换为整数的浮点数,基于标签的边界将被排除。

In [117]: s.loc[5.1:6]
Out[117]: 
6    3
Length: 1, dtype: int64 

Float64Index 上的浮点索引操作保持不变。

In [118]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [119]: s[1.0]
Out[119]: 2

In [120]: s[1.0:2.5]
Out[120]: 
1.0    2
2.0    3
Length: 2, dtype: int64 
```### 移除之前版本的弃用/更改

+   移除 `rolling_corr_pairwise`,改为使用 `.rolling().corr(pairwise=True)`([GH 4950](https://github.com/pandas-dev/pandas/issues/4950))

+   移除 `expanding_corr_pairwise`,改为使用 `.expanding().corr(pairwise=True)`([GH 4950](https://github.com/pandas-dev/pandas/issues/4950))

+   移除 `DataMatrix` 模块。这在任何情况下都没有被导入到 pandas 命名空间中([GH 12111](https://github.com/pandas-dev/pandas/issues/12111))

+   在 `DataFrame.duplicated()` 和 `DataFrame.drop_duplicates()` 中,`cols` 关键字已被弃用,改为使用 `subset`([GH 6680](https://github.com/pandas-dev/pandas/issues/6680))

+   移除 `read_frame` 和 `frame_query`(都是 `pd.read_sql` 的别名)以及 `write_frame`(`to_sql` 的别名)函数在 `pd.io.sql` 命名空间中,自 0.14.0 版本起已被弃用([GH 6292](https://github.com/pandas-dev/pandas/issues/6292))。

+   移除 `.factorize()` 中的 `order` 关键字([GH 6930](https://github.com/pandas-dev/pandas/issues/6930))

### NaT 和 Timedelta 操作

`NaT` 和 `Timedelta` 扩展了算术运算,适用于 `Series` 的算术运算也相应扩展。 对于 `datetime64[ns]` 或 `timedelta64[ns]` 定义的操作现在也适用于 `NaT` ([GH 11564](https://github.com/pandas-dev/pandas/issues/11564))。

现在 `NaT` 支持与整数和浮点数进行算术运算。

```py
In [58]: pd.NaT * 1
Out[58]: NaT

In [59]: pd.NaT * 1.5
Out[59]: NaT

In [60]: pd.NaT / 2
Out[60]: NaT

In [61]: pd.NaT * np.nan
Out[61]: NaT 

NaT 定义了更多与 datetime64[ns]timedelta64[ns] 的算术运算。

In [62]: pd.NaT / pd.NaT
Out[62]: nan

In [63]: pd.Timedelta('1s') / pd.NaT
Out[63]: nan 

NaT 可能表示 datetime64[ns] 空值或 timedelta64[ns] 空值。 鉴于歧义,将其视为 timedelta64[ns],这样可以使更多操作成功。

In [64]: pd.NaT + pd.NaT
Out[64]: NaT

# same as
In [65]: pd.Timedelta('1s') + pd.Timedelta('1s')
Out[65]: Timedelta('0 days 00:00:02') 

与...相反

In [3]: pd.Timestamp('19900315') + pd.Timestamp('19900315')
TypeError: unsupported operand type(s) for +: 'Timestamp' and 'Timestamp' 

但是,当包装在 dtypedatetime64[ns]timedelta64[ns]Series 中时,将尊重 dtype 信息。

In [1]: pd.Series([pd.NaT], dtype='<M8[ns]') + pd.Series([pd.NaT], dtype='<M8[ns]')
TypeError: can only operate on a datetimes for subtraction,
 but the operator [__add__] was passed 
In [66]: pd.Series([pd.NaT], dtype='<m8[ns]') + pd.Series([pd.NaT], dtype='<m8[ns]')
Out[66]: 
0   NaT
Length: 1, dtype: timedelta64[ns] 

Timedelta 通过 floats 进行除法现在有效。

In [67]: pd.Timedelta('1s') / 2.0
Out[67]: Timedelta('0 days 00:00:00.500000') 

通过 TimedeltaSeries 中的 Timestamp 进行减法运算有效(GH 11925

In [68]: ser = pd.Series(pd.timedelta_range('1 day', periods=3))

In [69]: ser
Out[69]: 
0   1 days
1   2 days
2   3 days
Length: 3, dtype: timedelta64[ns]

In [70]: pd.Timestamp('2012-01-01') - ser
Out[70]: 
0   2011-12-31
1   2011-12-30
2   2011-12-29
Length: 3, dtype: datetime64[ns] 

NaT.isoformat() 现在返回 'NaT'。 此更改允许 pd.Timestamp 从其 isoformat 重新创建任何类似时间戳的对象 (GH 12300)。

msgpack 的更改

0.17.0 和 0.18.0 上进行了 msgpack 写入格式的向前不兼容更改; 较旧版本的 pandas 无法读取由较新版本打包的文件 (GH 12129GH 10527)

0.17.0 中引入的 to_msgpackread_msgpack 中的错误在 0.18.0 中修复,导致 Python 2 打包的文件无法被 Python 3 读取 (GH 12142)。 以下表格描述了 msgpack 的向后和向前兼容性。

警告

由以下版本打包 可以解包
pre-0.17 / Python 2 任何
pre-0.17 / Python 3 任何
0.17 / Python 2
  • ==0.17 / Python 2

  • =0.18 / 任何 Python

|

0.17 / Python 3 >=0.18 / 任何 Python
0.18 >= 0.18

0.18.0 对于由较旧版本打包的文件是向后兼容的,但对于 0.17 在 Python 2 中打包的文件,只能在 Python 2 中解包。

.rank 的签名更改

Series.rankDataFrame.rank 现在具有相同的签名 (GH 11759)

以前的签名

In [3]: pd.Series([0,1]).rank(method='average', na_option='keep',
 ascending=True, pct=False)
Out[3]:
0    1
1    2
dtype: float64

In [4]: pd.DataFrame([0,1]).rank(axis=0, numeric_only=None,
 method='average', na_option='keep',
 ascending=True, pct=False)
Out[4]:
 0
0  1
1  2 

新签名

In [71]: pd.Series([0,1]).rank(axis=0, method='average', numeric_only=False,
 ....:                      na_option='keep', ascending=True, pct=False)
 ....: 
Out[71]: 
0    1.0
1    2.0
Length: 2, dtype: float64

In [72]: pd.DataFrame([0,1]).rank(axis=0, method='average', numeric_only=False,
 ....:                         na_option='keep', ascending=True, pct=False)
 ....: 
Out[72]: 
 0
0  1.0
1  2.0

[2 rows x 1 columns] 

季度起始日当 n=0 时存在的错误

在先前版本中,当 n 参数为 0 时,QuarterBegin 偏移的行为取决于日期。

对于 n=0 的锚定偏移的一般语义是当它是锚点时不移动日期(例如,季度开始日期),否则向前滚动到下一个锚点。

In [73]: d = pd.Timestamp('2014-02-01')

In [74]: d
Out[74]: Timestamp('2014-02-01 00:00:00')

In [75]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[75]: Timestamp('2014-02-01 00:00:00')

In [76]: d + pd.offsets.QuarterBegin(n=0, startingMonth=1)
Out[76]: Timestamp('2014-04-01 00:00:00') 

对于之前版本中的 QuarterBegin 偏移,如果日期与季度开始日期在同一个月,则日期会向滚动。

In [3]: d = pd.Timestamp('2014-02-15')

In [4]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[4]: Timestamp('2014-02-01 00:00:00') 

此行为已在版本 0.18.0 中得到纠正,与其他锚定偏移量(如 MonthBeginYearBegin)保持一致。

In [77]: d = pd.Timestamp('2014-02-15')

In [78]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[78]: Timestamp('2014-05-01 00:00:00') 

重新采样 API

与上文中窗口函数 API 的更改类似,.resample(...) 正在改为具有更类似于 groupby 的 API。(GH 11732, GH 12702, GH 12202, GH 12332, GH 12334, GH 12348, GH 12448)。

In [79]: np.random.seed(1234)

In [80]: df = pd.DataFrame(np.random.rand(10,4),
 ....:                  columns=list('ABCD'),
 ....:                  index=pd.date_range('2010-01-01 09:00:00',
 ....:                                      periods=10, freq='s'))
 ....: 

In [81]: df
Out[81]: 
 A         B         C         D
2010-01-01 09:00:00  0.191519  0.622109  0.437728  0.785359
2010-01-01 09:00:01  0.779976  0.272593  0.276464  0.801872
2010-01-01 09:00:02  0.958139  0.875933  0.357817  0.500995
2010-01-01 09:00:03  0.683463  0.712702  0.370251  0.561196
2010-01-01 09:00:04  0.503083  0.013768  0.772827  0.882641
2010-01-01 09:00:05  0.364886  0.615396  0.075381  0.368824
2010-01-01 09:00:06  0.933140  0.651378  0.397203  0.788730
2010-01-01 09:00:07  0.316836  0.568099  0.869127  0.436173
2010-01-01 09:00:08  0.802148  0.143767  0.704261  0.704581
2010-01-01 09:00:09  0.218792  0.924868  0.442141  0.909316

[10 rows x 4 columns] 

以前的 API

您将编写一个立即评估的重新采样操作。如果未提供 how 参数,它将默认为 how='mean'

In [6]: df.resample('2s')
Out[6]:
 A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949 

您也可以直接指定 how

In [7]: df.resample('2s', how='sum')
Out[7]:
 A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897 

新 API:

现在,您可以像 .groupby(...) 一样将 .resample(..) 写成两阶段操作,这将产生一个 Resampler

In [82]: r = df.resample('2s')

In [83]: r
Out[83]: <pandas.core.resample.DatetimeIndexResampler object at 0x7ff230e71c30> 

降采样

然后,您可以使用此对象执行操作。这些是降采样操作(从更高频率到更低频率)。

In [84]: r.mean()
Out[84]: 
 A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949

[5 rows x 4 columns] 
In [85]: r.sum()
Out[85]: 
 A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897

[5 rows x 4 columns] 

此外,现在 resample 支持 getitem 操作,以在特定列上执行重新采样。

In [86]: r[['A','C']].mean()
Out[86]: 
 A         C
2010-01-01 09:00:00  0.485748  0.357096
2010-01-01 09:00:02  0.820801  0.364034
2010-01-01 09:00:04  0.433985  0.424104
2010-01-01 09:00:06  0.624988  0.633165
2010-01-01 09:00:08  0.510470  0.573201

[5 rows x 2 columns] 

.aggregate 类型的操作。

In [87]: r.agg({'A' : 'mean', 'B' : 'sum'})
Out[87]: 
 A         B
2010-01-01 09:00:00  0.485748  0.894701
2010-01-01 09:00:02  0.820801  1.588635
2010-01-01 09:00:04  0.433985  0.629165
2010-01-01 09:00:06  0.624988  1.219477
2010-01-01 09:00:08  0.510470  1.068634

[5 rows x 2 columns] 

当然,这些访问器可以组合使用

In [88]: r[['A','B']].agg(['mean','sum'])
Out[88]: 
 A                   B 
 mean       sum      mean       sum
2010-01-01 09:00:00  0.485748  0.971495  0.447351  0.894701
2010-01-01 09:00:02  0.820801  1.641602  0.794317  1.588635
2010-01-01 09:00:04  0.433985  0.867969  0.314582  0.629165
2010-01-01 09:00:06  0.624988  1.249976  0.609738  1.219477
2010-01-01 09:00:08  0.510470  1.020940  0.534317  1.068634

[5 rows x 4 columns] 

上采样

上采样操作将您从低频率转到高频率。现在,这些操作由 Resampler 对象使用 backfill()ffill()fillna()asfreq() 方法执行。

In [89]: s = pd.Series(np.arange(5, dtype='int64'),
 index=pd.date_range('2010-01-01', periods=5, freq='Q'))

In [90]: s
Out[90]:
2010-03-31    0
2010-06-30    1
2010-09-30    2
2010-12-31    3
2011-03-31    4
Freq: Q-DEC, Length: 5, dtype: int64 

以前

In [6]: s.resample('M', fill_method='ffill')
Out[6]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, dtype: int64 

新 API

In [91]: s.resample('M').ffill()
Out[91]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, Length: 13, dtype: int64 

注意

在新 API 中,您可以进行降采样或上采样。之前的实现允许您传递聚合函数(如 mean),即使您正在上采样,这可能会带来一些困惑。

以前的 API 仍然可用,但已弃用。

警告

重新采样的这种新 API 包括一些内部更改,用于之前的 0.18.0 版 API,以与大多数情况下的弃用警告一起工作,因为重新采样操作返回一个延迟对象。我们可以拦截操作,并仅执行(0.18.0 之前的)API 所做的事情(带有警告)。以下是一个典型的用例:

In [4]: r = df.resample('2s')

In [6]: r*10
pandas/tseries/resample.py:80: FutureWarning: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...)

Out[6]:
 A         B         C         D
2010-01-01 09:00:00  4.857476  4.473507  3.570960  7.936154
2010-01-01 09:00:02  8.208011  7.943173  3.640340  5.310957
2010-01-01 09:00:04  4.339846  3.145823  4.241039  6.257326
2010-01-01 09:00:06  6.249881  6.097384  6.331650  6.124518
2010-01-01 09:00:08  5.104699  5.343172  5.732009  8.069486 

然而,在 Resampler 上直接进行获取和赋值操作将引发 ValueError

In [7]: r.iloc[0] = 5
ValueError: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...) 

在使用原始代码时,存在一种情况,新 API 无法执行所有操作。此代码意在每 2 秒重新采样一次,取 mean 然后取这些结果的 min

In [4]: df.resample('2s').min()
Out[4]:
A    0.433985
B    0.314582
C    0.357096
D    0.531096
dtype: float64 

新 API 将:

In [89]: df.resample('2s').min()
Out[89]: 
 A         B         C         D
2010-01-01 09:00:00  0.191519  0.272593  0.276464  0.785359
2010-01-01 09:00:02  0.683463  0.712702  0.357817  0.500995
2010-01-01 09:00:04  0.364886  0.013768  0.075381  0.368824
2010-01-01 09:00:06  0.316836  0.568099  0.397203  0.436173
2010-01-01 09:00:08  0.218792  0.143767  0.442141  0.704581

[5 rows x 4 columns] 

好消息是新 API 和旧 API 的返回维度将不同,因此这应该会引发异常。

要复制原始操作

In [90]: df.resample('2s').mean().min()
Out[90]: 
A    0.433985
B    0.314582
C    0.357096
D    0.531096
Length: 4, dtype: float64 

降采样

然后,您可以使用此对象执行操作。这些是降采样操作(从更高频率到更低频率)。

In [84]: r.mean()
Out[84]: 
 A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949

[5 rows x 4 columns] 
In [85]: r.sum()
Out[85]: 
 A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897

[5 rows x 4 columns] 

此外,现在 resample 支持 getitem 操作,以在特定列上执行重新采样。

In [86]: r[['A','C']].mean()
Out[86]: 
 A         C
2010-01-01 09:00:00  0.485748  0.357096
2010-01-01 09:00:02  0.820801  0.364034
2010-01-01 09:00:04  0.433985  0.424104
2010-01-01 09:00:06  0.624988  0.633165
2010-01-01 09:00:08  0.510470  0.573201

[5 rows x 2 columns] 

.aggregate 类型的操作。

In [87]: r.agg({'A' : 'mean', 'B' : 'sum'})
Out[87]: 
 A         B
2010-01-01 09:00:00  0.485748  0.894701
2010-01-01 09:00:02  0.820801  1.588635
2010-01-01 09:00:04  0.433985  0.629165
2010-01-01 09:00:06  0.624988  1.219477
2010-01-01 09:00:08  0.510470  1.068634

[5 rows x 2 columns] 

当然,这些访问器可以组合使用

In [88]: r[['A','B']].agg(['mean','sum'])
Out[88]: 
 A                   B 
 mean       sum      mean       sum
2010-01-01 09:00:00  0.485748  0.971495  0.447351  0.894701
2010-01-01 09:00:02  0.820801  1.641602  0.794317  1.588635
2010-01-01 09:00:04  0.433985  0.867969  0.314582  0.629165
2010-01-01 09:00:06  0.624988  1.249976  0.609738  1.219477
2010-01-01 09:00:08  0.510470  1.020940  0.534317  1.068634

[5 rows x 4 columns] 

上采样

上采样操作将您从较低频率转移到较高频率。现在使用Resampler对象执行这些操作,具有backfill()ffill()fillna()asfreq()方法。

In [89]: s = pd.Series(np.arange(5, dtype='int64'),
 index=pd.date_range('2010-01-01', periods=5, freq='Q'))

In [90]: s
Out[90]:
2010-03-31    0
2010-06-30    1
2010-09-30    2
2010-12-31    3
2011-03-31    4
Freq: Q-DEC, Length: 5, dtype: int64 

以前

In [6]: s.resample('M', fill_method='ffill')
Out[6]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, dtype: int64 

新 API

In [91]: s.resample('M').ffill()
Out[91]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, Length: 13, dtype: int64 

注意

在新 API 中,您可以进行下采样或上采样。之前的实现允许您传递聚合函数(如mean),即使您在上采样,这可能会带来一些混淆。

之前的 API 将继续工作,但会有弃用警告

警告

这个新的重采样 API 包括一些内部更改,用于之前的 0.18.0 版本 API,以便在大多数情况下使用弃用警告,因为重采样操作返回一个延迟对象。我们可以拦截操作,并只执行(0.18.0 之前)API 执行的操作(带有警告)。这里是一个典型的用例:

In [4]: r = df.resample('2s')

In [6]: r*10
pandas/tseries/resample.py:80: FutureWarning: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...)

Out[6]:
 A         B         C         D
2010-01-01 09:00:00  4.857476  4.473507  3.570960  7.936154
2010-01-01 09:00:02  8.208011  7.943173  3.640340  5.310957
2010-01-01 09:00:04  4.339846  3.145823  4.241039  6.257326
2010-01-01 09:00:06  6.249881  6.097384  6.331650  6.124518
2010-01-01 09:00:08  5.104699  5.343172  5.732009  8.069486 

但是,在Resampler上直接进行获取和赋值操作将引发ValueError

In [7]: r.iloc[0] = 5
ValueError: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...) 

有一种情况,新 API 无法在使用原始代码时执行所有操作。这段代码意在每 2 秒重采样,取mean然后取这些结果的min

In [4]: df.resample('2s').min()
Out[4]:
A    0.433985
B    0.314582
C    0.357096
D    0.531096
dtype: float64 

新 API 将:

In [89]: df.resample('2s').min()
Out[89]: 
 A         B         C         D
2010-01-01 09:00:00  0.191519  0.272593  0.276464  0.785359
2010-01-01 09:00:02  0.683463  0.712702  0.357817  0.500995
2010-01-01 09:00:04  0.364886  0.013768  0.075381  0.368824
2010-01-01 09:00:06  0.316836  0.568099  0.397203  0.436173
2010-01-01 09:00:08  0.218792  0.143767  0.442141  0.704581

[5 rows x 4 columns] 

好消息是,新 API 和旧 API 之间的返回维度将不同,因此这应该会引发异常。

为了复制原始操作

In [90]: df.resample('2s').mean().min()
Out[90]: 
A    0.433985
B    0.314582
C    0.357096
D    0.531096
Length: 4, dtype: float64 

对 eval 的更改

在之前的版本中,在eval表达式中进行新列赋值会导致对DataFrame的原地更改。(GH 9297, GH 8664, GH 10486)

In [91]: df = pd.DataFrame({'a': np.linspace(0, 10, 5), 'b': range(5)})

In [92]: df
Out[92]: 
 a  b
0   0.0  0
1   2.5  1
2   5.0  2
3   7.5  3
4  10.0  4

[5 rows x 2 columns] 
In [12]: df.eval('c = a + b')
FutureWarning: eval expressions containing an assignment currentlydefault to operating inplace.
This will change in a future version of pandas, use inplace=True to avoid this warning.

In [13]: df
Out[13]:
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0 

在 0.18.0 版本中,添加了一个新的inplace关键字,用于选择是应该原地进行赋值还是返回一个副本。

In [93]: df
Out[93]: 
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [94]: df.eval('d = c - b', inplace=False)
Out[94]: 
 a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns]

In [95]: df
Out[95]: 
 a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [96]: df.eval('d = c - b', inplace=True)

In [97]: df
Out[97]: 
 a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns] 

警告

为了向后兼容,如果未指定,inplace默认为True。这将在未来的 pandas 版本中更改。如果您的代码依赖于原地赋值,您应该更新为显式设置inplace=True

inplace关键字参数也被添加到query方法中。

In [98]: df.query('a > 5')
Out[98]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [99]: df.query('a > 5', inplace=True)

In [100]: df
Out[100]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns] 

警告

请注意,在queryinplace的默认值为False,这与之前的版本一致。

eval也已更新,允许多行表达式进行多个赋值。这些表达式将按顺序逐个进行评估。多行表达式只对赋值有效。

In [101]: df
Out[101]: 
 a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [102]: df.eval("""
 .....: e = d + a
 .....: f = e - 22
 .....: g = f / 2.0""", inplace=True)
 .....: 

In [103]: df
Out[103]: 
 a  b     c     d     e    f    g
3   7.5  3  10.5   7.5  15.0 -7.0 -3.5
4  10.0  4  14.0  10.0  20.0 -2.0 -1.0

[2 rows x 7 columns] 

其他 API 更改

  • DataFrame.between_timeSeries.between_time现在只解析一组固定的时间字符串。不再支持日期字符串的解析,并引发ValueError。(GH 11818)

    In [107]: s = pd.Series(range(10), pd.date_range('2015-01-01', freq='H', periods=10))
    
    In [108]: s.between_time("7:00am", "9:00am")
    Out[108]:
    2015-01-01 07:00:00    7
    2015-01-01 08:00:00    8
    2015-01-01 09:00:00    9
    Freq: H, Length: 3, dtype: int64 
    

    现在会引发错误。

    In [2]: s.between_time('20150101 07:00:00','20150101 09:00:00')
    ValueError: Cannot convert arg ['20150101 07:00:00'] to a time. 
    
  • .memory_usage()现在包括索引中的值,.info()中的 memory_usage 也是如此 (GH 11597)

  • DataFrame.to_latex()现在支持非 ascii 编码(例如utf-8)在 Python 2 中使用参数encoding (GH 7061)

  • 当尝试与不是DataFrame或其子类的对象合并时,pandas.merge()DataFrame.merge()将显示特定的错误消息(GH 12081

  • DataFrame.unstackSeries.unstack现在接受fill_value关键字,以允许在 unstack 导致结果DataFrame中出现缺失值时直接替换缺失值。另一个好处是,指定fill_value将保留原始堆叠数据的数据类型(GH 9746

  • 作为窗口函数和重新采样的新 API 的一部分,聚合函数已经得到澄清,对无效聚合提出更具信息性的错误消息(GH 9052)。在 groupby 中提供了一整套示例。

  • NDFrame对象的统计函数(如sum(), mean(), min())现在会在传递给**kwargs的非 numpy 兼容参数时引发错误(GH 12301

  • .to_latex.to_html现在增加了一个decimal参数,类似于.to_csv;默认值为'.'GH 12031

  • 当使用空数据但带有索引构建DataFrame时,会提供更有帮助的错误消息(GH 8020

  • .describe()现在将正确处理 bool 类型作为分类变量(GH 6625

  • 在使用用户定义输入的无效.transform时提供更有帮助的错误消息(GH 10165)

  • 指数加权函数现在允许直接指定 alpha 值(GH 10789),并且如果参数违反0 < alpha <= 1,则会引发ValueErrorGH 12492

弃用

  • 函数pd.rolling_*pd.expanding_*pd.ewm*已被弃用,并被相应的方法调用所取代。请注意,新建议的语法包括所有参数(即使是默认值)(GH 11603

    In [1]: s = pd.Series(range(3))
    
    In [2]: pd.rolling_mean(s,window=2,min_periods=1)
     FutureWarning: pd.rolling_mean is deprecated for Series and
     will be removed in a future version, replace with
     Series.rolling(min_periods=1,window=2,center=False).mean()
    Out[2]:
     0    0.0
     1    0.5
     2    1.5
     dtype: float64
    
    In [3]: pd.rolling_cov(s, s, window=2)
     FutureWarning: pd.rolling_cov is deprecated for Series and
     will be removed in a future version, replace with
     Series.rolling(window=2).cov(other=<Series>)
    Out[3]:
     0    NaN
     1    0.5
     2    0.5
     dtype: float64 
    
  • .rolling.expanding.ewm(新)函数的freqhow参数已被弃用,并将在将来的版本中移除。您可以在创建窗口函数之前简单地对输入进行重新采样(GH 11603)。

    例如,不再使用s.rolling(window=5,freq='D').max()来获取滚动 5 天窗口上的最大值,而是可以使用s.resample('D').mean().rolling(window=5).max(),首先将数据重新采样为每日数据,然后提供一个滚动 5 天窗口。

  • pd.tseries.frequencies.get_offset_name 函数已弃用。使用偏移的 .freqstr 属性作为替代方案 (GH 11192)

  • pandas.stats.fama_macbeth 例程已弃用,并将在未来版本中移除 (GH 6077)

  • pandas.stats.olspandas.stats.plmpandas.stats.var 例程已弃用,并将在未来版本中移除 (GH 6077)

  • HDFStore.select 中,使用长时间弃用的语法时,将显示 FutureWarning 而不是 DeprecationWarning,其中 where 子句不是类似字符串的情况 (GH 12027)

  • pandas.options.display.mpl_style 配置已弃用,并将在未来版本的 pandas 中移除。此功能最好由 matplotlib 的 样式表 处理 (GH 11783)。

移除弃用的浮点索引器

GH 4892 中,对非 Float64Index 上的浮点数进行索引已弃用(在 0.14.0 版本中)。在 0.18.0 版本中,此弃用警告已移除,现在将引发 TypeError。 (GH 12165, GH 12333)

In [104]: s = pd.Series([1, 2, 3], index=[4, 5, 6])

In [105]: s
Out[105]: 
4    1
5    2
6    3
Length: 3, dtype: int64

In [106]: s2 = pd.Series([1, 2, 3], index=list('abc'))

In [107]: s2
Out[107]: 
a    1
b    2
c    3
Length: 3, dtype: int64 

先前行为:

# this is label indexing
In [2]: s[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[2]: 2

# this is positional indexing
In [3]: s.iloc[1.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[3]: 2

# this is label indexing
In [4]: s.loc[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[4]: 2

# .ix would coerce 1.0 to the positional 1, and index
In [5]: s2.ix[1.0] = 10
FutureWarning: scalar indexers for index type Index should be integers and not floating point

In [6]: s2
Out[6]:
a     1
b    10
c     3
dtype: int64 

新行为:

对于 iloc,通过浮点标量进行获取和设置将始终引发错误。

In [3]: s.iloc[2.0]
TypeError: cannot do label indexing on <class 'pandas.indexes.numeric.Int64Index'> with these indexers [2.0] of <type 'float'> 

其他索引器将在获取和设置时强制转换为类似整数。对于 .loc.ix[]FutureWarning 已被移除。

In [108]: s[5.0]
Out[108]: 2

In [109]: s.loc[5.0]
Out[109]: 2 

和设置

In [110]: s_copy = s.copy()

In [111]: s_copy[5.0] = 10

In [112]: s_copy
Out[112]: 
4     1
5    10
6     3
Length: 3, dtype: int64

In [113]: s_copy = s.copy()

In [114]: s_copy.loc[5.0] = 10

In [115]: s_copy
Out[115]: 
4     1
5    10
6     3
Length: 3, dtype: int64 

使用 .ix 和浮点索引器进行位置设置将将此值添加到索引中,而不是以前按位置设置值。

In [3]: s2.ix[1.0] = 10
In [4]: s2
Out[4]:
a       1
b       2
c       3
1.0    10
dtype: int64 

对于非 Float64Index,切片还将强制将整数型浮点数转换为整数。

In [116]: s.loc[5.0:6]
Out[116]: 
5    2
6    3
Length: 2, dtype: int64 

请注意,对于无法强制转换为整数的浮点数,基于标签的边界将被排除。

In [117]: s.loc[5.1:6]
Out[117]: 
6    3
Length: 1, dtype: int64 

Float64Index 上进行浮点索引不变。

In [118]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [119]: s[1.0]
Out[119]: 2

In [120]: s[1.0:2.5]
Out[120]: 
1.0    2
2.0    3
Length: 2, dtype: int64 

移除之前版本的弃用/更改

  • 弃用 rolling_corr_pairwise,改用 .rolling().corr(pairwise=True) (GH 4950)

  • 弃用 expanding_corr_pairwise,改用 .expanding().corr(pairwise=True) (GH 4950)

  • 移除 DataMatrix 模块。无论如何,此模块都未被导入到 pandas 命名空间中 (GH 12111)

  • 弃用 cols 关键字,改用 DataFrame.duplicated()DataFrame.drop_duplicates() 中的 subset (GH 6680)

  • 移除 read_frameframe_query(均为 pd.read_sql 的别名)以及 write_frameto_sql 的别名)函数在 pd.io.sql 命名空间中,自 0.14.0 版本起已弃用 (GH 6292)。

  • .factorize()中移除了order关键字(GH 6930

性能改进

  • 提高了andrews_curves的性能(GH 11534

  • 提高了巨大DatetimeIndexPeriodIndexTimedeltaIndex的操作性能,包括NaTGH 10277

  • 提高了pandas.concat的性能(GH 11958

  • 提高了StataReader的性能(GH 11591

  • 在包含NaT的日期时间SeriesCategoricals构造中,提高了性能(GH 12077

  • 提高了 ISO 8601 日期解析的性能,包括无分隔符的日期(GH 11899)、前导零(GH 11871)和时区前的空格(GH 9714

错误修复

  • 当数据框为空时,修复了GroupBy.size中的错误(GH 11699

  • 当请求时间段的倍数时,修复了Period.end_time中的错误(GH 11738

  • 在具有时区的日期时间上,修复了.clip中的回归(GH 11838

  • 当边界落在频率上时,修复了date_range中的错误(GH 11804GH 12409

  • 在将嵌套字典传递给.groupby(...).agg(...)时,修复了一致性错误(GH 9052

  • Timedelta构造函数中接受 Unicode(GH 11995

  • 当增量读取时,修复了StataReader中读取值标签的错误(GH 12014

  • n参数为0时,修复了向量化DateOffset中的错误(GH 11370

  • 与 numpy 1.11 兼容,关于NaT比较的更改(GH 12049

  • 当从线程中的StringIO读取时,修复了read_csv中的错误(GH 11790

  • 当因子化和使用Categoricals时,未将NaT视为缺失值的错误(GH 12077

  • Series的值带有时区时,修复了 getitem 中的错误(GH 12089

  • 修复了Series.str.get_dummies中一个变量为‘name’时的错误(GH 12180

  • 连接 tz-aware NaT series 时 pd.concat 中存在的错误。 (GH 11693, GH 11755, GH 12217)

  • pd.read_stata 中存在版本 <= 108 文件的错误 (GH 12232)

  • 当索引是 DatetimeIndex 并且包含非零纳秒部分时,使用 Nano 频率的 Series.resample 中存在的错误 (GH 12037)

  • 使用 .nunique 和稀疏索引进行重采样的错误 (GH 12352)

  • 移除了一些编译器警告 (GH 12471)

  • 在 python 3.5 中使用 boto 的兼容性问题解决方案 (GH 11915)

  • 从具有时区的 TimestampDatetimeIndex 减去 NaT 中存在的错误 (GH 11718)

  • 单个 tz-aware TimestampSeries 减法中存在的错误 (GH 12290)

  • 使用兼容的迭代器在 PY2 中支持 .next() (GH 12299)

  • Timedelta.round 中存在负值的错误 (GH 11690)

  • 针对 CategoricalIndex.loc 中可能导致正常 Index 的错误 (GH 11586)

  • 当存在重复列名时 DataFrame.info 中存在的错误 (GH 11761)

  • 日期时间 tz-aware 对象的 .copy 中存在的错误 (GH 11794)

  • Series.applySeries.map 中存在的 timedelta64 未包装的错误 (GH 11349)

  • DataFrame.set_index() 中存在带有时区感知的 Series 的错误 (GH 12358)

  • DataFrame 的子类中存在 AttributeError 未传播的错误 (GH 11808)

  • 在 tz-aware 数据上进行分组,选择未返回 Timestamp 的错误 (GH 11616)

  • pd.read_clipboardpd.to_clipboard 函数不支持 Unicode 的错误;升级包含了 pyperclip 到 v1.5.15 (GH 9263)

  • 包含赋值的 DataFrame.query 中存在的错误 (GH 8664)

  • from_msgpack 中,如果 DataFrame 具有对象列,则对解压缩的 DataFrame 的列进行 __contains__() 失败的错误。 (GH 11880)

  • 在具有 TimedeltaIndex 的分类数据上的 .resample 中存在的错误 (GH 12169)

  • 当将标量日期时间广播到 DataFrame 时,时区信息丢失的 Bug(GH 11682

  • 从具有混合时区的 Timestamp 创建 Index 时的 Bug 会强制转换为 UTC(GH 11488

  • to_numeric 中的 Bug 不会在输入为多维时引发异常(GH 11776

  • 在解析具有非零分钟的时区偏移字符串时的 Bug(GH 11708

  • 在 matplotlib 1.5+ 下,df.plot 中的 Bug 会为柱状图使用不正确的颜色(GH 11614

  • 在使用关键字参数时,groupby plot 方法中的 Bug(GH 11805

  • 在设置 keep=False 时,DataFrame.duplicateddrop_duplicates 中的 Bug 会导致错误匹配(GH 11864

  • 在重复键具有的 .loc 结果中,可能会出现具有不正确 dtype 的 Index 的 Bug(GH 11497

  • pd.rolling_median 中的 Bug,即使内存充足,内存分配也失败了(GH 11696

  • DataFrame.style 中的 Bug 会产生错误的零值(GH 12134

  • DataFrame.style 中,整数列不从 0 开始的 Bug(GH 12125

  • 使用特定浏览器时,.style.bar 中的 Bug 可能无法正确渲染(GH 11678

  • numpy.array 中的 Timedelta 进行比较时,发生无限递归的 Timedelta 的 Bug (GH 11835

  • DataFrame.round 中的 Bug 会丢失列索引名称(GH 11986

  • 在混合数据类型 Dataframe 中替换值时,df.replace 中的 Bug 会导致问题(GH 11698

  • 当未提供新名称时,Index 中的 Bug 会阻止复制传递的 Index 名称(GH 11193

  • read_excel 中的 Bug 在存在空工作表且 sheetname=None 时无法读取任何非空工作表(GH 11711

  • 当提供关键字 parse_datesdate_parser 时,read_excel 中的 Bug 未能引发 NotImplemented 错误(GH 11544

  • 使用 pymysql 连接时,read_sql 中的 Bug 无法返回分块数据(GH 11522

  • .to_csv 中,忽略了浮点索引的格式化参数 decimalna_repfloat_format 的 Bug(GH 11553

  • Int64IndexFloat64Index 中的错误,阻止了模数运算符的使用(GH 9244

  • MultiIndex.drop 中的错误,未按字典顺序排序 MultiIndexes(GH 12078

  • 在掩盖空的 DataFrame 时的 DataFrame 中的错误(GH 11859

  • 当列数不匹配所提供的系列数量时,.plot 中可能会修改 colors 输入的错误(GH 12039)。

  • 当索引具有 CustomBusinessDay 频率时,Series.plot 失败的错误(GH 7222)。

  • 对于带有 sqlite 回退的 datetime.time 值,to_sql 中的错误(GH 8341

  • squeeze=True 时,read_excel 在只有一列数据时无法读取的错误(GH 12157

  • 在读取一个空列时,read_excel 失败(GH 12292GH 9002

  • .groupby 中的错误,如果 dataframe 中只有一行,则不会针对错误的列引发 KeyErrorGH 11741

  • 在空数据上指定 dtype 的情况下,.read_csv 中出现错误(GH 12048

  • .read_csv 中字符串如 '2E' 被视为有效浮点数的错误(GH 12237

  • 在使用调试符号构建 pandas 时出现的错误(GH 12123

  • 移除了 DatetimeIndexmillisecond 属性。这将始终引发 ValueErrorGH 12019)。

  • 在只读数据中的 Series 构造函数中的错误(GH 11502

  • 移除了 pandas._testing.choice()。应该使用 np.random.choice() 代替。 (GH 12386

  • .loc setitem 索引器中的错误,阻止了使用 TZ-aware DatetimeIndex(GH 12050

  • .style 中索引和 MultiIndexes 不出现的错误(GH 11655

  • to_msgpackfrom_msgpack 中未正确序列化或反序列化 NaT 的错误(GH 12307

  • 由于高度相似值的四舍五入误差,.skew.kurt 中的错误(GH 11974

  • Timestamp 构造函数中,如果 HHMMSS 没有用 ':' 分隔,则会丢失微秒分辨率的错误(GH 10041

  • buffer_rd_bytes中的错误,如果读取失败,src->buffer 可能会被释放多次,导致段错误(GH 12098

  • crosstab中的错误,非重叠索引的参数将返回KeyError (GH 10291)

  • DataFrame.apply中的错误,未能防止那些dtype不是 numpy dtype 的情况下进行缩减 (GH 12244)

  • 初始化分类系列时出现错误,带有标量值。 (GH 12336)

  • .to_datetime中设置了 UTCDatetimeIndex时出现错误,通过设置utc=True (GH 11934)

  • read_csv中增加缓冲区大小时出现的错误(GH 12494

  • 设置具有重复列名的DataFrame的列时出现的错误 (GH 12344)

贡献者

共有 101 人为此版本提交了补丁。 姓名后带有“+”的人第一次贡献了补丁。

  • ARF +

  • Alex Alekseyev +

  • Andrew McPherson +

  • Andrew Rosenfeld

  • Andy Hayden

  • Anthonios Partheniou

  • Anton I. Sipos

  • Ben +

  • Ben North +

  • Bran Yang +

  • Chris

  • Chris Carroux +

  • Christopher C. Aycock +

  • Christopher Scanlin +

  • Cody +

  • Da Wang +

  • Daniel Grady +

  • Dorozhko Anton +

  • Dr-Irv +

  • Erik M. Bray +

  • Evan Wright

  • Francis T. O’Donovan +

  • Frank Cleary +

  • Gianluca Rossi

  • Graham Jeffries +

  • Guillaume Horel

  • Henry Hammond +

  • Isaac Schwabacher +

  • Jean-Mathieu Deschenes

  • Jeff Reback

  • Joe Jevnik +

  • John Freeman +

  • John Fremlin +

  • Jonas Hoersch +

  • Joris Van den Bossche

  • Joris Vankerschaver

  • Justin Lecher

  • Justin Lin +

  • Ka Wo Chen

  • Keming Zhang +

  • Kerby Shedden

  • Kyle +

  • Marco Farrugia +

  • MasonGallo +

  • MattRijk +

  • Matthew Lurie +

  • Maximilian Roos

  • Mayank Asthana +

  • Mortada Mehyar

  • Moussa Taifi +

  • Navreet Gill +

  • Nicolas Bonnotte

  • Paul Reiners +

  • Philip Gura +

  • Pietro Battiston

  • RahulHP +

  • Randy Carnevale

  • Rinoc Johnson

  • Rishipuri +

  • Sangmin Park +

  • Scott E Lasley

  • Sereger13 +

  • Shannon Wang +

  • Skipper Seabold

  • Thierry Moisan

  • Thomas A Caswell

  • Toby Dylan Hocking +

  • Tom Augspurger

  • Travis +

  • Trent Hauck

  • Tux1

  • Varun

  • Wes McKinney

  • Will Thompson +

  • Yoav Ram

  • Yoong Kang Lim +

  • Yoshiki Vázquez Baeza

  • Young Joong Kim +

  • Younggun Kim

  • Yuval Langer +

  • alex argunov +

  • behzad nouri

  • boombard +

  • brian-pantano +

  • chromy +

  • daniel +

  • dgram0 +

  • gfyoung +

  • hack-c +

  • hcontrast +

  • jfoo +

  • kaustuv deolal +

  • llllllllll

  • ranarag +

  • rockg

  • scls19fr

  • seales +

  • sinhrks

  • srib +

  • surveymedia.ca +

  • tworec +

posted @ 2024-06-26 10:37  绝不原创的飞龙  阅读(1)  评论(0编辑  收藏  举报