版本 0.18.1 (2016 年 5 月 3 日)#

这是 0.18.0 版本的一个小型的 bug 修复版本,包含大量 bug 修复以及若干新特性、增强功能和性能改进。我们建议所有用户升级到此版本。

主要亮点包括

  • .groupby(...) 已增强,在使用 .rolling(..), .expanding(..).resample(..) 进行分组操作时提供了便捷的语法,详见此处

  • pd.to_datetime() 增加了从 DataFrame 组装日期的能力,详见此处

  • 方法链改进,详见此处

  • 自定义工作小时偏移,详见此处

  • sparse 处理中的许多 bug 修复,详见此处

  • 扩展了教程部分,新增了现代 pandas 特性,由 @TomAugsburger 提供。(GH 13045)。

新特性#

自定义工作小时#

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 日前的星期五

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)。

您现在可以在 groupby 对象上将 .rolling(..).expanding(..) 作为方法使用。它们会返回另一个延迟对象(类似于 .rolling().expanding() 在未分组的 pandas 对象上的操作)。然后您可以以类似的方式操作这些 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()#

这些方法可以接受 callable 作为条件和 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,以及 callable 元组作为切片器。callable 可以返回一个有效的布尔索引器或任何对这些索引器输入有效的值。

# 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 的 [] 索引中使用 callable。callable 必须根据其类别和索引类型返回一个对 [] 索引有效的输入。

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]

DatetimeIndexMultiIndex 的一部分时进行部分字符串索引#

部分字符串索引现在在 DateTimeIndex 作为 MultiIndex 的一部分时匹配(GH 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 或 dict 组装日期时间的能力。(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]

使用传入的 DataFrame 进行组装。

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

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

  • pd.read_csv() 现在支持通过扩展名推断或显式指定 compression='xz' 来打开使用 xz 压缩的文件;DataFrame.to_csv 也以同样的方式支持 xz 压缩(GH 11852

  • pd.read_msgpack() 现在即使在使用压缩时也总是提供可写 ndarrays(GH 12359)。

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

  • .to_json() 现在支持包含 categorical 和 sparse 数据 的 NDFramesGH 10778

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

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

  • DatetimeIndex.dt accessor 添加了 .weekday_name 属性作为其组成部分。(GH 11128

  • Index.take 现在一致地处理 allow_fillfill_value 参数(GH 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 现在支持返回 MultiIndex.str.get_dummies() 方法,详见创建指示变量GH 10008, GH 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() 现在接受传入的 sets(集合)(GH 12988

Sparse 更改#

这些更改使 sparse 处理返回正确的类型,并致力于提供更顺畅的索引体验。

SparseArray.take 现在对标量输入返回标量,对其他输入返回 SparseArray。此外,它以与 Index 相同的规则处理负索引器(GH 10560, GH 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[] 可能导致返回 dense Series 而非 SparseSeries 的 bug(GH 12787

  • SparseArray 加法运算忽略右侧 fill_value 的 bug(GH 12910

  • SparseArray 取模运算引发 AttributeError 的 bug(GH 12910

  • SparseArray 幂运算将 1 ** np.nan 计算为 np.nan 而非 1 的 bug(GH 12910

  • SparseArray 比较运算输出结果可能不正确或引发 ValueError 的 bug(GH 12971

  • SparseSeries.__repr__ 在长度超过 max_rows 时引发 TypeError 的 bug(GH 10560

  • SparseSeries.shape 忽略 fill_value 的 bug(GH 10452

  • SparseSeriesSparseArraydtype 可能与其 dense 值不同步的 bug(GH 12908

  • SparseSeries.reindex 错误处理 fill_value 的 bug(GH 12797

  • SparseArray.to_frame() 结果为 DataFrame 而非 SparseDataFrame 的 bug(GH 9850

  • SparseSeries.value_counts() 不计数 fill_value 的 bug(GH 6749

  • SparseArray.to_dense() 不保留 dtype 的 bug(GH 10648

  • SparseArray.to_dense() 错误处理 fill_value 的 bug(GH 12797

  • pd.concat() 拼接 SparseSeries 导致结果为 dense 的 bug(GH 10536

  • pd.concat() 拼接 SparseDataFrame 错误处理 fill_value 的 bug(GH 9765

  • pd.concat() 拼接 SparseDataFrame 可能引发 AttributeError 的 bug(GH 12174

  • SparseArray.shift() 可能引发 NameErrorTypeError 的 bug(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 总是进行排序,无论是否在 .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 数组类方法(例如 sumtake)与其 numpy 对应方法的兼容性得到了显著提升(GH 12644, GH 12638, GH 12687

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

  • np.round()Series 上的 numpy 兼容性 bug(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 异常的变更#

为了标准化 read_csv API 在 c 引擎和 python 引擎中的行为,当遇到空列或无标题时,两者现在都将引发 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 并且 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() 中存在错误:当传递包含可转换条目的 uniterrors='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 变更#

  • SeriesDataFramePanelMultiIndex.swaplevel() 方法现在为其前两个参数 ij 设置了默认值,用于交换索引的最内两层。(GH 12934)

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

  • PeriodPeriodIndex 现在引发继承自 ValueErrorIncompatibleFrequency 错误,而不是原始的 ValueError (GH 12615)

  • 对于 category 数据类型,Series.apply 现在将传递的函数应用于其每个 .categories (而不是 .codes),并尽可能返回 category 数据类型 (GH 12473)

  • 如果 parse_dates 既不是布尔值、列表也不是字典,read_csv 现在将引发 TypeError (与文档字符串匹配) (GH 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)

  • 在合并/连接单层索引和多层索引的 DataFrame 时,pd.merge()DataFrame.join() 将显示 UserWarning (GH 9455, GH 12219)

  • scipy > 0.17 版本的兼容性:支持已弃用的 piecewise_polynomial 插值方法;支持替换方法 from_derivatives (GH 12887)

弃用#

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

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

性能改进#

  • 改进了 SAS 阅读器的速度 (GH 12656, GH 12961)

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

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

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

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

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

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

  • 改进了使用 IntIndex 进行稀疏运算的性能 (GH 13036)

错误修复#

  • 即使 CSV 文件行数不一致,pd.read_csv 中的 usecols 参数现在也能被遵守 (GH 12203)

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

  • PeriodPeriodIndex 创建中的错误:如果指定了 freq="Minute",会引发 KeyError。请注意,v0.17.0 版本中“Minute”频率已弃用,建议改用 freq="T" (GH 11854)

  • 使用 PeriodIndex 调用 .resample(...).count() 时总是引发 TypeError 的错误 (GH 12774)

  • 使用 PeriodIndex 调用 .resample(...) 时,在为空时转换为 DatetimeIndex 的错误 (GH 12868)

  • 使用 PeriodIndex 调用 .resample(...) 时,重采样到现有频率时的错误 (GH 12770)

  • 打印包含具有不同 freqPeriod 数据时引发 ValueError 的错误 (GH 12615)

  • 在使用 Categorical 构造 Series 且指定了 dtype='category' 时出错 (GH 12574)

  • 与可强制转换数据类型的连接过于激进,导致对象长度超过 display.max_rows 时输出格式的数据类型不同的错误 (GH 12411, GH 12045, GH 11594, GH 10571, GH 12211)

  • float_format 选项未被验证为可调用对象的错误 (GH 12706)

  • GroupBy.filter 中的错误:当 dropna=False 且没有组满足条件时 (GH 12768)

  • .cum* 函数的 __name__ 错误 (GH 12021)

  • Float64Inde/Int64Index 转换为 Int64Index 时的 .astype() 错误 (GH 12881)

  • 在使用 orient='index' (默认值) 在 .to_json()/.read_json() 中往返整数索引时出错 (GH 12866)

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

  • 与 >= numpy 1.11 版本的兼容性,用于 NaT 比较 (GH 12969)

  • 使用非唯一的 MultiIndex 调用 .drop() 时的错误。(GH 12701)

  • 时区感知和时区无关 DataFrame 的 .concat 错误 (GH 12467)

  • .resample(..).fillna(..) 中传递非字符串参数时未正确引发 ValueError 的错误 (GH 12952)

  • pd.read_sas() 中各种编码和标题处理问题的错误修复 (GH 12659, GH 12654, GH 12647, GH 12809)

  • pd.crosstab() 中的错误:当 values=None 时会静默忽略 aggfunc (GH 12569)。

  • 在序列化 datetime.timeDataFrame.to_json 中潜在的段错误 (GH 11473)。

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

  • 尝试序列化非 ndarray 值的 DataFrameSeriesto_json 中的段错误;现在支持序列化 categorysparse 和时区感知的 datetime64[ns, tz] 数据类型 (GH 10778)。

  • 不支持的数据类型未传递给默认处理器时 DataFrame.to_json 中的错误 (GH 12554)。

  • .align 未返回子类的错误 (GH 12983)

  • SeriesDataFrame 对齐时出错 (GH 13037)

  • ABCPanel 中的错误:Panel4D 未被视为此泛型类型的有效实例 (GH 12810)

  • .groupby(..).apply(..) 情况下 .name 的一致性错误 (GH 12363)

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

  • Timedelta.minTimedelta.max 中的错误,现在属性报告 pandas 识别的真正最小/最大 timedeltas。请参阅文档。(GH 12727)

  • 使用插值调用 .quantile() 时可能会意外地强制转换为 float 的错误 (GH 12772)

  • 空的 Series 调用 .quantile() 可能会返回标量而不是空的 Series 的错误 (GH 12772)

  • .loc 中的错误:大型索引器中的越界访问会引发 IndexError 而不是 KeyError (GH 12527)

  • 使用 TimedeltaIndex.asfreq() 进行重采样时,此前不会包含最后一个时间点的错误 (GH 12926)

  • DataFrame 中与 Categorical 进行相等性测试时出错 (GH 12564)

  • 使用 TimeGrouper 时,GroupBy.first().last() 返回错误的行 (GH 7453)

  • 使用 c 引擎并指定包含带引号项中换行的 skiprows 时,pd.read_csv() 中的错误 (GH 10911, GH 12775)

  • 对齐赋值时,时区感知的日期时间 Series 的时区信息丢失的 DataFrame 错误 (GH 12981)

  • .value_counts() 中的错误:当 normalize=Truedropna=True 时,空值仍计入归一化计数 (GH 12558)

  • Series.value_counts() 如果数据类型是 category,则名称丢失 (GH 12835)

  • Series.value_counts() 时区信息丢失 (GH 12835)

  • 使用 Categorical 调用 Series.value_counts(normalize=True) 时引发 UnboundLocalError 的错误 (GH 12835)

  • Panel.fillna() 忽略 inplace=True 的错误 (GH 12633)

  • 使用 c 引擎并同时指定 names, usecols, 和 parse_dates 时,pd.read_csv() 中的错误 (GH 9755)

  • 使用 c 引擎并同时指定 delim_whitespace=Truelineterminator 时,pd.read_csv() 中的错误 (GH 12912)

  • Series.rename, DataFrame.renameDataFrame.rename_axis 未将 Series 视为重新标记的映射的错误 (GH 12623)。

  • 改进了 .rolling.min.rolling.max 中的数据类型处理 (GH 12373)

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

  • 如果数据类型是 category 或时区感知日期时间,则 Series.map 引发 TypeError 的错误 (GH 12473)

  • 在 32 位平台上进行某些测试比较时出错 (GH 12972)

  • RangeIndex 构造回退时索引强制转换中的错误 (GH 12893)

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

  • 对定义为返回子类化 Series 的子类化 DataFrame 进行切片时可能会返回正常的 Series 的错误 (GH 11559)

  • 如果输入具有 name 且结果是 DataFrameMultiIndex,则 .str 访问器方法可能引发 ValueError 的错误 (GH 12617)

  • 在空 DataFrame 上的 DataFrame.last_valid_index()DataFrame.first_valid_index() 错误 (GH 12800)

  • CategoricalIndex.get_loc 返回与普通 Index 不同的结果的错误 (GH 12531)

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

  • date_range closed 关键字和时区错误 (GH 12684)。

  • 当输入数据包含时区感知日期时间和时间差时,pd.concat 引发 AttributeError 的错误 (GH 12620)

  • pd.concat 未正确处理空的 Series 的错误 (GH 11082)

  • 指定整数 width 时,.plot.bar 对齐错误 (GH 12979)

  • 如果二元运算符的参数是常量,则 fill_value 被忽略的错误 (GH 12723)

  • 使用 bs4 解析器且解析的表格有标题但只有一列时,pd.read_html() 中的错误 (GH 9178)

  • .pivot_table 中的错误:当 margins=Truedropna=True 时,空值仍计入边际计数 (GH 12577)

  • .pivot_table 中的错误:当 dropna=False 时,表索引/列名消失 (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)

  • pd.to_numeric() 中,当输入为 Index 时,返回 np.ndarray 而不是 Index 的 Bug (GH 12777)

  • pd.to_numeric() 中,当输入为日期时间类型时,可能引发 TypeError 的 Bug (GH 12777)

  • pd.to_numeric() 中,当输入为标量时,引发 ValueError 的 Bug (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 +