版本 0.19.0 (2016 年 10 月 2 日)#

这是从 0.18.1 版本开始的一个主要版本,包含多项 API 变更、若干新功能、增强功能、性能改进以及大量的错误修复。我们建议所有用户升级到此版本。

主要亮点包括

  • 用于 asof 风格时间序列连接的 merge_asof() 函数,请参见此处

  • .rolling() 现在支持时间序列,请参见此处

  • read_csv() 现在支持解析 Categorical 数据,请参见此处

  • 已添加 union_categorical() 函数用于组合分类数据,请参见此处

  • PeriodIndex 现在拥有其自身的 period 数据类型,并已更改为与其它 Index 类更一致。请参见此处

  • 稀疏数据结构增强了对 intbool 数据类型的支持,请参见此处

  • Series 的比较操作不再忽略索引,有关 API 变更的概述,请参见此处

  • 引入了用于实用函数的 pandas 开发 API,请参见此处

  • Panel4DPanelND 已弃用。我们建议使用 xarray 包来表示这些类型的 n 维数据。

  • 移除了之前已弃用的模块 pandas.io.datapandas.io.wbpandas.tools.rplot

警告

pandas >= 0.19.0 在导入时将不再抑制 numpy ufunc 警告,请参见此处

新特性#

merge_asof 函数用于 asof 风格时间序列连接#

已通过 merge_asof() 函数添加了一项长期以来需求的功能,以支持 asof 风格的时间序列连接(GH 1870GH 13695GH 13709GH 13902)。完整文档请参见此处

merge_asof() 执行 asof 合并,这类似于左连接,但我们匹配最接近的键而不是相等的键。

In [1]: left = pd.DataFrame({"a": [1, 5, 10], "left_val": ["a", "b", "c"]})

In [2]: right = pd.DataFrame({"a": [1, 2, 3, 6, 7], "right_val": [1, 2, 3, 6, 7]})

In [3]: left
Out[3]: 
    a left_val
0   1        a
1   5        b
2  10        c

[3 rows x 2 columns]

In [4]: right
Out[4]: 
   a  right_val
0  1          1
1  2          2
2  3          3
3  6          6
4  7          7

[5 rows x 2 columns]

我们通常希望在可能时精确匹配,否则使用最近的值。

In [5]: pd.merge_asof(left, right, on="a")
Out[5]: 
    a left_val  right_val
0   1        a          1
1   5        b          3
2  10        c          7

[3 rows x 3 columns]

我们也可以只匹配之前的数据行,而不是精确匹配。

In [6]: pd.merge_asof(left, right, on="a", allow_exact_matches=False)
Out[6]: 
    a left_val  right_val
0   1        a        NaN
1   5        b        3.0
2  10        c        7.0

[3 rows x 3 columns]

在一个典型的时间序列示例中,我们有 tradesquotes,我们想对它们进行 asof-join。这还说明了如何使用 by 参数在合并前对数据进行分组。

In [7]: trades = pd.DataFrame(
   ...:     {
   ...:         "time": pd.to_datetime(
   ...:             [
   ...:                 "20160525 13:30:00.023",
   ...:                 "20160525 13:30:00.038",
   ...:                 "20160525 13:30:00.048",
   ...:                 "20160525 13:30:00.048",
   ...:                 "20160525 13:30:00.048",
   ...:             ]
   ...:         ),
   ...:         "ticker": ["MSFT", "MSFT", "GOOG", "GOOG", "AAPL"],
   ...:         "price": [51.95, 51.95, 720.77, 720.92, 98.00],
   ...:         "quantity": [75, 155, 100, 100, 100],
   ...:     },
   ...:     columns=["time", "ticker", "price", "quantity"],
   ...: )
   ...: 

In [8]: quotes = pd.DataFrame(
   ...:     {
   ...:         "time": pd.to_datetime(
   ...:             [
   ...:                 "20160525 13:30:00.023",
   ...:                 "20160525 13:30:00.023",
   ...:                 "20160525 13:30:00.030",
   ...:                 "20160525 13:30:00.041",
   ...:                 "20160525 13:30:00.048",
   ...:                 "20160525 13:30:00.049",
   ...:                 "20160525 13:30:00.072",
   ...:                 "20160525 13:30:00.075",
   ...:             ]
   ...:         ),
   ...:         "ticker": ["GOOG", "MSFT", "MSFT", "MSFT", "GOOG", "AAPL", "GOOG", "MSFT"],
   ...:         "bid": [720.50, 51.95, 51.97, 51.99, 720.50, 97.99, 720.50, 52.01],
   ...:         "ask": [720.93, 51.96, 51.98, 52.00, 720.93, 98.01, 720.88, 52.03],
   ...:     },
   ...:     columns=["time", "ticker", "bid", "ask"],
   ...: )
   ...: 
In [9]: trades
Out[9]: 
                     time ticker   price  quantity
0 2016-05-25 13:30:00.023   MSFT   51.95        75
1 2016-05-25 13:30:00.038   MSFT   51.95       155
2 2016-05-25 13:30:00.048   GOOG  720.77       100
3 2016-05-25 13:30:00.048   GOOG  720.92       100
4 2016-05-25 13:30:00.048   AAPL   98.00       100

[5 rows x 4 columns]

In [10]: quotes
Out[10]: 
                     time ticker     bid     ask
0 2016-05-25 13:30:00.023   GOOG  720.50  720.93
1 2016-05-25 13:30:00.023   MSFT   51.95   51.96
2 2016-05-25 13:30:00.030   MSFT   51.97   51.98
3 2016-05-25 13:30:00.041   MSFT   51.99   52.00
4 2016-05-25 13:30:00.048   GOOG  720.50  720.93
5 2016-05-25 13:30:00.049   AAPL   97.99   98.01
6 2016-05-25 13:30:00.072   GOOG  720.50  720.88
7 2016-05-25 13:30:00.075   MSFT   52.01   52.03

[8 rows x 4 columns]

asof 合并基于 on 字段进行连接,该字段通常是日期时间类型,并且是排序的,在这种情况下,我们使用 by 字段中的分组器。这类似于左外连接,只是会自动发生前向填充,取最近的非 NaN 值。

In [11]: pd.merge_asof(trades, quotes, on="time", by="ticker")
Out[11]: 
                     time ticker   price  quantity     bid     ask
0 2016-05-25 13:30:00.023   MSFT   51.95        75   51.95   51.96
1 2016-05-25 13:30:00.038   MSFT   51.95       155   51.97   51.98
2 2016-05-25 13:30:00.048   GOOG  720.77       100  720.50  720.93
3 2016-05-25 13:30:00.048   GOOG  720.92       100  720.50  720.93
4 2016-05-25 13:30:00.048   AAPL   98.00       100     NaN     NaN

[5 rows x 6 columns]

这会返回一个合并后的 DataFrame,其中的条目顺序与原始左侧传入的 DataFrame(本例中为 trades)相同,并合并了 quotes 的字段。

.rolling() 方法现在支持时间序列#

.rolling() 对象现在支持时间序列,并且可以在 window 参数中接受时间序列偏移量(或可转换类型)(GH 13327GH 12995)。完整文档请参见此处

In [12]: dft = pd.DataFrame(
   ....:     {"B": [0, 1, 2, np.nan, 4]},
   ....:     index=pd.date_range("20130101 09:00:00", periods=5, freq="s"),
   ....: )
   ....: 

In [13]: dft
Out[13]: 
                       B
2013-01-01 09:00:00  0.0
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  2.0
2013-01-01 09:00:03  NaN
2013-01-01 09:00:04  4.0

[5 rows x 1 columns]

这是一个规则频率索引。使用整数窗口参数可以按窗口频率进行滚动。

In [14]: dft.rolling(2).sum()
Out[14]: 
                       B
2013-01-01 09:00:00  NaN
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  3.0
2013-01-01 09:00:03  NaN
2013-01-01 09:00:04  NaN

[5 rows x 1 columns]

In [15]: dft.rolling(2, min_periods=1).sum()
Out[15]: 
                       B
2013-01-01 09:00:00  0.0
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  3.0
2013-01-01 09:00:03  2.0
2013-01-01 09:00:04  4.0

[5 rows x 1 columns]

指定偏移量允许更直观地指定滚动频率。

In [16]: dft.rolling("2s").sum()
Out[16]: 
                       B
2013-01-01 09:00:00  0.0
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  3.0
2013-01-01 09:00:03  2.0
2013-01-01 09:00:04  4.0

[5 rows x 1 columns]

使用非规则但仍单调的索引,使用整数窗口进行滚动不会产生任何特殊计算。

In [17]: dft = pd.DataFrame(
   ....:     {"B": [0, 1, 2, np.nan, 4]},
   ....:     index=pd.Index(
   ....:         [
   ....:             pd.Timestamp("20130101 09:00:00"),
   ....:             pd.Timestamp("20130101 09:00:02"),
   ....:             pd.Timestamp("20130101 09:00:03"),
   ....:             pd.Timestamp("20130101 09:00:05"),
   ....:             pd.Timestamp("20130101 09:00:06"),
   ....:         ],
   ....:         name="foo",
   ....:     ),
   ....: )
   ....: 

In [18]: dft
Out[18]: 
                       B
foo                     
2013-01-01 09:00:00  0.0
2013-01-01 09:00:02  1.0
2013-01-01 09:00:03  2.0
2013-01-01 09:00:05  NaN
2013-01-01 09:00:06  4.0

[5 rows x 1 columns]

In [19]: dft.rolling(2).sum()
Out[19]: 
                       B
foo                     
2013-01-01 09:00:00  NaN
2013-01-01 09:00:02  1.0
2013-01-01 09:00:03  3.0
2013-01-01 09:00:05  NaN
2013-01-01 09:00:06  NaN

[5 rows x 1 columns]

使用时间规范为此稀疏数据生成可变窗口。

In [20]: dft.rolling("2s").sum()
Out[20]: 
                       B
foo                     
2013-01-01 09:00:00  0.0
2013-01-01 09:00:02  1.0
2013-01-01 09:00:03  3.0
2013-01-01 09:00:05  NaN
2013-01-01 09:00:06  4.0

[5 rows x 1 columns]

此外,我们现在允许一个可选的 on 参数来指定 DataFrame 中的列(而不是索引的默认值)。

In [21]: dft = dft.reset_index()

In [22]: dft
Out[22]: 
                  foo    B
0 2013-01-01 09:00:00  0.0
1 2013-01-01 09:00:02  1.0
2 2013-01-01 09:00:03  2.0
3 2013-01-01 09:00:05  NaN
4 2013-01-01 09:00:06  4.0

[5 rows x 2 columns]

In [23]: dft.rolling("2s", on="foo").sum()
Out[23]: 
                  foo    B
0 2013-01-01 09:00:00  0.0
1 2013-01-01 09:00:02  1.0
2 2013-01-01 09:00:03  3.0
3 2013-01-01 09:00:05  NaN
4 2013-01-01 09:00:06  4.0

[5 rows x 2 columns]

read_csv 方法改进了对重复列名的支持#

read_csv() 现在支持重复列名,无论它们是在文件中还是作为 names 参数传入(GH 7160GH 9424

In [24]: data = "0,1,2\n3,4,5"

In [25]: names = ["a", "b", "a"]

之前行为:

In [2]: pd.read_csv(StringIO(data), names=names)
Out[2]:
   a  b  a
0  2  1  2
1  5  4  5

第一个 a 列包含的数据与第二个 a 列相同,而它应该包含值 [0, 3]

新行为:

In [26]: pd.read_csv(StringIO(data), names=names)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[26], line 1
----> 1 pd.read_csv(StringIO(data), names=names)

File ~/work/pandas/pandas/pandas/io/parsers/readers.py:1026, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)
   1013 kwds_defaults = _refine_defaults_read(
   1014     dialect,
   1015     delimiter,
   (...)
   1022     dtype_backend=dtype_backend,
   1023 )
   1024 kwds.update(kwds_defaults)
-> 1026 return _read(filepath_or_buffer, kwds)

File ~/work/pandas/pandas/pandas/io/parsers/readers.py:617, in _read(filepath_or_buffer, kwds)
    614 nrows = kwds.get("nrows", None)
    616 # Check for duplicates in names.
--> 617 _validate_names(kwds.get("names", None))
    619 # Create the parser.
    620 parser = TextFileReader(filepath_or_buffer, **kwds)

File ~/work/pandas/pandas/pandas/io/parsers/readers.py:576, in _validate_names(names)
    574 if names is not None:
    575     if len(names) != len(set(names)):
--> 576         raise ValueError("Duplicate names are not allowed.")
    577     if not (
    578         is_list_like(names, allow_sets=False) or isinstance(names, abc.KeysView)
    579     ):
    580         raise ValueError("Names should be an ordered collection.")

ValueError: Duplicate names are not allowed.

read_csv 方法支持直接解析 Categorical#

read_csv() 函数现在支持在指定数据类型时解析 Categorical 列(GH 10153)。根据数据结构的不同,这可以比解析后转换为 Categorical 更快地解析时间并降低内存使用。请参见 I/O 文档此处

In [27]: data = """
   ....: col1,col2,col3
   ....: a,b,1
   ....: a,b,2
   ....: c,d,3
   ....: """
   ....: 

In [28]: pd.read_csv(StringIO(data))
Out[28]: 
  col1 col2  col3
0    a    b     1
1    a    b     2
2    c    d     3

[3 rows x 3 columns]

In [29]: pd.read_csv(StringIO(data)).dtypes
Out[29]: 
col1    object
col2    object
col3     int64
Length: 3, dtype: object

In [30]: pd.read_csv(StringIO(data), dtype="category").dtypes
Out[30]: 
col1    category
col2    category
col3    category
Length: 3, dtype: object

可以使用字典规范将单个列解析为 Categorical

In [31]: pd.read_csv(StringIO(data), dtype={"col1": "category"}).dtypes
Out[31]: 
col1    category
col2      object
col3       int64
Length: 3, dtype: object

注意

结果类别将始终解析为字符串(对象数据类型)。如果类别是数字,可以使用 to_numeric() 函数进行转换,或者根据需要使用其他转换器,如 to_datetime()

In [32]: df = pd.read_csv(StringIO(data), dtype="category")

In [33]: df.dtypes
Out[33]: 
col1    category
col2    category
col3    category
Length: 3, dtype: object

In [34]: df["col3"]
Out[34]: 
0    1
1    2
2    3
Name: col3, Length: 3, dtype: category
Categories (3, object): ['1', '2', '3']

In [35]: new_categories = pd.to_numeric(df["col3"].cat.categories)

In [36]: df["col3"] = df["col3"].cat.rename_categories(new_categories)

In [37]: df["col3"]
Out[37]: 
0    1
1    2
2    3
Name: col3, Length: 3, dtype: category
Categories (3, int64): [1, 2, 3]

分类数据拼接#

  • 已添加 union_categoricals() 函数用于组合分类数据,请参见分类数据联合GH 13361GH 13763GH 13846GH 14173

    In [38]: from pandas.api.types import union_categoricals
    
    In [39]: a = pd.Categorical(["b", "c"])
    
    In [40]: b = pd.Categorical(["a", "b"])
    
    In [41]: union_categoricals([a, b])
    Out[41]: 
    ['b', 'c', 'a', 'b']
    Categories (3, object): ['b', 'c', 'a']
    
  • concatappend 现在可以将具有不同 categoriescategory 数据类型拼接为 object 数据类型(GH 13524

    In [42]: s1 = pd.Series(["a", "b"], dtype="category")
    
    In [43]: s2 = pd.Series(["b", "c"], dtype="category")
    

之前行为:

In [1]: pd.concat([s1, s2])
ValueError: incompatible categories in categorical concat

新行为:

In [44]: pd.concat([s1, s2])
Out[44]: 
0    a
1    b
0    b
1    c
Length: 4, dtype: object

半月偏移量#

pandas 增加了新的频率偏移量,SemiMonthEnd ('SM') 和 SemiMonthBegin ('SMS')。它们分别提供了默认锚定到每月 15 日和月末,以及每月 15 日和月初的日期偏移量。(GH 1543

In [45]: from pandas.tseries.offsets import SemiMonthEnd, SemiMonthBegin

半月结束:

In [46]: pd.Timestamp("2016-01-01") + SemiMonthEnd()
Out[46]: Timestamp('2016-01-15 00:00:00')

In [47]: pd.date_range("2015-01-01", freq="SM", periods=4)
Out[47]: DatetimeIndex(['2015-01-15', '2015-01-31', '2015-02-15', '2015-02-28'], dtype='datetime64[ns]', freq='SM-15')

半月开始:

In [46]: pd.Timestamp("2016-01-01") + SemiMonthBegin()
Out[46]: Timestamp('2016-01-15 00:00:00')

In [47]: pd.date_range("2015-01-01", freq="SMS", periods=4)
Out[47]: DatetimeIndex(['2015-01-01', '2015-01-15', '2015-02-01', '2015-02-15'], dtype='datetime64[ns]', freq='SMS-15')

使用锚定后缀,您还可以指定要使用的月份日期,而不是 15 日。

In [50]: pd.date_range("2015-01-01", freq="SMS-16", periods=4)
Out[50]: DatetimeIndex(['2015-01-01', '2015-01-16', '2015-02-01', '2015-02-16'], dtype='datetime64[ns]', freq='SMS-16')

In [51]: pd.date_range("2015-01-01", freq="SM-14", periods=4)
Out[51]: DatetimeIndex(['2015-01-14', '2015-01-31', '2015-02-14', '2015-02-28'], dtype='datetime64[ns]', freq='SM-14')

新索引方法#

以下方法和选项已添加到 Index 中,以使其与 SeriesDataFrame API 更加一致。

Index 现在支持用于相同形状索引的 .where() 函数(GH 13170

In [48]: idx = pd.Index(["a", "b", "c"])

In [49]: idx.where([True, False, True])
Out[49]: Index(['a', None, 'c'], dtype='object')

Index 现在支持 .dropna() 以排除缺失值(GH 6194

In [50]: idx = pd.Index([1, 2, np.nan, 4])

In [51]: idx.dropna()
Out[51]: Index([1.0, 2.0, 4.0], dtype='float64')

对于 MultiIndex,默认情况下,如果任何级别缺失,则会删除值。指定 how='all' 仅在所有级别都缺失时删除值。

In [52]: midx = pd.MultiIndex.from_arrays([[1, 2, np.nan, 4], [1, 2, np.nan, np.nan]])

In [53]: midx
Out[53]: 
MultiIndex([(1.0, 1.0),
            (2.0, 2.0),
            (nan, nan),
            (4.0, nan)],
           )

In [54]: midx.dropna()
Out[54]: 
MultiIndex([(1, 1),
            (2, 2)],
           )

In [55]: midx.dropna(how="all")
Out[55]: 
MultiIndex([(1, 1.0),
            (2, 2.0),
            (4, nan)],
           )

Index 现在支持 .str.extractall(),它返回一个 DataFrame,请参见此处文档GH 10008GH 13156

In [56]: idx = pd.Index(["a1a2", "b1", "c1"])

In [57]: idx.str.extractall(r"[ab](?P<digit>\d)")
Out[57]: 
        digit
  match      
0 0         1
  1         2
1 0         1

[3 rows x 1 columns]

Index.astype() 现在接受一个可选的布尔参数 copy,如果满足数据类型要求,则允许可选复制(GH 13209

Google BigQuery 增强功能#

  • read_gbq() 方法已添加 dialect 参数,允许用户指定是使用 BigQuery 的旧版 SQL 还是 BigQuery 的标准 SQL。更多详细信息请参见文档GH 13615)。

  • to_gbq() 方法现在允许 DataFrame 列顺序与目标表模式不同(GH 11359)。

细粒度 NumPy 错误状态#

以前版本的 pandas 在导入 pandas 时会永久禁用 numpy 的 ufunc 错误处理。pandas 这样做是为了抑制在使用 numpy ufuncs 处理缺失数据(通常表示为 NaN)时可能出现的警告。不幸的是,这会抑制应用程序中非 pandas 代码中出现的合法警告。从 0.19.0 开始,pandas 将使用 numpy.errstate 上下文管理器,以更细粒度的方式抑制这些警告,只在 pandas 代码库中实际使用这些操作时才进行抑制。(GH 13109GH 13145

升级 pandas 后,您可能会看到代码中发出新的 RuntimeWarnings。这些警告很可能是合法的,并且其根本原因在使用之前版本的 pandas 时就已经存在,只是当时警告被抑制了。请在 RuntimeWarning 的来源处使用 numpy.errstate 来控制如何处理这些情况。

get_dummies 方法现在返回整数数据类型#

pd.get_dummies 函数现在将独热编码的列作为小整数返回,而不是浮点数(GH 8725)。这应该会改善内存占用。

之前行为:

In [1]: pd.get_dummies(['a', 'b', 'a', 'c']).dtypes

Out[1]:
a    float64
b    float64
c    float64
dtype: object

新行为:

In [58]: pd.get_dummies(["a", "b", "a", "c"]).dtypes
Out[58]: 
a    bool
b    bool
c    bool
Length: 3, dtype: object

to_numeric 中将值下转换为最小可能的数据类型#

pd.to_numeric() 现在接受一个 downcast 参数,如果可能,它将数据下转换为最小的指定数值数据类型(GH 13352

In [59]: s = ["1", 2, 3]

In [60]: pd.to_numeric(s, downcast="unsigned")
Out[60]: array([1, 2, 3], dtype=uint8)

In [61]: pd.to_numeric(s, downcast="integer")
Out[61]: array([1, 2, 3], dtype=int8)

pandas 开发 API#

作为未来使 pandas API 更统一和易于访问的一部分,我们创建了一个标准的 pandas 子包 pandas.api 来存放公共 API。我们首先在 pandas.api.types 中公开类型自省函数。更多子包和官方认可的 API 将在未来版本的 pandas 中发布(GH 13147GH 13634

以下现在是此 API 的一部分

In [62]: import pprint

In [63]: from pandas.api import types

In [64]: funcs = [f for f in dir(types) if not f.startswith("_")]

In [65]: pprint.pprint(funcs)
['CategoricalDtype',
 'DatetimeTZDtype',
 'IntervalDtype',
 'PeriodDtype',
 'infer_dtype',
 'is_any_real_numeric_dtype',
 'is_array_like',
 'is_bool',
 'is_bool_dtype',
 'is_categorical_dtype',
 'is_complex',
 'is_complex_dtype',
 'is_datetime64_any_dtype',
 'is_datetime64_dtype',
 'is_datetime64_ns_dtype',
 'is_datetime64tz_dtype',
 'is_dict_like',
 'is_dtype_equal',
 'is_extension_array_dtype',
 'is_file_like',
 'is_float',
 'is_float_dtype',
 'is_hashable',
 'is_int64_dtype',
 'is_integer',
 'is_integer_dtype',
 'is_interval',
 'is_interval_dtype',
 'is_iterator',
 'is_list_like',
 'is_named_tuple',
 'is_number',
 'is_numeric_dtype',
 'is_object_dtype',
 'is_period_dtype',
 'is_re',
 'is_re_compilable',
 'is_scalar',
 'is_signed_integer_dtype',
 'is_sparse',
 'is_string_dtype',
 'is_timedelta64_dtype',
 'is_timedelta64_ns_dtype',
 'is_unsigned_integer_dtype',
 'pandas_dtype',
 'union_categoricals']

注意

从内部模块 pandas.core.common 调用这些函数现在将显示 DeprecationWarningGH 13990

其他增强功能#

  • Timestamp 现在可以接受类似于 datetime.datetime() 的位置和关键字参数(GH 10758GH 11630

    In [66]: pd.Timestamp(2012, 1, 1)
    Out[66]: Timestamp('2012-01-01 00:00:00')
    
    In [67]: pd.Timestamp(year=2012, month=1, day=1, hour=8, minute=30)
    Out[67]: Timestamp('2012-01-01 08:30:00')
    
  • .resample() 函数现在接受 on=level= 参数,用于对类日期时间列或 MultiIndex 级别进行重采样(GH 13500

    In [68]: df = pd.DataFrame(
       ....:     {"date": pd.date_range("2015-01-01", freq="W", periods=5), "a": np.arange(5)},
       ....:     index=pd.MultiIndex.from_arrays(
       ....:         [[1, 2, 3, 4, 5], pd.date_range("2015-01-01", freq="W", periods=5)],
       ....:         names=["v", "d"],
       ....:     ),
       ....: )
       ....: 
    
    In [69]: df
    Out[69]: 
                       date  a
    v d                       
    1 2015-01-04 2015-01-04  0
    2 2015-01-11 2015-01-11  1
    3 2015-01-18 2015-01-18  2
    4 2015-01-25 2015-01-25  3
    5 2015-02-01 2015-02-01  4
    
    [5 rows x 2 columns]
    
    In [74]: df.resample("M", on="date")[["a"]].sum()
    Out[74]:
                a
    date
    2015-01-31  6
    2015-02-28  4
    
    [2 rows x 1 columns]
    
    In [75]: df.resample("M", level="d")[["a"]].sum()
    Out[75]:
                a
    d
    2015-01-31  6
    2015-02-28  4
    
    [2 rows x 1 columns]
    
  • GbqConnector.get_credentials() 方法现在可以首先尝试获取应用程序默认凭据。更多详细信息请参见文档(GH 13577)。

  • DatetimeIndexTimestamp.tz_localize() 方法新增了 errors 关键字,因此您可以将不存在的时间戳强制转换为 NaT。默认行为仍然是引发 NonExistentTimeErrorGH 13057

  • .to_hdf/read_hdf() 现在接受文件路径的路径对象(例如 pathlib.Pathpy.path.local)(GH 11773

  • pd.read_csv() 使用 engine='python' 现在支持 decimalGH 12933)、na_filterGH 13321)和 memory_map 选项(GH 13381)。

  • 与 Python API 一致,pd.read_csv() 现在会将 +inf 解释为正无穷大(GH 13274

  • pd.read_html() 现在支持 na_valuesconverterskeep_default_na 选项(GH 13461

  • Categorical.astype() 现在接受一个可选的布尔参数 copy,当数据类型是分类时生效(GH 13209

  • DataFrame 新增了 .asof() 方法,根据所选子集返回最后一个非 NaN 值(GH 13358

  • 如果传入 OrderedDict 对象的列表,DataFrame 构造函数现在将尊重键的顺序(GH 13304

  • pd.read_html() 现在支持 decimal 选项(GH 12907

  • Series 新增了 .is_monotonic.is_monotonic_increasing.is_monotonic_decreasing 属性,类似于 IndexGH 13336

  • DataFrame.to_sql() 现在允许为所有列指定单个 SQL 类型值(GH 11886)。

  • Series.append 现在支持 ignore_index 选项(GH 13677

  • .to_stata()StataWriter 现在可以使用字典将列名映射到标签,从而将变量标签写入 Stata dta 文件(GH 13535GH 13536

  • .to_stata()StataWriter 现在将自动把 datetime64[ns] 列转换为 Stata 格式 %tc,而不是引发 ValueErrorGH 12259

  • read_stata()StataReader 在读取带有重复值标签的 Stata 文件且 convert_categoricals=True 时,会引发更明确的错误消息(GH 13923

  • DataFrame.style 现在将渲染稀疏化的 MultiIndexes(GH 11655

  • DataFrame.style 现在将显示列级别名称(例如 DataFrame.columns.names)(GH 13775

  • DataFrame 增加了根据行中的值使用 df.sort_values(by='...', axis=1) 对列进行重新排序的支持(GH 10806

    In [70]: df = pd.DataFrame({"A": [2, 7], "B": [3, 5], "C": [4, 8]}, index=["row1", "row2"])
    
    In [71]: df
    Out[71]: 
          A  B  C
    row1  2  3  4
    row2  7  5  8
    
    [2 rows x 3 columns]
    
    In [72]: df.sort_values(by="row2", axis=1)
    Out[72]: 
          B  A  C
    row1  3  2  4
    row2  5  7  8
    
    [2 rows x 3 columns]
    
  • I/O 文档中添加了关于读取混合数据类型列的危险以及如何处理的说明(GH 13746

  • to_html() 现在有一个 border 参数来控制开头 <table> 标签中的值。默认值是 html.border 选项的值,该选项默认为 1。这也会影响 Notebook 的 HTML 表示,但由于 Jupyter 的 CSS 包含 `border-width` 属性,视觉效果是相同的。(GH 11563)。

  • 当未安装 sqlalchemy 且使用了连接字符串时,SQL 函数中会引发 ImportErrorGH 11920)。

  • 与 matplotlib 2.0 的兼容性。旧版本的 pandas 也应与 matplotlib 2.0 兼容(GH 13333

  • TimestampPeriodDatetimeIndexPeriodIndex.dt 访问器新增了 .is_leap_year 属性,用于检查日期是否属于闰年。(GH 13727

  • astype() 现在将接受一个列名到数据类型映射的字典作为 dtype 参数。(GH 12086

  • pd.read_jsonDataFrame.to_json 现在支持使用 lines 选项读取和写入 JSON 行,请参见行分隔 JSONGH 9180

  • read_excel() 现在支持 true_valuesfalse_values 关键字参数(GH 13347

  • groupby() 现在接受标量和单元素列表,用于在非 MultiIndex 分组器上指定级别。(GH 13907

  • Excel 日期列中不可转换的日期将不进行转换直接返回,且该列的数据类型将为 object,而不是引发异常(GH 10001)。

  • pd.Timedelta(None) 现在被接受并返回 NaT,与 pd.Timestamp 一致(GH 13687

  • pd.read_stata() 现在可以处理一些格式为 111 的文件,这些文件是 SAS 在生成 Stata dta 文件时产生的(GH 11526

  • SeriesIndex 现在支持 divmod,它将返回一个 series 或 indices 的元组。这在广播规则方面表现得像一个标准的二元运算符(GH 14208)。

API 变更#

Series.tolist() 现在将返回 Python 类型#

Series.tolist() 现在将在输出中返回 Python 类型,模仿 NumPy 的 .tolist() 行为(GH 10904

In [73]: s = pd.Series([1, 2, 3])

之前行为:

In [7]: type(s.tolist()[0])
Out[7]:
 <class 'numpy.int64'>

新行为:

In [74]: type(s.tolist()[0])
Out[74]: int

不同索引的 Series 运算符#

以下 Series 运算符已更改,以使所有运算符保持一致,包括 DataFrameGH 1134GH 4581GH 13538

  • Series 比较运算符在 index 不同时现在会引发 ValueError

  • Series 逻辑运算符将左侧和右侧的两个 index 对齐。

警告

在 0.18.1 版本之前,比较相同长度的 Series 即使 .index 不同也会成功(结果忽略 .index)。从 0.19.0 开始,这会引发 ValueError 以更加严格。本节还描述了如何使用 `.eq` 等灵活的比较方法来保持之前的行为或对齐不同的索引。

因此,SeriesDataFrame 运算符的行为如下

算术运算符#

算术运算符会使两个 index 对齐(无变化)。

In [75]: s1 = pd.Series([1, 2, 3], index=list("ABC"))

In [76]: s2 = pd.Series([2, 2, 2], index=list("ABD"))

In [77]: s1 + s2
Out[77]: 
A    3.0
B    4.0
C    NaN
D    NaN
Length: 4, dtype: float64

In [78]: df1 = pd.DataFrame([1, 2, 3], index=list("ABC"))

In [79]: df2 = pd.DataFrame([2, 2, 2], index=list("ABD"))

In [80]: df1 + df2
Out[80]: 
     0
A  3.0
B  4.0
C  NaN
D  NaN

[4 rows x 1 columns]

比较运算符#

比较运算符在 .index 不同时会引发 ValueError

之前的行为Series

Series 在长度相同时比较值,忽略 .index

In [1]: s1 == s2
Out[1]:
A    False
B     True
C    False
dtype: bool

新行为Series

In [2]: s1 == s2
Out[2]:
ValueError: Can only compare identically-labeled Series objects

注意

要达到与之前版本相同的结果(根据位置比较值,忽略 .index),请比较两个 .values

In [81]: s1.values == s2.values
Out[81]: array([False,  True, False])

如果您想比较 Series 并对齐其 .index,请参见下面的灵活比较方法部分

In [82]: s1.eq(s2)
Out[82]: 
A    False
B     True
C    False
D    False
Length: 4, dtype: bool

当前行为DataFrame,无变化)

In [3]: df1 == df2
Out[3]:
ValueError: Can only compare identically-labeled DataFrame objects

逻辑运算符#

逻辑运算符将左侧和右侧的两个 .index 对齐。

之前的行为Series),只保留左侧索引

In [4]: s1 = pd.Series([True, False, True], index=list('ABC'))
In [5]: s2 = pd.Series([True, True, True], index=list('ABD'))
In [6]: s1 & s2
Out[6]:
A     True
B    False
C    False
dtype: bool

新行为Series

In [83]: s1 = pd.Series([True, False, True], index=list("ABC"))

In [84]: s2 = pd.Series([True, True, True], index=list("ABD"))

In [85]: s1 & s2
Out[85]: 
A     True
B    False
C    False
D    False
Length: 4, dtype: bool

注意

Series 逻辑运算符用 False 填充 NaN 结果。

注意

要达到与之前版本相同的结果(仅根据左侧索引比较值),可以使用 reindex_like

In [86]: s1 & s2.reindex_like(s1)
Out[86]: 
A     True
B    False
C    False
Length: 3, dtype: bool

当前行为DataFrame,无变化)

In [87]: df1 = pd.DataFrame([True, False, True], index=list("ABC"))

In [88]: df2 = pd.DataFrame([True, True, True], index=list("ABD"))

In [89]: df1 & df2
Out[89]: 
       0
A   True
B  False
C  False
D  False

[4 rows x 1 columns]

灵活的比较方法#

Series 的灵活比较方法,如 eqneleltgegt,现在会使两个 index 对齐。如果您想比较两个索引不同的 Series,请使用这些运算符。

In [90]: s1 = pd.Series([1, 2, 3], index=["a", "b", "c"])

In [91]: s2 = pd.Series([2, 2, 2], index=["b", "c", "d"])

In [92]: s1.eq(s2)
Out[92]: 
a    False
b     True
c    False
d    False
Length: 4, dtype: bool

In [93]: s1.ge(s2)
Out[93]: 
a    False
b     True
c     True
d    False
Length: 4, dtype: bool

以前,这与比较运算符的工作方式相同(参见上文)。

赋值时的 Series 类型提升#

Series 现在将正确提升其数据类型,以适应与当前数据类型不兼容的值的赋值(GH 13234

In [94]: s = pd.Series()

之前行为:

In [2]: s["a"] = pd.Timestamp("2016-01-01")

In [3]: s["b"] = 3.0
TypeError: invalid type promotion

新行为:

In [95]: s["a"] = pd.Timestamp("2016-01-01")

In [96]: s["b"] = 3.0

In [97]: s
Out[97]: 
a    2016-01-01 00:00:00
b                    3.0
Length: 2, dtype: object

In [98]: s.dtype
Out[98]: dtype('O')

.to_datetime() 函数变更#

以前,如果 .to_datetime() 遇到混合的整数/浮点数和字符串,但没有日期时间且 errors='coerce',它会将所有内容转换为 NaT

之前行为:

In [2]: pd.to_datetime([1, 'foo'], errors='coerce')
Out[2]: DatetimeIndex(['NaT', 'NaT'], dtype='datetime64[ns]', freq=None)

当前行为:

这现在将把整数/浮点数转换为默认单位为 ns 的时间戳。

In [99]: pd.to_datetime([1, "foo"], errors="coerce")
Out[99]: DatetimeIndex(['1970-01-01 00:00:00.000000001', 'NaT'], dtype='datetime64[ns]', freq=None)

.to_datetime() 相关的错误修复

  • pd.to_datetime() 在传递整数或浮点数,且没有 uniterrors='coerce' 时的错误(GH 13180)。

  • pd.to_datetime() 在传递无效数据类型(例如布尔值)时的错误;现在将遵守 errors 关键字(GH 13176

  • pd.to_datetime()int8int16 数据类型上溢出时的错误(GH 13451

  • pd.to_datetime()errors='ignore' 且遇到 NaN 和其他无效字符串时引发 AttributeError 的错误(GH 12424

  • pd.to_datetime() 在指定 unit 时未能正确转换浮点数,导致日期时间被截断的错误(GH 13834

合并变更#

合并现在将保留连接键的数据类型(GH 8596

In [100]: df1 = pd.DataFrame({"key": [1], "v1": [10]})

In [101]: df1
Out[101]: 
   key  v1
0    1  10

[1 rows x 2 columns]

In [102]: df2 = pd.DataFrame({"key": [1, 2], "v1": [20, 30]})

In [103]: df2
Out[103]: 
   key  v1
0    1  20
1    2  30

[2 rows x 2 columns]

之前行为:

In [5]: pd.merge(df1, df2, how='outer')
Out[5]:
   key    v1
0  1.0  10.0
1  1.0  20.0
2  2.0  30.0

In [6]: pd.merge(df1, df2, how='outer').dtypes
Out[6]:
key    float64
v1     float64
dtype: object

新行为:

我们能够保留连接键

In [104]: pd.merge(df1, df2, how="outer")
Out[104]: 
   key  v1
0    1  10
1    1  20
2    2  30

[3 rows x 2 columns]

In [105]: pd.merge(df1, df2, how="outer").dtypes
Out[105]: 
key    int64
v1     int64
Length: 2, dtype: object

当然,如果引入了缺失值,则结果数据类型将进行向上转型,这与之前保持不变。

In [106]: pd.merge(df1, df2, how="outer", on="key")
Out[106]: 
   key  v1_x  v1_y
0    1  10.0    20
1    2   NaN    30

[2 rows x 3 columns]

In [107]: pd.merge(df1, df2, how="outer", on="key").dtypes
Out[107]: 
key       int64
v1_x    float64
v1_y      int64
Length: 3, dtype: object

.describe() 方法变更#

.describe() 输出索引中的百分位数标识符现在将四舍五入到保持其独特性所需的最小精度(GH 13104

In [108]: s = pd.Series([0, 1, 2, 3, 4])

In [109]: df = pd.DataFrame([0, 1, 2, 3, 4])

之前行为:

百分位数最多保留一位小数,如果数据帧中的百分位数重复,这可能会引发 ValueError

In [3]: s.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
Out[3]:
count     5.000000
mean      2.000000
std       1.581139
min       0.000000
0.0%      0.000400
0.1%      0.002000
0.1%      0.004000
50%       2.000000
99.9%     3.996000
100.0%    3.998000
100.0%    3.999600
max       4.000000
dtype: float64

In [4]: df.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
Out[4]:
...
ValueError: cannot reindex from a duplicate axis

新行为:

In [110]: s.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
Out[110]: 
count     5.000000
mean      2.000000
std       1.581139
min       0.000000
0.01%     0.000400
0.05%     0.002000
0.1%      0.004000
50%       2.000000
99.9%     3.996000
99.95%    3.998000
99.99%    3.999600
max       4.000000
Length: 12, dtype: float64

In [111]: df.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
Out[111]: 
               0
count   5.000000
mean    2.000000
std     1.581139
min     0.000000
0.01%   0.000400
0.05%   0.002000
0.1%    0.004000
50%     2.000000
99.9%   3.996000
99.95%  3.998000
99.99%  3.999600
max     4.000000

[12 rows x 1 columns]

此外

  • 传递重复的 percentiles 现在将引发 ValueError

  • .describe() 在带有混合数据类型列索引的 DataFrame 上出现错误,之前会引发 TypeErrorGH 13288

Period 变更#

PeriodIndex 现在具有 period 数据类型#

PeriodIndex 现在拥有其自身的 period 数据类型。period 数据类型是 pandas 的扩展数据类型,类似于 category时区感知数据类型datetime64[ns, tz])(GH 13941)。因此,PeriodIndex 不再具有整数数据类型

之前行为:

In [1]: pi = pd.PeriodIndex(['2016-08-01'], freq='D')

In [2]: pi
Out[2]: PeriodIndex(['2016-08-01'], dtype='int64', freq='D')

In [3]: pd.api.types.is_integer_dtype(pi)
Out[3]: True

In [4]: pi.dtype
Out[4]: dtype('int64')

新行为:

In [112]: pi = pd.PeriodIndex(["2016-08-01"], freq="D")

In [113]: pi
Out[113]: PeriodIndex(['2016-08-01'], dtype='period[D]')

In [114]: pd.api.types.is_integer_dtype(pi)
Out[114]: False

In [115]: pd.api.types.is_period_dtype(pi)
Out[115]: True

In [116]: pi.dtype
Out[116]: period[D]

In [117]: type(pi.dtype)
Out[117]: pandas.core.dtypes.dtypes.PeriodDtype

Period('NaT') 现在返回 pd.NaT#

以前,Period 拥有其自身与 pd.NaT 不同的 Period('NaT') 表示。现在 Period('NaT') 已更改为返回 pd.NaT。(GH 12759GH 13582

之前行为:

In [5]: pd.Period('NaT', freq='D')
Out[5]: Period('NaT', 'D')

新行为:

在不提供 freq 选项的情况下,这些操作将返回 pd.NaT

In [118]: pd.Period("NaT")
Out[118]: NaT

In [119]: pd.Period(None)
Out[119]: NaT

为了与 Period 的加减法兼容,pd.NaT 现在支持与 int 的加减法。以前会引发 ValueError

之前行为:

In [5]: pd.NaT + 1
...
ValueError: Cannot add integral value to Timestamp without freq.

新行为:

In [120]: pd.NaT + 1
Out[120]: NaT

In [121]: pd.NaT - 1
Out[121]: NaT

PeriodIndex.values 现在返回 Period 对象数组#

.values 已更改为返回 Period 对象数组,而不是整数数组(GH 13988)。

之前行为:

In [6]: pi = pd.PeriodIndex(['2011-01', '2011-02'], freq='M')
In [7]: pi.values
Out[7]: array([492, 493])

新行为:

In [122]: pi = pd.PeriodIndex(["2011-01", "2011-02"], freq="M")

In [123]: pi.values
Out[123]: array([Period('2011-01', 'M'), Period('2011-02', 'M')], dtype=object)

索引 + / - 不再用于集合操作#

`Index` 基本类型和 `DatetimeIndex`(非数值索引类型)的加减法以前执行集合操作(集合并集和差集)。此行为自 0.15.0 版本以来已被弃用(转而使用特定的 .union().difference() 方法),现在已禁用。在可能的情况下,+- 现在用于元素级操作,例如用于连接字符串或减去日期时间(GH 8227GH 14127)。

之前行为

In [1]: pd.Index(['a', 'b']) + pd.Index(['a', 'c'])
FutureWarning: using '+' to provide set union with Indexes is deprecated, use '|' or .union()
Out[1]: Index(['a', 'b', 'c'], dtype='object')

新行为:相同的操作现在将执行元素级加法

In [124]: pd.Index(["a", "b"]) + pd.Index(["a", "c"])
Out[124]: Index(['aa', 'bc'], dtype='object')

请注意,数值 Index 对象已经执行元素级操作。例如,添加两个整数 Index 的行为保持不变。现在 Index 基类与此行为保持一致。

In [125]: pd.Index([1, 2, 3]) + pd.Index([2, 3, 4])
Out[125]: Index([3, 5, 7], dtype='int64')

此外,由于此更改,现在可以减去两个 DatetimeIndex 对象,从而得到一个 TimedeltaIndex

之前行为:

In [1]: (pd.DatetimeIndex(['2016-01-01', '2016-01-02'])
   ...:  - pd.DatetimeIndex(['2016-01-02', '2016-01-03']))
FutureWarning: using '-' to provide set differences with datetimelike Indexes is deprecated, use .difference()
Out[1]: DatetimeIndex(['2016-01-01'], dtype='datetime64[ns]', freq=None)

新行为:

In [126]: (
   .....:     pd.DatetimeIndex(["2016-01-01", "2016-01-02"])
   .....:     - pd.DatetimeIndex(["2016-01-02", "2016-01-03"])
   .....: )
   .....: 
Out[126]: TimedeltaIndex(['-1 days', '-1 days'], dtype='timedelta64[ns]', freq=None)

Index.difference.symmetric_difference 变更#

Index.differenceIndex.symmetric_difference 现在将更一致地将 NaN 值视为任何其他值。(GH 13514

In [127]: idx1 = pd.Index([1, 2, 3, np.nan])

In [128]: idx2 = pd.Index([0, 1, np.nan])

之前行为:

In [3]: idx1.difference(idx2)
Out[3]: Float64Index([nan, 2.0, 3.0], dtype='float64')

In [4]: idx1.symmetric_difference(idx2)
Out[4]: Float64Index([0.0, nan, 2.0, 3.0], dtype='float64')

新行为:

In [129]: idx1.difference(idx2)
Out[129]: Index([2.0, 3.0], dtype='float64')

In [130]: idx1.symmetric_difference(idx2)
Out[130]: Index([0.0, 2.0, 3.0], dtype='float64')

Index.unique 始终返回 Index#

Index.unique() 现在将唯一值作为具有适当 dtypeIndex 返回。(GH 13395)。以前,大多数 Index 类返回 np.ndarray,而 DatetimeIndexTimedeltaIndexPeriodIndex 返回 Index 以保留时区等元数据。

之前行为:

In [1]: pd.Index([1, 2, 3]).unique()
Out[1]: array([1, 2, 3])

In [2]: pd.DatetimeIndex(['2011-01-01', '2011-01-02',
   ...:                   '2011-01-03'], tz='Asia/Tokyo').unique()
Out[2]:
DatetimeIndex(['2011-01-01 00:00:00+09:00', '2011-01-02 00:00:00+09:00',
               '2011-01-03 00:00:00+09:00'],
              dtype='datetime64[ns, Asia/Tokyo]', freq=None)

新行为:

In [131]: pd.Index([1, 2, 3]).unique()
Out[131]: Index([1, 2, 3], dtype='int64')

In [132]: pd.DatetimeIndex(
   .....:     ["2011-01-01", "2011-01-02", "2011-01-03"], tz="Asia/Tokyo"
   .....: ).unique()
   .....: 
Out[132]: 
DatetimeIndex(['2011-01-01 00:00:00+09:00', '2011-01-02 00:00:00+09:00',
               '2011-01-03 00:00:00+09:00'],
              dtype='datetime64[ns, Asia/Tokyo]', freq=None)

MultiIndex 构造函数、groupbyset_index 保留分类数据类型#

MultiIndex.from_arraysMultiIndex.from_product 现在将保留 MultiIndex 级别中的分类数据类型(GH 13743GH 13854)。

In [133]: cat = pd.Categorical(["a", "b"], categories=list("bac"))

In [134]: lvl1 = ["foo", "bar"]

In [135]: midx = pd.MultiIndex.from_arrays([cat, lvl1])

In [136]: midx
Out[136]: 
MultiIndex([('a', 'foo'),
            ('b', 'bar')],
           )

之前行为:

In [4]: midx.levels[0]
Out[4]: Index(['b', 'a', 'c'], dtype='object')

In [5]: midx.get_level_values[0]
Out[5]: Index(['a', 'b'], dtype='object')

新行为:单个级别现在是一个 CategoricalIndex

In [137]: midx.levels[0]
Out[137]: CategoricalIndex(['b', 'a', 'c'], categories=['b', 'a', 'c'], ordered=False, dtype='category')

In [138]: midx.get_level_values(0)
Out[138]: CategoricalIndex(['a', 'b'], categories=['b', 'a', 'c'], ordered=False, dtype='category')

MultiIndex.from_product 也进行了类似更改。因此,groupbyset_index 也会保留索引中的分类数据类型

In [139]: df = pd.DataFrame({"A": [0, 1], "B": [10, 11], "C": cat})

In [140]: df_grouped = df.groupby(by=["A", "C"], observed=False).first()

In [141]: df_set_idx = df.set_index(["A", "C"])

之前行为:

In [11]: df_grouped.index.levels[1]
Out[11]: Index(['b', 'a', 'c'], dtype='object', name='C')
In [12]: df_grouped.reset_index().dtypes
Out[12]:
A      int64
C     object
B    float64
dtype: object

In [13]: df_set_idx.index.levels[1]
Out[13]: Index(['b', 'a', 'c'], dtype='object', name='C')
In [14]: df_set_idx.reset_index().dtypes
Out[14]:
A      int64
C     object
B      int64
dtype: object

新行为:

In [142]: df_grouped.index.levels[1]
Out[142]: CategoricalIndex(['b', 'a', 'c'], categories=['b', 'a', 'c'], ordered=False, dtype='category', name='C')

In [143]: df_grouped.reset_index().dtypes
Out[143]: 
A       int64
C    category
B     float64
Length: 3, dtype: object

In [144]: df_set_idx.index.levels[1]
Out[144]: CategoricalIndex(['b', 'a', 'c'], categories=['b', 'a', 'c'], ordered=False, dtype='category', name='C')

In [145]: df_set_idx.reset_index().dtypes
Out[145]: 
A       int64
C    category
B       int64
Length: 3, dtype: object

read_csv 函数将逐步枚举分块#

当调用 read_csv() 时指定 chunksize=n 但未指定索引,每个分块过去都有一个从 0n-1 独立生成的索引。现在它们被赋予一个递增的索引,第一个分块从 0 开始,第二个从 n 开始,依此类推,这样在连接时,它们与不带 chunksize= 参数调用 read_csv() 的结果相同(GH 12185)。

In [146]: data = "A,B\n0,1\n2,3\n4,5\n6,7"

之前行为:

In [2]: pd.concat(pd.read_csv(StringIO(data), chunksize=2))
Out[2]:
   A  B
0  0  1
1  2  3
0  4  5
1  6  7

新行为:

In [147]: pd.concat(pd.read_csv(StringIO(data), chunksize=2))
Out[147]: 
   A  B
0  0  1
1  2  3
2  4  5
3  6  7

[4 rows x 2 columns]

稀疏数据变更#

这些更改使 pandas 能够处理更多数据类型的稀疏数据,并使得数据处理体验更加顺畅。

int64bool 类型支持增强#

稀疏数据结构现在增强了对 int64bool dtype 的支持(GH 667GH 13849)。

以前,稀疏数据默认是 float64 数据类型,即使所有输入都是 intbool 数据类型。您必须明确指定 dtype 才能创建 int64 数据类型的稀疏数据。此外,必须明确指定 fill_value,因为默认值是 np.nan,它不会出现在 int64bool 数据中。

In [1]: pd.SparseArray([1, 2, 0, 0])
Out[1]:
[1.0, 2.0, 0.0, 0.0]
Fill: nan
IntIndex
Indices: array([0, 1, 2, 3], dtype=int32)

# specifying int64 dtype, but all values are stored in sp_values because
# fill_value default is np.nan
In [2]: pd.SparseArray([1, 2, 0, 0], dtype=np.int64)
Out[2]:
[1, 2, 0, 0]
Fill: nan
IntIndex
Indices: array([0, 1, 2, 3], dtype=int32)

In [3]: pd.SparseArray([1, 2, 0, 0], dtype=np.int64, fill_value=0)
Out[3]:
[1, 2, 0, 0]
Fill: 0
IntIndex
Indices: array([0, 1], dtype=int32)

从 v0.19.0 开始,稀疏数据保留输入数据类型,并使用更合适的 fill_value 默认值(int64 数据类型为 0bool 数据类型为 False)。

In [148]: pd.arrays.SparseArray([1, 2, 0, 0], dtype=np.int64)
Out[148]: 
[1, 2, 0, 0]
Fill: 0
IntIndex
Indices: array([0, 1], dtype=int32)

In [149]: pd.arrays.SparseArray([True, False, False, False])
Out[149]: 
[True, False, False, False]
Fill: False
IntIndex
Indices: array([0], dtype=int32)

更多详细信息请参见文档

运算符现在保留数据类型#

  • 稀疏数据结构现在可以在算术运算后保留 dtypeGH 13848

s = pd.SparseSeries([0, 2, 0, 1], fill_value=0, dtype=np.int64)
s.dtype

s + 1
  • 稀疏数据结构现在支持 astype 来转换内部 dtype (GH 13900)

s = pd.SparseSeries([1.0, 0.0, 2.0, 0.0], fill_value=0)
s
s.astype(np.int64)

astype 会在数据包含无法转换为指定 dtype 的值时失败。请注意,此限制也适用于 fill_value(默认值为 np.nan)。

In [7]: pd.SparseSeries([1., np.nan, 2., np.nan], fill_value=np.nan).astype(np.int64)
Out[7]:
ValueError: unable to coerce current fill_value nan to int64 dtype

其他稀疏修复#

  • 子类化的 SparseDataFrameSparseSeries 现在在切片或转置时会保留类类型。 (GH 13787)

  • 具有 bool dtype 的 SparseArray 现在支持逻辑(布尔)运算符 (GH 14000)

  • SparseSeries 使用 MultiIndex [] 索引可能引发 IndexError 错误 (GH 13144)

  • SparseSeries 使用 MultiIndex [] 索引结果可能具有正常的 Index (GH 13144)

  • SparseDataFrame 中 `axis=None` 未默认设置为 `axis=0` 的错误 (GH 13048)

  • 使用 object dtype 创建 SparseSeriesSparseDataFrame 时可能引发 TypeError 错误 (GH 11633)

  • SparseDataFrame 未遵守传入的 SparseArraySparseSeries 的 dtype 和 fill_value 的错误 (GH 13866)

  • SparseArraySparseSeries 不对 fill_value 应用 ufunc 的错误 (GH 13853)

  • SparseSeries.abs 错误地保留负 fill_value 的错误 (GH 13853)

  • 在多类型 SparseDataFrame 上进行单行切片时,类型以前被强制转换为浮点型的错误 (GH 13917)

  • SparseSeries 切片将整数 dtype 更改为浮点型的错误 (GH 8292)

  • SparseDataFarme 比较操作可能引发 TypeError 的错误 (GH 13001)

  • SparseDataFarme.isnull 引发 ValueError 的错误 (GH 8276)

  • 使用 bool dtype 表示 SparseSeries 时可能引发 IndexError 的错误 (GH 13110)

  • 具有 boolint64 dtype 的 SparseSeriesSparseDataFrame 可能将其值显示为 float64 dtype 的错误 (GH 13110)

  • 使用具有 bool dtype 的 SparseArray 进行稀疏索引可能返回不正确结果的错误 (GH 13985)

  • SparseSeries 创建的 SparseArray 可能丢失 dtype 的错误 (GH 13999)

  • SparseSeries 与密集类型比较时返回普通 Series 而不是 SparseSeries 的错误 (GH 13999)

索引器 dtype 更改#

注意

此更改仅影响在 Windows 上运行的 64 位 Python,并且仅影响相对高级的索引操作

返回索引器数组的方法(例如 Index.get_indexer)会将该数组强制转换为“平台整数”,以便可以直接用于第三方库操作,例如 numpy.take。以前,平台整数被定义为 np.int_,它对应于 C 整数;而现在使用的正确类型是 np.intp,它对应于可以容纳指针的 C 整数大小 (GH 3033, GH 13972)。

这些类型在许多平台上是相同的,但在 Windows 上的 64 位 Python 中,np.int_ 是 32 位,而 np.intp 是 64 位。改变这种行为可以提高该平台上许多操作的性能。

之前行为:

In [1]: i = pd.Index(['a', 'b', 'c'])

In [2]: i.get_indexer(['b', 'b', 'c']).dtype
Out[2]: dtype('int32')

新行为:

In [1]: i = pd.Index(['a', 'b', 'c'])

In [2]: i.get_indexer(['b', 'b', 'c']).dtype
Out[2]: dtype('int64')

其他 API 更改#

  • warn=True 且实例具有非零纳秒数时,Timestamp.to_pydatetime 将发出 UserWarning;此前,这会将消息打印到 stdout (GH 14101)。

  • 带有日期时间和时区的 Series.unique() 现在返回带有时间区的 Timestamp 数组 (GH 13565)。

  • 调用 Panel.to_sparse() 时将引发 NotImplementedError 异常 (GH 13778)。

  • 调用 Index.reshape() 时将引发 NotImplementedError 异常 (GH 12882)。

  • .filter() 强制关键字参数的互斥 (GH 12399)。

  • evalfloat32 类型的向上转型规则已更新,以与 NumPy 的规则更一致。新行为是,如果您将 pandas float32 对象乘以一个标量 float64,则不会向上转型为 float64 (GH 12388)。

  • 如果对 groupby 或 resample 对象调用 np.mean 等 NumPy ufuncs,现在会引发 UnsupportedFunctionCall 错误 (GH 12811)。

  • __setitem__ 将不再把可调用 rhs 作为函数应用,而是直接存储。请直接调用 where 以获得之前的行为 (GH 13299)。

  • 调用 .sample() 将遵循通过 numpy.random.seed(n) 设置的随机种子 (GH 13161)

  • Styler.apply 现在对函数必须返回的输出更严格。对于 axis=0axis=1,输出形状必须相同。对于 axis=None,输出必须是具有相同列和索引标签的 DataFrame (GH 13222)。

  • Float64Index.astype(int) 现在如果 Float64Index 包含 NaN 值,将引发 ValueError (GH 13149)

  • TimedeltaIndex.astype(int)DatetimeIndex.astype(int) 现在将返回 Int64Index 而非 np.array (GH 13209)

  • 将具有多个频率的 Period 传递给普通 Index 现在会返回具有 object dtype 的 Index (GH 13664)

  • PeriodIndex.fillna 使用不同 freq 的 Period 时,现在会强制转换为 object dtype (GH 13664)

  • return_type 不为 None 时,DataFrame.boxplot(by=col) 生成的分面箱线图现在返回 Series。此前,这些图返回 OrderedDict。请注意,当 return_type=None(默认值)时,它们仍然返回 2-D NumPy 数组 (GH 12216, GH 7096)。

  • 如果提供了 r, r+a 之外的模式,pd.read_hdf 现在将引发 ValueError 而非 KeyError。 (GH 13623)

  • 对于 Python 3.x,当调用不存在的文件时,pd.read_csv()pd.read_table()pd.read_hdf() 将引发内置的 FileNotFoundError 异常;在 Python 2.x 中,这被回溯为 IOError (GH 14086)

  • 更具信息量的异常通过 CSV 解析器传递。现在异常类型将是原始异常类型而不是 CParserError (GH 13652)。

  • C 引擎中的 pd.read_csv() 现在在 sep 编码长度超过一个字符时,将发出 ParserWarning 或引发 ValueError (GH 14065)

  • 包含混合 int64uint64 dtypes 的 DataFrame,其 DataFrame.values 现在将返回 float64,符合 np.find_common_type (GH 10364, GH 13917)

  • .groupby.groups 现在将返回一个 Index 对象的字典,而不是 np.ndarraylists 的字典 (GH 14293)

弃用#

  • Series.reshapeCategorical.reshape 已被弃用,并将在后续版本中移除 (GH 12882, GH 12882)

  • PeriodIndex.to_datetime 已被弃用,取而代之的是 PeriodIndex.to_timestamp (GH 8254)

  • Timestamp.to_datetime 已被弃用,取而代之的是 Timestamp.to_pydatetime (GH 8254)

  • Index.to_datetimeDatetimeIndex.to_datetime 已被弃用,取而代之的是 pd.to_datetime (GH 8254)

  • pandas.core.datetools 模块已被弃用,并将在后续版本中移除 (GH 14094)

  • SparseList 已被弃用,并将在未来版本中移除 (GH 13784)

  • DataFrame.to_html()DataFrame.to_latex() 已放弃 colSpace 参数,取而代之的是 col_space (GH 13857)

  • DataFrame.to_sql() 已弃用 flavor 参数,因为在未安装 SQLAlchemy 时它是多余的 (GH 13611)

  • 已弃用的 read_csv 关键词

    • compact_intsuse_unsigned 已被弃用,并将在未来版本中移除 (GH 13320)

    • buffer_lines 已被弃用,并将在未来版本中移除 (GH 13360)

    • as_recarray 已被弃用,并将在未来版本中移除 (GH 13373)

    • skip_footer 已被弃用,取而代之的是 skipfooter,并将在未来版本中移除 (GH 13349)

  • 顶级 pd.ordered_merge() 已更名为 pd.merge_ordered(),原名称将在未来版本中移除 (GH 13358)

  • Timestamp.offset 属性(以及构造函数中的命名参数)已被弃用,取而代之的是 freq (GH 12160)

  • pd.tseries.util.pivot_annual 已弃用。请使用 pivot_table 作为替代,例如此处所示:here (GH 736)

  • pd.tseries.util.isleapyear 已被弃用,并将在后续版本中移除。Datetime-like 对象现在具有 .is_leap_year 属性 (GH 13727)

  • Panel4DPanelND 构造函数已被弃用,并将在未来版本中移除。表示这些类型 N 维数据的推荐方式是使用 xarray 包。pandas 提供了一个 to_xarray() 方法来自动化此转换 (GH 13564)。

  • pandas.tseries.frequencies.get_standard_freq 已弃用。请改用 pandas.tseries.frequencies.to_offset(freq).rule_code (GH 13874)

  • pandas.tseries.frequencies.to_offsetfreqstr 关键词已被弃用,取而代之的是 freq (GH 13874)

  • Categorical.from_array 已被弃用,并将在未来版本中移除 (GH 13854)

移除先前版本弃用/更改#

  • SparsePanel 类已被移除 (GH 13778)

  • pd.sandbox 模块已被移除,取而代之的是外部库 pandas-qt (GH 13670)

  • pandas.io.datapandas.io.wb 模块已被移除,取而代之的是 pandas-datareader 包 (GH 13724)。

  • pandas.tools.rplot 模块已被移除,取而代之的是 seaborn 包 (GH 13855)

  • DataFrame.to_csv() 已移除 engine 参数,该参数已在 0.17.1 中弃用 (GH 11274, GH 13419)

  • DataFrame.to_dict() 已移除 outtype 参数,取而代之的是 orient (GH 13627, GH 8486)

  • pd.Categorical 已放弃直接设置 ordered 属性,取而代之的是 set_ordered 方法 (GH 13671)

  • pd.Categorical 已移除 levels 属性,取而代之的是 categories (GH 8376)

  • DataFrame.to_sql() 已移除 flavor 参数的 mysql 选项 (GH 13611)

  • Panel.shift() 已移除 lags 参数,取而代之的是 periods (GH 14041)

  • pd.Index 已移除 diff 方法,取而代之的是 difference (GH 13669)

  • pd.DataFrame 已移除 to_wide 方法,取而代之的是 to_panel (GH 14039)

  • Series.to_csv 已移除 nanRep 参数,取而代之的是 na_rep (GH 13804)

  • Series.xs, DataFrame.xs, Panel.xs, Panel.major_xsPanel.minor_xs 已移除 copy 参数 (GH 13781)

  • str.split 已移除 return_type 参数,取而代之的是 expand (GH 13701)

  • 移除了旧版时间规则(偏移别名),自 0.17.0 起已弃用(自 0.8.0 起即为别名)(GH 13590, GH 13868)。现在旧版时间规则会引发 ValueError。有关当前支持的偏移量列表,请参阅此处

  • DataFrame.plot.boxDataFrame.boxplotreturn_type 参数的默认值从 None 更改为 "axes"。这些方法现在默认返回 matplotlib 轴,而不是艺术家字典。参见此处 (GH 6581)。

  • pandas.io.sql 模块中的 tqueryuquery 函数已移除 (GH 5950)。

性能改进#

  • 稀疏 IntIndex.intersect 的性能得到改进 (GH 13082)

  • 当块数量较大时,使用 BlockIndex 的稀疏算术运算性能得到改进,但在这种情况下推荐使用 IntIndex (GH 13082)

  • DataFrame.quantile() 的性能得到改进,因为它现在按块操作 (GH 11623)

  • 提高了 float64 散列表操作的性能,修复了 Python 3 中一些非常慢的索引和 groupby 操作 (GH 13166, GH 13334)

  • DataFrameGroupBy.transform 的性能得到改进 (GH 12737)

  • IndexSeries.duplicated 性能得到改进 (GH 10235)

  • Index.difference 的性能得到改进 (GH 12044)

  • RangeIndex.is_monotonic_increasingis_monotonic_decreasing 的性能得到改进 (GH 13749)

  • DatetimeIndex 中日期时间字符串解析的性能得到改进 (GH 13692)

  • 提高了 Period 哈希的性能 (GH 12817)

  • 提高了带有时区的日期时间 factorize 的性能 (GH 13750)

  • 通过在较大的索引上惰性创建索引哈希表,提高了性能 (GH 14266)

  • groupby.groups 的性能得到改进 (GH 14293)

  • 在内省内存使用时,不必要地实例化 MultiIndex (GH 14308)

错误修复#

  • groupby().shift() 中的一个错误,在极少数情况下,当按含有缺失值的列进行分组时,可能导致段错误或数据损坏 (GH 13813)

  • groupby().cumsum()axis=1 时计算 cumprod 的错误 (GH 13994)

  • pd.to_timedelta()errors 参数未被遵守的错误 (GH 13613)

  • io.json.json_normalize() 中的一个错误,其中非 ASCII 键会引发异常 (GH 13213)

  • .plot() 中,将非默认索引的 Series 作为 xerryerr 传递时的错误 (GH 11858)

  • 区域图在启用子图或图例移动后绘制图例不正确的错误(需要 matplotlib 1.5.0 才能正确绘制区域图图例)(GH 9161, GH 13544)

  • DataFrame 赋值使用对象类型 Index 时,导致结果列可变回原始对象的错误 (GH 13522)

  • matplotlib AutoDataFormatter 中的一个错误;这恢复了第二个缩放格式并重新添加了微秒缩放格式 (GH 13131)

  • HDFStore 中,固定格式且指定了 start 和/或 stop 的选择现在将返回选定的范围 (GH 8287)

  • Categorical.from_codes() 中,当传入无效的 ordered 参数时,会引发无用错误提示的错误 (GH 14058)

  • 在 Windows 上,从整数元组构造 Series 时不返回默认 dtype (int64) 的错误 (GH 13646)

  • TimedeltaIndex 与类日期时间对象相加时,未捕获加法溢出的错误 (GH 14068)

  • .groupby(..).resample(..) 在多次调用同一对象时出现的错误 (GH 13174)

  • 当索引名称为 Unicode 字符串时,调用 .to_records() 中的错误 (GH 13172)

  • 调用未实现 .memory_usage() 的对象时的错误 (GH 12924)

  • 带有 NaN 值的 Series.quantile 回归(也出现在 .median().describe() 中);此外,现在将 Series 命名为分位数 (GH 13098, GH 13146)

  • 带有日期时间值和缺失组的 SeriesGroupBy.transform 错误 (GH 13191)

  • Series 在日期时间类数字操作中被错误强制转换的错误 (GH 13844)

  • 当传入包含带时区的日期时间的 Categorical 时,Categorical 构造函数中的错误 (GH 14190)

  • 带有 str 索引的 Series.str.extractall() 引起 ValueError 的错误 (GH 13156)

  • 带有单个组和量词的 Series.str.extractall() 中的错误 (GH 13382)

  • DatetimeIndexPeriod 相减时引发 ValueErrorAttributeError 而非 TypeError 的错误 (GH 13078)

  • 使用 NaNNaT 混合数据创建的 IndexSeries 可能没有 datetime64 dtype 的错误 (GH 13324)

  • IndexSeries 可能忽略 np.datetime64('nat')np.timdelta64('nat') 来推断 dtype 的错误 (GH 13324)

  • PeriodIndexPeriod 相减时引发 AttributeError 的错误 (GH 13071)

  • 在某些情况下,PeriodIndex 构造返回 float64 索引的错误 (GH 13067)

  • PeriodIndex 为空时,.resample(..) 未能适当地更改其 freq 的错误 (GH 13067)

  • DataFrame 为空时,.resample(..) 搭配 PeriodIndex 未能正确保留其类型或名称的错误 (GH 13212)

  • 当传入函数为每个组返回标量值时,groupby(..).apply(..) 中的错误 (GH 13468)。

  • groupby(..).resample(..) 中,传入某些关键词会引发异常的错误 (GH 13235)

  • 在 tz-aware DateTimeIndex 上使用 .tz_convert 时,其结果依赖于索引是否排序正确的错误 (GH 13306)

  • .tz_localizedateutil.tz.tzlocal 可能返回不正确结果的错误 (GH 13583)

  • 带有 dateutil.tz.tzlocalDatetimeTZDtype dtype 无法被视为有效 dtype 的错误 (GH 13583)

  • pd.read_hdf() 中的一个错误:尝试加载包含单个数据集的 HDF 文件(该文件含有一个或多个分类列)时,除非将 key 参数设置为数据集的名称,否则加载失败。(GH 13231)

  • .rolling() 中的一个错误,它允许在构建 Rolling() 对象时使用负整数窗口,但在聚合时会失败 (GH 13383)

  • 带有元组值数据和数字索引的 Series 索引中的错误 (GH 13509)

  • 打印 pd.DataFrame 时,带有 object dtype 的异常元素导致段错误的错误 (GH 13717)

  • Series 排名时可能导致段错误的错误 (GH 13445)

  • 各种索引类型中,未传递传入索引名称的错误 (GH 12309)

  • DatetimeIndex 中未遵守 copy=True 的错误 (GH 13205)

  • DatetimeIndex.is_normalized 在本地时区的情况下,对已标准化的日期范围返回不正确结果的错误 (GH 13459)

  • pd.concat.append 可能将 datetime64timedelta 强制转换为包含 Python 内置 datetimetimedelta 而非 TimestampTimedeltaobject dtype 的错误 (GH 13626)

  • 当结果为 object dtype 时,PeriodIndex.append 可能引发 AttributeError 的错误 (GH 13221)

  • CategoricalIndex.append 可能接受普通 list 的错误 (GH 13626)

  • pd.concat.append 在相同 timezone 时区被重置为 UTC 的错误 (GH 7795)

  • 如果数据包含夏令时边界附近的日期时间,SeriesDataFrame.append 会引发 AmbiguousTimeError 的错误 (GH 13626)

  • DataFrame.to_csv() 中,即使指定了非数字值需要引用,浮点值仍被引用的错误 (GH 12922, GH 13259)

  • DataFrame.describe() 在仅包含布尔列时引发 ValueError 的错误 (GH 13898)

  • MultiIndex 切片中,当级别非唯一时,返回额外元素的错误 (GH 12896)

  • .str.replace 对无效替换不引发 TypeError 的错误 (GH 13438)

  • MultiIndex.from_arrays 未检查输入数组长度是否匹配的错误 (GH 13599)

  • cartesian_productMultiIndex.from_product 在输入空数组时可能引发异常的错误 (GH 12258)

  • pd.read_csv() 在极少数情况下,在大型数据块上迭代流/文件时,可能导致段错误或数据损坏的错误 (GH 13703)

  • pd.read_csv() 中的一个错误,当为 na_values 传入包含标量的字典时,导致引发错误 (GH 12224)

  • pd.read_csv() 中的一个错误,该错误导致 BOM 文件因未忽略 BOM 而被错误解析 (GH 4793)

  • pd.read_csv()engine='python' 的错误,当 NumPy 数组作为 usecols 传入时引发错误 (GH 12546)

  • pd.read_csv() 中的一个错误,当索引列被解析为日期并带有 thousands 参数时,它们被错误解析 (GH 14066)

  • pd.read_csv()engine='python' 的一个错误,其中在数据转换为数值后未能正确检测到 NaN 值 (GH 13314)

  • pd.read_csv() 中,未对两个引擎的 nrows 参数进行适当验证的错误 (GH 10476)

  • pd.read_csv()engine='python' 的错误,其中混合大小写形式的无穷大未能被正确解释 (GH 13274)

  • pd.read_csv()engine='python' 的错误,其中尾随的 NaN 值未能被解析 (GH 13320)

  • 在 Windows Python 3 下,pd.read_csv()engine='python'tempfile.TemporaryFile 读取时的错误 (GH 13398)

  • pd.read_csv() 中,阻止 usecols kwarg 接受单字节 unicode 字符串的错误 (GH 13219)

  • pd.read_csv() 中,阻止 usecols 为空集的错误 (GH 13402)

  • pd.read_csv() 在 C 引擎中,NULL 字符未被解析为 NULL 的错误 (GH 14012)

  • pd.read_csv() 在 C 引擎中,即使 quoting 被指定为 None,NULL quotechar 也不被接受的错误 (GH 13411)

  • pd.read_csv() 在 C 引擎中,当 quoting 被指定为非数字时,字段未被正确转换为浮点数的错误 (GH 13411)

  • pd.read_csv() 在 Python 2.x 中,使用非 UTF8 编码的多字符分隔数据时的错误 (GH 3404)

  • pd.read_csv() 中的一个错误,其中 utf-xx 的别名(例如 UTF-xx, UTF_xx, utf_xx)引发 UnicodeDecodeError (GH 13549)

  • pd.read_csv, pd.read_table, pd.read_fwf, pd.read_statapd.read_sas 中的一个错误,如果 chunksizeiterator 都为 None,文件会被解析器打开但未关闭。(GH 13940)

  • StataReader, StataWriter, XportReaderSAS7BDATReader 中的一个错误,其中在引发错误时文件未被正确关闭。(GH 13940)

  • pd.pivot_table() 中当 aggfunc 是列表时,margins_name 被忽略的错误 (GH 13354)

  • pd.Series.str.zfill, center, ljust, rjustpad 在传递非整数时未引发 TypeError 的错误 (GH 13598)

  • 检查 TimedeltaIndex 中是否有任何空对象时,总是返回 True 的错误 (GH 13603)

  • 如果 Series 包含日期时间类型作为 object dtype,则 Series 算术运算会引发 TypeError 的错误 (GH 13043)

  • Series.isnull()Series.notnull() 忽略 Period('NaT') 的错误 (GH 13737)

  • Series.fillna()Series.dropna() 不影响 Period('NaT') 的错误 (GH 13737

  • .fillna(value=np.nan)category dtyped Series 上错误地引发 KeyError 的错误 (GH 14021)

  • 扩展 dtype 创建中的错误,其中创建的类型不相同/同一 (GH 13285)

  • .resample(..) 中,IPython 内省触发不正确警告的错误 (GH 13618)

  • NaT - Period 引发 AttributeError 的错误 (GH 13071)

  • 如果 rhs 包含 NaT,则 Series 比较可能输出不正确结果的错误 (GH 9005)

  • 如果 IndexSeries 包含 NaT 且 dtype 为 object,则比较可能输出不正确结果的错误 (GH 13592)

  • 如果 Period 在右侧,则 Period 加法会引发 TypeError 的错误 (GH 13069)

  • PeriodSeriesIndex 比较会引发 TypeError 的错误 (GH 13200)

  • pd.set_eng_float_format() 中,阻止 NaN 和 Inf 格式化的错误 (GH 11981)

  • .unstack 搭配 Categorical dtype 将 .ordered 重置为 True 的错误 (GH 13249)

  • 清理日期时间解析中的一些编译时警告 (GH 13607)

  • 如果数据包含夏令时边界附近的日期时间,则 factorize 会引发 AmbiguousTimeError 的错误 (GH 13750)

  • 如果新索引包含夏令时边界和多级别,则 .set_index 会引发 AmbiguousTimeError 的错误 (GH 12920)

  • 如果数据包含夏令时边界附近的日期时间,则 .shift 会引发 AmbiguousTimeError 的错误 (GH 13926)

  • pd.read_hdf()DataFrame 包含 categorical 列且查询不匹配任何值时返回不正确结果的错误 (GH 13792)

  • 当使用非词法排序的 MultiIndex 进行索引时,.iloc 中的错误 (GH 13797)

  • 当在反向排序的 DatetimeIndex 中使用日期字符串索引时,.loc 中的错误 (GH 14316)

  • Series 比较运算符在处理零维 NumPy 数组时的错误 (GH 13006)

  • .combine_first 可能返回不正确 dtype 的错误 (GH 7630, GH 10567)

  • groupby 中的一个错误,其中 apply 返回不同结果,取决于第一个结果是否为 None (GH 12824)

  • groupby(..).nth() 中的一个错误,其中如果调用 .head()/.tail() 之后调用,组键包含不一致 (GH 12839)

  • .to_html, .to_latex.to_string 静默忽略通过 formatters 关键词传入的自定义日期时间格式器的错误 (GH 10690)

  • DataFrame.iterrows() 未产生 Series 子类的错误(如果已定义)(GH 13977)

  • errors='coerce' 且输入包含不可哈希对象时,pd.to_numeric 中的错误 (GH 13324)

  • 无效的 Timedelta 算术和比较可能引发 ValueError 而非 TypeError 的错误 (GH 13624)

  • to_datetimeDatetimeIndex 中无效日期时间解析可能引发 TypeError 而非 ValueError 的错误 (GH 11169, GH 11287)

  • 当使用 tz-aware Timestamp 和不匹配的 tz 选项创建 Index 时,时区被错误强制转换的错误 (GH 13692)

  • 纳秒频率的 DatetimeIndex 未包含使用 end 指定的时间戳的错误 (GH 13672)

  • Series 在使用 np.timedelta64 设置切片时的错误 (GH 14155)

  • 如果 datetime 超过 datetime64[ns] 边界,Index 会引发 OutOfBoundsDatetime,而不是强制转换为 object dtype 的错误 (GH 13663)

  • Index 可能忽略作为 dtype 传入的指定 datetime64timedelta64 的错误 (GH 13981)

  • RangeIndex 可以在没有参数的情况下创建,而不是引发 TypeError 的错误 (GH 13793)

  • 如果数据超出 datetime64[ns] 边界,则 .value_counts() 会引发 OutOfBoundsDatetime 的错误 (GH 13663)

  • DatetimeIndex 可能引发 OutOfBoundsDatetime,如果输入 np.datetime64 的单位不是 ns (GH 9114)

  • 当创建 Series 时,使用单位不是 nsnp.datetime64 作为 object dtype 导致值不正确的错误 (GH 13876)

  • 带有 timedelta 数据的 resample 错误,其中数据被转换为浮点数 (GH 13119)。

  • 如果输入类日期时间单位不是 ns,则 pd.isnull()pd.notnull() 会引发 TypeError 的错误 (GH 13389)

  • 如果输入类日期时间单位不是 ns,则 pd.merge() 可能引发 TypeError 的错误 (GH 13389)

  • HDFStore/read_hdf() 丢弃 DatetimeIndex.name 的错误,如果 tz 已设置 (GH 13884)

  • Categorical.remove_unused_categories().codes dtype 更改为平台 int 的错误 (GH 13261)

  • 当按多列(包括分类列)分组时,groupby 搭配 as_index=False 返回所有 NaN 的错误 (GH 13204)

  • df.groupby(...)[...] 中,使用 Int64Index 进行 getitem 操作时引发错误的错误 (GH 13731)

  • DataFrame.style 分配给索引名称的 CSS 类中的一个错误。此前它们被分配为 "col_heading level<n> col<c>",其中 n 是级别数 + 1。现在它们被分配为 "index_name level<n>",其中 n 是该 MultiIndex 的正确级别。

  • pd.read_gbq() 可能因与另一个名为 apiclient 的 python 包命名冲突而抛出 ImportError: No module named discovery 的错误 (GH 13454)

  • Index.union 在处理命名为空的索引时返回不正确结果的错误 (GH 13432)

  • Index.differenceDataFrame.join 在 Python3 中使用混合整数索引时引发错误的错误 (GH 13432, GH 12814)

  • 从 tz-aware datetime64 series 中减去 tz-aware datetime.datetime 的错误 (GH 14088)

  • .to_excel() 中,当 DataFrame 包含一个 MultiIndex 且其中一个标签带有 NaN 值时发生的错误 (GH 13511)

  • 无效的频率偏移字符串(如“D1”、“-2-3H”)可能不引发 ValueError 的错误 (GH 13930)

  • concatgroupby 对于带有 RangeIndex 级别的层次结构帧的错误 (GH 13542)。

  • Series.str.contains() 对于仅包含 object dtype 的 NaN 值的 Series 的错误 (GH 14171)

  • groupby dataframe 上的 agg() 函数将 datetime64[ns] 列的 dtype 更改为 float64 的错误 (GH 12821)

  • 使用 NumPy ufunc 和 PeriodIndex 添加或减去整数时引发 IncompatibleFrequency 的错误。请注意,建议使用标准运算符如 +-,因为标准运算符使用更有效的路径 (GH 13980)

  • NaT 的操作返回 float 而非 datetime64[ns] 的错误 (GH 12941)

  • axis=None 时,Series 灵活算术方法(如 .add())引发 ValueError 的错误 (GH 13894)

  • DataFrame.to_csv() 方法处理 MultiIndex 列时出现一个错误,导致多余的空行被添加 (GH 6618)

  • DatetimeIndex, TimedeltaIndexPeriodIndex.equals() 方法中存在一个错误,当输入不是 Index 但包含相同值时,可能会返回 True (GH 13107)

  • 在对带有时区的 datetime 进行赋值时存在一个错误,如果它包含接近夏令时(DST)边界的 datetime,可能无法正常工作 (GH 14146)

  • pd.eval()HDFStore 查询中存在一个错误,在 Python 2 下会截断长浮点文字 (GH 14241)

  • Index 中存在一个错误,当列不在 df 中且列包含重复值时,会引发 KeyError 并显示不正确的列 (GH 13822)

  • PeriodPeriodIndex 中存在一个错误,当频率具有组合偏移别名时,会创建错误的日期 (GH 13874)

  • .to_string() 方法中存在一个错误,当使用整数 line_widthindex=False 调用时,会引发 UnboundLocalError 异常,因为 idx 在赋值前被引用。

  • eval() 中存在一个错误,其中 resolvers 参数不接受列表 (GH 14095)

  • stack, get_dummies, make_axis_dummies 中存在一些错误,它们没有在(多)索引中保留分类 dtype (GH 13854)

  • PeriodIndex 现在可以接受包含 pd.NaTlistarray (GH 13430)

  • df.groupby 中存在一个错误,如果分组的数据框包含空箱,.median() 会返回任意值 (GH 13629)

  • Index.copy() 中存在一个错误,其中 name 参数被忽略了 (GH 14302)

贡献者#

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

  • Adrien Emery +

  • Alex Alekseyev

  • Alex Vig +

  • Allen Riddell +

  • Amol +

  • Amol Agrawal +

  • Andy R. Terrel +

  • Anthonios Partheniou

  • Ben Kandel +

  • Bob Baxley +

  • Brett Rosen +

  • Camilo Cota +

  • Chris

  • Chris Grinolds

  • Chris Warth

  • Christian Hudon

  • Christopher C. Aycock

  • Daniel Siladji +

  • Douglas McNeil

  • Drewrey Lupton +

  • Eduardo Blancas Reyes +

  • Elliot Marsden +

  • Evan Wright

  • Felix Marczinowski +

  • Francis T. O’Donovan

  • Geraint Duck +

  • Giacomo Ferroni +

  • Grant Roch +

  • Gábor Lipták

  • Haleemur Ali +

  • Hassan Shamim +

  • Iulius Curt +

  • Ivan Nazarov +

  • Jeff Reback

  • Jeffrey Gerard +

  • Jenn Olsen +

  • Jim Crist

  • Joe Jevnik

  • John Evans +

  • John Freeman

  • John Liekezer +

  • John W. O’Brien

  • John Zwinck +

  • Johnny Gill +

  • Jordan Erenrich +

  • Joris Van den Bossche

  • Josh Howes +

  • Jozef Brandys +

  • Ka Wo Chen

  • Kamil Sindi +

  • Kerby Shedden

  • Kernc +

  • Kevin Sheppard

  • Matthieu Brucher +

  • Maximilian Roos

  • Michael Scherer +

  • Mike Graham +

  • Mortada Mehyar

  • Muhammad Haseeb Tariq +

  • Nate George +

  • Neil Parley +

  • Nicolas Bonnotte

  • OXPHOS

  • Pan Deng / Zora +

  • Paul +

  • Paul Mestemaker +

  • Pauli Virtanen

  • Pawel Kordek +

  • Pietro Battiston

  • Piotr Jucha +

  • Ravi Kumar Nimmi +

  • Robert Gieseke

  • Robert Kern +

  • Roger Thomas

  • Roy Keyes +

  • Russell Smith +

  • Sahil Dua +

  • Sanjiv Lobo +

  • Sašo Stanovnik +

  • Shawn Heide +

  • Sinhrks

  • Stephen Kappel +

  • Steve Choi +

  • Stewart Henderson +

  • Sudarshan Konge +

  • Thomas A Caswell

  • Tom Augspurger

  • Tom Bird +

  • Uwe Hoffmann +

  • WillAyd +

  • Xiang Zhang +

  • YG-Riku +

  • Yadunandan +

  • Yaroslav Halchenko

  • Yuichiro Kaneko +

  • adneu

  • agraboso +

  • babakkeyvani +

  • c123w +

  • chris-b1

  • cmazzullo +

  • conquistador1492 +

  • cr3 +

  • dsm054

  • gfyoung

  • harshul1610 +

  • iamsimha +

  • jackieleng +

  • mpuels +

  • pijucha +

  • priyankjain +

  • sinhrks

  • wcwagner +

  • yui-knk +

  • zhangjinjie +

  • znmean +

  • 颜发才(Yan Facai) +