Pandas 2.2 中文文档(九十九·二)

重复列名 现在在read_csv()中得到支持,无论它们是否在文件中或作为names参数传递(GH 7160, GH 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`

当指定为 dtype 时,`read_csv()` 函数现在支持解析`Categorical`列([GH 10153](https://github.com/pandas-dev/pandas/issues/10153))。根据数据的结构,这可能导致比解析后转换为`Categorical`更快的解析时间和更低的内存使用。在这里查看 io 文档。

```py
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 

注意

结果类别将始终被解析为字符串(对象 dtype)。如果类别是数值型的,则可以使用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()`,请参阅 Unioning Categoricals ([GH 13361](https://github.com/pandas-dev/pandas/issues/13361), [GH 13763](https://github.com/pandas-dev/pandas/issues/13763), [GH 13846](https://github.com/pandas-dev/pandas/issues/13846), [GH 14173](https://github.com/pandas-dev/pandas/issues/14173))

    ```py
    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'] 
    ```

+   `concat` 和 `append` 现在可以将具有不同 `categories` 的 `category` dtypes 连接为 `object` dtype ([GH 13524](https://github.com/pandas-dev/pandas/issues/13524))

    ```py
    In [42]: s1 = pd.Series(["a", "b"], dtype="category")

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

**先前的行为**:

```py
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 号)和月底,以及月初(1 号)和 15 号的日期偏移量。 ([GH 1543](https://github.com/pandas-dev/pandas/issues/1543))

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

SemiMonthEnd:

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

SemiMonthBegin:

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`中,以使其与`Series`和`DataFrame`API 更一致。

`Index`现在支持`.where()`函数进行相同形状的索引 ([GH 13170](https://github.com/pandas-dev/pandas/issues/13170))

```py
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 10008, GH 13156)

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

In [57]: idx.str.extractall(r"ab")
Out[57]: 
 digit
 match 
0 0         1
 1         2
1 0         1

[3 rows x 1 columns] 

Index.astype()现在接受一个可选的布尔参数copy,如果满足 dtype 的要求,则允许可选复制 (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 13109, GH 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](https://github.com/pandas-dev/pandas/issues/13352))

```py
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 13147](https://github.com/pandas-dev/pandas/issues/13147), [GH 13634](https://github.com/pandas-dev/pandas/issues/13634))

以下现在是这个 API 的一部分:

```py
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调用这些函数现在会显示一个DeprecationWarning。(GH 13990) ### 其他增强功能

  • Timestamp 现在可以接受类似于datetime.datetime()的位置参数和关键字参数。(GH 10758, GH 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

  • 使用engine='python'pd.read_csv()现在支持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,当 dtype 为分类时生效(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

  • 当使用 convert_categoricals=True 读取具有重复值标签的 Stata 文件时,read_stata()StataReader 会提出更明确的错误消息 (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 文档中添加了关于读取具有混合 dtypes 的列的危险性以及如何处理的说明 (GH 13746)

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

  • 当未安装 sqlalchemy 并使用连接字符串时,sql 函数将引发 ImportError 错误 (GH 11920)

  • 与 matplotlib 2.0 兼容。旧版本的 pandas 应该也可以与 matplotlib 2.0 一起工作 (GH 13333)

  • Timestamp, Period, DatetimeIndex, PeriodIndex.dt accessor 现在具有 .is_leap_year 属性来检查日期是否属于闰年。 (GH 13727)

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

  • pd.read_jsonDataFrame.to_json 现在支持使用 lines 选项读取和写入 json 行,参见 Line delimited json (GH 9180)

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

  • groupby() 现在将接受标量和单元素列表以指定非 MultiIndex 分组器上的 level。 (GH 13907)

  • 在 excel 日期列中的不可转换日期将以 object dtype 返回,而不是引发异常 (GH 10001).

  • 现在接受pd.Timedelta(None),并将返回NaT,与pd.Timestamp相似(GH 13687

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

  • SeriesIndex 现在支持 divmod,将返回一个系列或索引的元组。这遵循标准的二元运算符,关于广播规则(GH 14208)的行为。 ### 函数 merge_asof 用于 asof 风格的时序连接

通过merge_asof() 函数添加了一个长期请求的功能,以支持时序数据的 asof 风格连接(GH 1870, GH 13695, GH 13709, GH 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 13327, GH 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 7160, GH 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

当指定为 dtype 时,read_csv()函数现在支持解析Categorical列 (GH 10153)。根据数据的结构,这可能导致比解析后转换为Categorical更快的解析时间和更低的内存使用。请参阅 io 这里的文档。

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 

注意

结果类别将始终被解析为字符串(object dtype)。如果类别是数字的,可以使用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()用于合并分类变量,参见 Unioning Categoricals (GH 13361, GH 13763, GH 13846, GH 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 dtypes 连接为object dtype (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 号)和月初(1 号)。(GH 1543)

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

SemiMonthEnd:

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

SemiMonthBegin:

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 方法

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

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")
Out[57]: 
 digit
 match 
0 0         1
 1         2
1 0         1

[3 rows x 1 columns] 

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

Google BigQuery 增强

  • read_gbq() 方法增加了 dialect 参数,允许用户指定使用 BigQuery 的传统 SQL 还是标准 SQL。更多细节请参阅文档GH 13615)。

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

细粒度的 NumPy errstate

先前版本的 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 现在返回整数 dtype

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 中公开了类型内省函数。未来版本的 pandas 将发布更多的子包和官方认可的 API (GH 13147, GH 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 调用这些函数现在将显示一个 DeprecationWarning (GH 13990)。

其他增强功能

  • Timestamp 现在可以接受类似于 datetime.datetime() 的位置参数和关键字参数 (GH 10758, GH 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。默认行为仍然是引发 NonExistentTimeError (GH 13057)。

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

  • pd.read_csv() 使用 engine='python' 现已支持 decimal (GH 12933),na_filter (GH 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,在 dtype 为 categorical 时有效 (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 13535, GH 13536)。

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

  • 当使用convert_categoricals=True时,read_stata()StataReader在读取具有重复值标签的 Stata 文件时会引发一个更明确的错误消息(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。这也会影响到笔记本的 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,请参阅 行分隔的 json。(GH 9180)

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

  • groupby() 现在接受标量和单元素列表来指定非MultiIndex分组器上的 level。(GH 13907)

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

  • pd.Timedelta(None) 现在被接受,并将返回 NaT,与 pd.Timestamp 类似。(GH 13687)

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

  • SeriesIndex 现在支持 divmod,将返回系列或索引的元组。这与广播规则一致的标准二元运算符行为。(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 运算符已更改,使所有运算符保持一致,包括 DataFrame。(GH 1134, GH 4581, GH 13538)

  • index 不同时,Series 比较运算符现在会引发 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),仅保留左侧的index

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逻辑运算符将NaN结果填充为False

注意

要实现与先前版本相同的结果(仅基于左侧索引比较值),可以使用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。如果要比较具有不同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`。

**先前行为**:

```py
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时,没有正确地转换浮点数,导致截断的 datetime(GH 13834) ### 合并变更

合并现在将保留连接键的 dtype(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 

当然,如果引入了缺失值,那么结果的 dtype 将被提升,这与以前的情况相同。

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](https://github.com/pandas-dev/pandas/issues/13104))

```py
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

  • 在具有混合 dtype 列索引的 DataFrame 上的.describe()中存在错误,以前会引发TypeErrorGH 13288) ### Period变更

PeriodIndex现在具有period dtype

PeriodIndex现在有自己的period dtype。period dtype 是 pandas 的扩展 dtype,类似于category或时区感知 dtype(datetime64[ns, tz])(GH 13941)。由于这一变化,PeriodIndex不再具有整数 dtype:

以前的行为

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有自己的Period('NaT')表示形式,与pd.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 8227](https://github.com/pandas-dev/pandas/issues/8227), [GH 14127](https://github.com/pandas-dev/pandas/issues/14127))。

先前行为:

```py
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 现在与此行为保持一致。

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.difference` 和 `Index.symmetric_difference` 现在将更一致地将 `NaN` 值视为任何其他值。([GH 13514](https://github.com/pandas-dev/pandas/issues/13514))

```py
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()` 现在返回适当 `dtype` 的唯一值作为 `Index`。([GH 13395](https://github.com/pandas-dev/pandas/issues/13395))。以前,大多数 `Index` 类返回 `np.ndarray`,而 `DatetimeIndex`、`TimedeltaIndex` 和 `PeriodIndex` 返回 `Index` 以保留元数据,如时区。

**先前行为**:

```py
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` 构造函数,`groupby` 和 `set_index` 保留分类 dtype

`MultiIndex.from_arrays` 和 `MultiIndex.from_product` 现在将在 `MultiIndex` 级别中保留分类 dtype ([GH 13743](https://github.com/pandas-dev/pandas/issues/13743), [GH 13854](https://github.com/pandas-dev/pandas/issues/13854)).

```py
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 也在索引中保留了分类 dtype

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` 将逐步枚举块

当使用`chunksize=n`调用`read_csv()`,且没有指定索引时,每个块以前都会有独立生成的索引,从`0`到`n-1`。现在,它们被赋予递进的索引,从第一个块开始为`0`,第二个块为`n`,依此类推,以便在连接时与没有`chunksize=`参数调用`read_csv()`的结果相同([GH 12185](https://github.com/pandas-dev/pandas/issues/12185))。

```py
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 能够处理更多 dtype 的稀疏数据,并且使数据处理体验更加流畅。

#### 类型`int64`和`bool`支持增强

稀疏数据结构现在获得了对`int64`和`bool` `dtype`的增强支持([GH 667](https://github.com/pandas-dev/pandas/issues/667)[GH 13849](https://github.com/pandas-dev/pandas/issues/13849))。

以前,稀疏数据默认为`float64` dtype,即使所有输入都是`int`或`bool` dtype。您必须明确指定`dtype`才能创建具有`int64` dtype 的稀疏数据。此外,必须显式指定`fill_value`,因为默认值为`np.nan`,而`np.nan`不会出现在`int64`或`bool`数据中。

```py
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 起,稀疏数据保留输入的 dtype,并使用更合适的fill_value默认值(int64 dtype 为0bool dtype 为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) 

有关更多详细信息,请参见文档。

运算符现在会保留 dtype
  • 稀疏数据结构现在在算术操作后可以保留dtypeGH 13848
s = pd.SparseSeries([0, 2, 0, 1], fill_value=0, dtype=np.int64)
s.dtype

s + 1 
  • 稀疏数据结构现在支持astype以转换内部的dtypeGH 13900
s = pd.SparseSeries([1.0, 0.0, 2.0, 0.0], fill_value=0)
s
s.astype(np.int64) 

如果数据包含不能转换为指定dtype的值,则astype会失败。请注意,此限制适用于默认为np.nanfill_value

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

  • SparseArray中的bool dtype 现在支持逻辑(bool)运算符(GH 14000

  • 在使用MultiIndex []索引的SparseSeries中可能会引发IndexError错误(GH 13144

  • 在使用MultiIndex []索引的SparseSeries中可能出现普通Index的错误结果(GH 13144

  • SparseDataFrame中的错误,其中axis=None未默认为axis=0GH 13048

  • 在包含object dtype 的SparseSeriesSparseDataFrame中创建时可能会引发TypeError的错误(GH 11633

  • SparseDataFrame 中的 Bug 不遵循传递的 SparseArraySparseSeries 的 dtype 和 fill_value (GH 13866)

  • SparseArraySparseSeries 中的 Bug 不对 fill_value 应用 ufunc (GH 13853)

  • SparseSeries.abs 中的 Bug 不正确地保留了负的 fill_value (GH 13853)

  • 在多类型 SparseDataFrame 上进行单行切片的 Bug,以前强制类型为浮点数 (GH 13917)

  • SparseSeries 切片中的 Bug 会将整数 dtype 更改为浮点数 (GH 8292)

  • SparseDataFarme 中的比较操作 Bug 可能会引发 TypeError (GH 13001)

  • SparseDataFarme.isnull 中的 Bug 会引发 ValueError (GH 8276)

  • 使用 bool dtype 的 SparseSeries 表示中的 Bug 可能会引发 IndexError (GH 13110)

  • SparseSeriesSparseDataFrameboolint64 dtype 的 Bug 可能会显示其值,如同 float64 dtype 一样 (GH 13110)

  • 使用 SparseArraybool dtype 进行稀疏索引的 Bug 可能返回不正确的结果 (GH 13985)

  • SparseSeries 创建的 SparseArray 中的 Bug 可能会丢失 dtype (GH 13999)

  • SparseSeries 与密集返回正常 Series 而不是 SparseSeries 的比较中的 Bug (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](https://github.com/pandas-dev/pandas/issues/14101)).

+   具有日期时间和时区的`Series.unique()`现在返回带时区的`Timestamp`数组 ([GH 13565](https://github.com/pandas-dev/pandas/issues/13565)).

+   当调用`Panel.to_sparse()`时将会抛出`NotImplementedError`异常 ([GH 13778](https://github.com/pandas-dev/pandas/issues/13778)).

+   当调用`Index.reshape()`时将会抛出`NotImplementedError`异常 ([GH 12882](https://github.com/pandas-dev/pandas/issues/12882)).

+   `.filter()`强制互斥的关键字参数 ([GH 12399](https://github.com/pandas-dev/pandas/issues/12399)).

+   `eval`的`float32`类型的 upcasting 规则已更新为与 NumPy 的规则更一致。 如果您将 pandas 的`float32`对象乘以标量 float64,新行为将不会向上转换为`float64` ([GH 12388](https://github.com/pandas-dev/pandas/issues/12388)).

+   如果在 groupby 或 resample 对象上调用 NumPy ufuncs 如`np.mean`,现在会引发`UnsupportedFunctionCall`错误 ([GH 12811](https://github.com/pandas-dev/pandas/issues/12811)).

+   `__setitem__`将不再将可调用的 rhs 应用为函数而不是存储它。 直接调用`where`以获取以前的行为 ([GH 13299](https://github.com/pandas-dev/pandas/issues/13299)).

+   调用`.sample()`将尊重通过`numpy.random.seed(n)`设置的随机种子 ([GH 13161](https://github.com/pandas-dev/pandas/issues/13161))

+   `Styler.apply`现在对您的函数必须返回的输出更严格。 对于`axis=0`或`axis=1`,输出形状必须相同。 对于`axis=None`,输出必须是具有相同列和索引标签的 DataFrame ([GH 13222](https://github.com/pandas-dev/pandas/issues/13222)).

+   调用`Float64Index.astype(int)`现在如果`Float64Index`包含`NaN`值将会抛出`ValueError`异常 ([GH 13149](https://github.com/pandas-dev/pandas/issues/13149))

+   `TimedeltaIndex.astype(int)`和`DatetimeIndex.astype(int)`现在将返回`Int64Index`而不是`np.array` ([GH 13209](https://github.com/pandas-dev/pandas/issues/13209))

+   将多频率的`Period`传递给普通的`Index`现在将返回`object` dtype 的`Index` ([GH 13664](https://github.com/pandas-dev/pandas/issues/13664))

+   使用`Period`的`PeriodIndex.fillna`现在会强制转换为`object` dtype ([GH 13664](https://github.com/pandas-dev/pandas/issues/13664))

+   从`DataFrame.boxplot(by=col)`绘制的分面箱线图现在在`return_type`不为 None 时返回`Series`。 以前这些返回一个`OrderedDict`。 请注意,当`return_type=None`时,默认情况下,这些仍然返回一个 2-D NumPy 数组 ([GH 12216](https://github.com/pandas-dev/pandas/issues/12216), [GH 7096](https://github.com/pandas-dev/pandas/issues/7096)).

+   `pd.read_hdf`现在将在提供除`r`,`r+`和`a`之外的模式时引发`ValueError`而不是`KeyError`。 ([GH 13623](https://github.com/pandas-dev/pandas/issues/13623))

+   当在不存在的文件上调用`pd.read_csv()`、`pd.read_table()`和`pd.read_hdf()`时,Python 3.x 将引发内置的`FileNotFoundError`异常;这在 Python 2.x 中回溯为`IOError`([GH 14086](https://github.com/pandas-dev/pandas/issues/14086)+   csv 解析器会传递更多信息的异常。异常类型现在将是原始异常类型,而不是`CParserError`([GH 13652](https://github.com/pandas-dev/pandas/issues/13652))。

+   当`sep`编码超过一个字符长时,C 引擎中的`pd.read_csv()`现在会发出`ParserWarning`或引发`ValueError`([GH 14065](https://github.com/pandas-dev/pandas/issues/14065)+   `DataFrame.values`现在将返回`float64`,具有混合`int64`和`uint64` dtypes 的`DataFrame`,符合`np.find_common_type`([GH 10364](https://github.com/pandas-dev/pandas/issues/10364)[GH 13917](https://github.com/pandas-dev/pandas/issues/13917)+   `.groupby.groups`现在将返回一个`Index`对象的字典,而不是`np.ndarray`或`lists`的字典([GH 14293](https://github.com/pandas-dev/pandas/issues/14293)### `Series.tolist()`现在将返回 Python 类型

`Series.tolist()`现在将以 Python 类型返回输出,模仿 NumPy 的`.tolist()`行为([GH 10904](https://github.com/pandas-dev/pandas/issues/10904))

```py
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

  • index不同时,Series比较运算符现在会引发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),仅保留左侧index

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结果。

注意

要实现与先前版本相同的结果(仅基于左侧index比较值),可以使用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。如果要比较具有不同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 

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

算术运算符

算术运算符会对齐两个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]) 

如果要比较对齐其.indexSeries,请参见下面的灵活比较方法部分:

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),仅保留左侧index

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结果。

注意

要实现与先前版本相同的结果(仅基于左侧index比较值),可以使用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。如果要比较具有不同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现在会正确提升其 dtype,以便将不兼容值分配给当前 dtype(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()相关的错误修复:

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

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

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

  • errors='ignore'时,pd.to_datetime()中的错误会引发AttributeError,并且另一个字符串无效 (GH 12424)

  • 在指定unit时,pd.to_datetime()中的错误未正确转换浮点数,导致截断的日期时间 (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

  • 在具有混合数据类型列索引的 DataFrame 上调用.describe()时出现的错误,之前会引发TypeError (GH 13288)

Period更改

PeriodIndex现在具有period数据类型

PeriodIndex现在具有自己的period数据类型。period数据类型是一种类似于category或时区感知数据类型 (datetime64[ns, tz]) 的 pandas 扩展数据类型 (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 12759, GH 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) 
PeriodIndex现在具有period数据类型

PeriodIndex 现在具有自己的 period dtype。period dtype 是一个类似于 category 或 时区感知 dtype (datetime64[ns, tz]) 的 pandas 扩展 dtype。由于这个改变,PeriodIndex 不再具有整数 dtype。

先前的行为

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 具有自己的 Period('NaT') 表示,不同于 pd.NaT。现在,Period('NaT') 已经更改为返回 pd.NaT

先前的行为

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 对象的数组,而不是整数数组。

先前的行为

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 + / - 不再用于集合操作

先前的基本 Index 类型和 DatetimeIndex (而不是数值索引类型) 的加法和减法已经执行了集合操作 (集合并和差)。这个行为从 0.15.0 开始已经被弃用 (而使用特定的 .union().difference() 方法),现在已被禁用。现在尽可能使用 +- 进行逐元素操作,例如连接字符串或减去日期时间。

先前的行为:

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 已经与此行为保持一致。

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 值视为任何其他值。

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 返回。先前,大多数 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 保留分类 dtype

MultiIndex.from_arraysMultiIndex.from_product 现在将在MultiIndex级别中保留分类 dtype(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 也在索引中保留了分类 dtypes

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将逐步枚举块

当使用chunksize=n调用read_csv()并且没有指定索引时,每个块过去都有一个独立生成的索引,从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 处理更多 dtypes 的稀疏数据,并使数据处理体验更加顺畅。

类型int64bool支持增强

稀疏数据结构现在增强支持int64bool dtypeGH 667GH 13849)。

以前,稀疏数据默认情况下为float64 dtype,即使所有输入都是intbool dtype。您必须显式指定dtype才能创建具有int64 dtype的稀疏数据。此外,必须显式指定fill_value,因为默认值为np.nan,而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 开始,稀疏数据保留输入 dtype,并使用更合适的fill_value默认值(int64 dtype 为0bool dtype 为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) 

请参阅文档以了解更多详情。

操作符现在保留 dtypes
  • 稀疏数据结构现在可以在算术运算后保留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) 

如果数据包含无法转换为指定dtype的值,则astype会失败。请注意,这个限制适用于默认为np.nanfill_value

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)

  • SparseArraybool dtype 现在支持逻辑(bool)运算符(GH 14000

  • 使用MultiIndex [] 索引的SparseSeries的错误可能会引发IndexErrorGH 13144

  • 具有MultiIndex [] 索引的SparseSeries的错误可能具有普通的Index结果(GH 13144

  • SparseDataFrame中的错误,其中axis=None没有默认为axis=0GH 13048

  • 使用object dtype 创建SparseSeriesSparseDataFrame的错误可能会引发TypeErrorGH 11633

  • SparseDataFrame中的错误不尊重传递的SparseArraySparseSeries的 dtype 和fill_valueGH 13866

  • SparseArraySparseSeries中不应用 ufunc 到fill_value的错误(GH 13853

  • SparseSeries.abs中的错误不正确地保留了负的fill_valueGH 13853

  • 在多类型SparseDataFrame上的单行切片中的错误,之前类型被强制为浮点数(GH 13917

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

  • SparseDataFarme比较操作中的错误可能会引发TypeErrorGH 13001

  • SparseDataFarme.isnull中的错误引发了ValueErrorGH 8276

  • SparseSeries表示中带有bool dtype 的错误可能会引发IndexErrorGH 13110

  • 具有boolint64 dtype 的SparseSeriesSparseDataFrame的错误可能显示其值像float64 dtype 一样(GH 13110

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

  • SparseSeries创建的SparseArray中的错误可能会丢失dtypeGH 13999

  • 与密集比较的SparseSeries的错误返回普通的Series而不是SparseSeriesGH 13999

类型int64bool的支持增强

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

以前,即使所有输入都是 intbool dtype,稀疏数据默认为 float64 dtype。您必须显式指定 dtype 来创建具有 int64 dtype 的稀疏数据。此外,fill_value 必须显式指定,因为默认值为 np.nan,而 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 开始,稀疏数据保留输入的 dtype,并使用更合适的 fill_value 默认值(int64 dtype 为 0bool dtype 为 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) 

更多详情请参见文档。

现在运算符会保留 dtype
  • 稀疏数据结构现在可以在算术操作后保留 dtypeGH 13848
s = pd.SparseSeries([0, 2, 0, 1], fill_value=0, dtype=np.int64)
s.dtype

s + 1 
  • 稀疏数据结构现在支持 astype 来转换内部的 dtypeGH 13900
s = pd.SparseSeries([1.0, 0.0, 2.0, 0.0], fill_value=0)
s
s.astype(np.int64) 

如果数据包含不能转换为指定 dtype 的值,则 astype 失败。请注意,此限制适用于默认值为 np.nanfill_value

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 类型的 SparseArray 现在支持逻辑(bool)运算(GH 14000

  • MultiIndexSparseSeries 的 Bug 使用 [] 索引可能引发 IndexErrorGH 13144

  • MultiIndexSparseSeries 的 Bug 使用 [] 索引结果可能有普通的 IndexGH 13144

  • SparseDataFrame 中的 Bug,其中 axis=None 不会默认为 axis=0GH 13048

  • 使用 object dtype 创建 SparseSeriesSparseDataFrame 的 Bug 可能会引发 TypeErrorGH 11633

  • SparseDataFrame 中的 Bug 不遵循传递的 SparseArraySparseSeries 的 dtype 和 fill_valueGH 13866

  • SparseArraySparseSeries 中的 Bug 不会将 ufunc 应用到 fill_valueGH 13853

  • SparseSeries.abs 中的 Bug 错误地保留了负的 fill_valueGH 13853

  • 单行切片在多类型的 SparseDataFrame 上的 Bug,以前会被强制转换为 float 类型(GH 13917

  • SparseSeries 切片中的 Bug 会将整数 dtype 更改为 float 类型(GH 8292

  • SparseDataFarme 中的比较操作可能会引发 TypeError 的 Bug(GH 13001

  • SparseDataFarme.isnull 中的 Bug 引发 ValueErrorGH 8276

  • 使用bool dtype 的SparseSeries表示中的错误可能会引发IndexErrorGH 13110)。

  • 使用boolint64 dtype 的SparseSeriesSparseDataFrame中的错误可能会显示其值,例如float64 dtype(GH 13110).

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

  • SparseSeries创建的SparseArray中的错误可能会丢失dtypeGH 13999)。

  • 与密集返回普通Series而不是SparseSeriesSparseSeries比较中的错误已修复(GH 13999)。

索引器 dtype 更改

注意

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

返回索引器数组的方法(例如Index.get_indexer)会将该数组强制转换为“平台整数”,以便可以直接在第三方库操作(如numpy.take)中使用。以前,平台整数被定义为np.int_,它对应于 C 整数,但正确的类型,以及现在正在使用的类型是np.intp,它对应于可以容纳指针的 C 整数大小(GH 3033GH 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 相乘,则新行为不会提升为float64GH 12388)。

  • 现在,如果在分组或重采样对象上调用 NumPy 的 ufuncs(如np.mean)会引发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 包含 NaN 值,Float64Index.astype(int) 现在会引发 ValueError (GH 13149)

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

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

  • 使用 PeriodPeriodIndex.fillna 现在强制转换为 object dtype (GH 13664)

  • DataFrame.boxplot(by=col) 获得的分面箱线图现在在 return_type 不为 None 时返回 Series。以前这些返回一个 OrderedDict。请注意,当 return_type=None 时,默认情况下,这些仍然返回一个 2-D NumPy 数组 (GH 12216GH 7096).

  • 如果 pd.read_hdf 提供的模式不是 rr+a 中的一个,现在会引发 ValueError 而不是 KeyError。(GH 13623)

  • 当在不存在的文件上调用 pd.read_csv()pd.read_table()pd.read_hdf() 时,Python 3.x 中将引发内置的 FileNotFoundError 异常;在 Python 2.x 中将其作为 IOError 进行回退 (GH 14086)

  • csv 解析器传递更具信息性的异常。异常类型现在将是原始异常类型,而不是 CParserError (GH 13652).

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

  • DataFrame.values 现在会返回 float64 类型的混合 int64uint64 dtypes 的 DataFrame,符合 np.find_common_type 规范(GH 10364GH 13917

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

弃用

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

  • PeriodIndex.to_datetime 已被弃用,推荐使用 PeriodIndex.to_timestampGH 8254

  • Timestamp.to_datetime 已被弃用,推荐使用 Timestamp.to_pydatetimeGH 8254

  • Index.to_datetimeDatetimeIndex.to_datetime 已被弃用,推荐使用 pd.to_datetimeGH 8254

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

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

  • DataFrame.to_html()DataFrame.to_latex() 已删除 colSpace 参数,推荐使用 col_spaceGH 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 属性(以及构造函数中的命名参数)已被弃用,推荐使用 freqGH 12160

  • pd.tseries.util.pivot_annual 已被弃用。使用 pivot_table 作为替代,一个示例在这里(GH 736

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

  • Panel4DPanelND构造函数已被弃用,并将在将来的版本中移除。推荐表示这些类型的 n 维数据的方法是使用xarray package。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关键字已被弃用,转而使用freqGH 13874

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

移除之前版本的弃用/更改

  • SparsePanel类已被移除(GH 13778

  • pd.sandbox模块已被移除,转而使用外部库pandas-qtGH 13670

  • pandas.io.datapandas.io.wb模块已被移除,转而使用pandas-datareader packageGH 13724

  • pandas.tools.rplot模块已被移除,转而使用seaborn packageGH 13855

  • DataFrame.to_csv()已经放弃了engine参数,因为在 0.17.1 中已经弃用(GH 11274GH 13419

  • DataFrame.to_dict()已经放弃了outtype参数,转而使用orientGH 13627GH 8486

  • pd.Categorical已经放弃了直接设置ordered属性,转而使用set_ordered方法(GH 13671

  • pd.Categorical已经放弃了levels属性,转而使用categoriesGH 8376

  • DataFrame.to_sql()已经放弃了mysql选项,用于flavor参数(GH 13611

  • Panel.shift()已经放弃了lags参数,转而使用periodsGH 14041

  • pd.Index已经放弃了diff方法,转而使用differenceGH 13669

  • pd.DataFrame已经放弃了to_wide方法,转而使用to_panelGH 14039

  • Series.to_csv已经放弃了nanRep参数,转而使用na_repGH 13804

  • Series.xsDataFrame.xsPanel.xsPanel.major_xsPanel.minor_xs 已经移除了 copy 参数(GH 13781)。

  • str.split 已经放弃了 return_type 参数,改为使用 expand 参数(GH 13701)。

  • 移除了自 0.17.0 起已弃用的旧时间规则(偏移别名)(自 0.8.0 起已是别名)(GH 13590GH 13868)。现在,旧的时间规则会引发 ValueError。当前支持的偏移列表请参见这里。

  • DataFrame.plot.boxDataFrame.boxplotreturn_type 参数的默认值从 None 改为了 "axes"。这些方法现在默认返回一个 matplotlib axes,而不是一个艺术家字典。请参阅这里(GH 6581)。

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

性能改进

  • 改进了稀疏 IntIndex.intersect 的性能(GH 13082)。

  • 当块数较大时,通过稀疏算术与 BlockIndex 的性能得到了改进,尽管在这种情况下建议使用 IntIndexGH 13082)。

  • DataFrame.quantile() 的性能得到了改进,现在它是基于块操作的(GH 11623)。

  • 通过改进 float64 哈希表操作的性能,修复了一些 Python 3 中非常慢的索引和 groupby 操作(GH 13166GH 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)

修复的 bug

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

  • groupby().cumsum()中存在的一个 bug,在axis=1时计算cumprod。(GH 13994)

  • pd.to_timedelta()中存在的一个 bug,未能尊重errors参数。(GH 13613)

  • io.json.json_normalize()中存在的一个 bug,非 ASCII 键会引发异常。(GH 13213)

  • .plot()中将非默认索引的Series作为xerryerr传递时存在的一个 bug。(GH 11858)

  • 在区域图绘制中存在的一个 bug,如果启用了子图或在绘图后移动图例,图例会被错误地绘制(需要 matplotlib 1.5.0 才能正确绘制区域图图例)。(GH 9161, GH 13544)

  • 在使用对象数据类型Index进行DataFrame赋值时存在的一个 bug,导致结果列对原始对象可变。(GH 13522)

  • 在 matplotlib AutoDataFormatter中存在的一个 bug;这将恢复第二个缩放格式并重新添加微秒缩放格式。(GH 13131)

  • 在使用固定格式和指定start和/或stopHDFStore进行选择时,现在将返回所选范围。(GH 8287)

  • Categorical.from_codes()中存在的一个 bug,当传递无效的ordered参数时会引发一个无用的错误。(GH 14058)

  • 在 Windows 上从整数元组构建Series时未返回默认的数据类型(int64)的 bug。(GH 13646)

  • TimedeltaIndex与类似日期时间对象相加时存在的一个 bug,未能捕获加法溢出。(GH 14068)

  • 在多次调用相同对象时,.groupby(..).resample(..)中存在的一个 bug。(GH 13174)

  • 在索引名称为 Unicode 字符串时,.to_records()中存在的一个 bug。(GH 13172)

  • 在调用未实现的对象上的.memory_usage()中存在的一个 bug。(GH 12924)

  • 具有 nans 的Series.quantile中的回归(也出现在.median().describe()中);此外,现在使用分位数命名SeriesGH 13098GH 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数据类型的错误(GH 13324

  • 可能会忽略np.datetime64('nat')np.timdelta64('nat')以推断数据类型的错误(GH 13324

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

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

  • 使用空时,.resample(..)中的PeriodIndex不会适当地更改其freq的错误(GH 13067

  • 使用空DataFrame时,.resample(..)中的PeriodIndex不会保留其类型或名称的错误(GH 13212

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

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

  • 依赖于索引排序以获得正确结果的 tz-awareDateTimeIndex上的.tz_convert中的错误(GH 13306

  • 使用dateutil.tz.tzlocal.tz_localize可能返回不正确的结果的错误(GH 13583

  • 使用dateutil.tz.tzlocalDatetimeTZDtype数据类型无法被视为有效数据类型的错误(GH 13583

  • Bug in pd.read_hdf() 在尝试加载具有单个数据集且具有一个或多个分类列的 HDF 文件时失败,除非将 key 参数设置为数据集的名称。(GH 13231)

  • Bug in .rolling() 允许在构建 Rolling() 对象时使用负整数窗口,但在聚合时会失败。(GH 13383)

  • Bug in 使用元组值数据和数值索引的 Series 索引。(GH 13509)

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

  • Bug in 排名 Series 可能导致段错误。(GH 13445)

  • Bug in 各种索引类型,未传播传递的索引名称。(GH 12309)

  • Bug in DatetimeIndex,未遵守 copy=True。(GH 13205)

  • Bug in DatetimeIndex.is_normalized 对于本地时区的规范化 date_range 返回不正确。(GH 13459)

  • Bug in pd.concat.append 可能会将 datetime64timedelta 强制转换为包含 Python 内置 datetimetimedelta 而不是 TimestampTimedeltaobject dtype。(GH 13626)

  • Bug in PeriodIndex.append 当结果为 object dtype 时可能引发 AttributeError。(GH 13221)

  • Bug in CategoricalIndex.append 可能接受普通的 list。(GH 13626)

  • Bug in pd.concat.append 具有相同时区时,会重置为 UTC。(GH 7795)

  • Bug in SeriesDataFrame .append 如果���据包含接近 DST 边界的日期时间,则引发 AmbiguousTimeError。(GH 13626)

  • Bug in DataFrame.to_csv() 中,即使仅为非数字值指定引号,浮点值也被引用。(GH 12922, GH 13259)

  • Bug in DataFrame.describe() 仅包含布尔列时引发 ValueError。(GH 13898)

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

  • Bug in .str.replace 对于无效的替换不会引发 TypeError。(GH 13438)

  • Bug in MultiIndex.from_arrays 未检查输入数组长度是否匹配。(GH 13599)

  • cartesian_productMultiIndex.from_product 中存在一个 bug,可能会因为空输入数组而引发错误(GH 12258)。

  • 在极少情况下,使用大块数据流/文件进行迭代时,pd.read_csv() 中存在一个 bug,可能导致 segfault 或数据损坏(GH 13703)。

  • pd.read_csv() 中存在一个 bug,当传递包含标量的字典作为 na_values 参数时,会引发错误(GH 12224)。

  • pd.read_csv() 中存在一个 bug,由于未忽略 BOM(字节顺序标记),导致 BOM 文件被错误解析(GH 4793)。

  • pd.read_csv() 中存在一个 bug,当传递一个 numpy 数组作为 usecols 参数时,会引发错误(GH 12546)。

  • 当使用 thousands 参数解析日期时,pd.read_csv() 中的索引列被错误解析为日期(GH 14066)。

  • pd.read_csv() 中存在一个 bug,当数据被转换为数值后,未能正确检测到 NaN 值(GH 13314)。

  • 在两种引擎中,pd.read_csv() 中的 nrows 参数未被正确验证(GH 10476)。

  • pd.read_csv() 中存在一个 bug,未能正确解释大小写混合形式的无穷大数值(GH 13274)。

  • pd.read_csv() 中存在一个 bug,当 engine='python' 时,尾随的 NaN 值未被解析(GH 13320)。

  • 在 Windows 中使用 Python 3 时,从 tempfile.TemporaryFile 读取时,pd.read_csv() 中存在一个 bug(GH 13398)。

  • pd.read_csv() 中存在一个 bug,阻止 usecols 参数接受单字节 Unicode 字符串(GH 13219)。

  • pd.read_csv() 中存在一个 bug,阻止 usecols 参数为空集合(GH 13402)。

  • 在 C 引擎中,pd.read_csv() 存在一个 bug,未能将 NULL 字符解析为 NULL(GH 14012)。

  • pd.read_csv() 中存在一个 bug,当 quoting 被指定为 None 时,不接受 NULL 的 quotechar,即使 quoting 参数被指定为 NoneGH 13411)。

  • pd.read_csv() 中存在一个 bug,当引号被指定为非数值时,字段未正确转换为浮点数(GH 13411)。

  • 在 Python 2.x 中,pd.read_csv() 存在一个 bug,处理非 UTF8 编码的、多字符分隔的数据时会出现问题(GH 3404)。

  • pd.read_csv() 中,utf-xx 的别名(例如 UTF-xx、UTF_xx、utf_xx)引发了 UnicodeDecodeError。(GH 13549

  • pd.read_csvpd.read_tablepd.read_fwfpd.read_statapd.read_sas 中,如果 chunksizeiterator 都是 None,则解析器打开但未关闭文件。(GH 13940

  • StataReaderStataWriterXportReaderSAS7BDATReader 中存在的 Bug,在出现错误时未正确关闭文件。(GH 13940

  • pd.pivot_table() 中,当 aggfunc 是列表时,会忽略 margins_name。(GH 13354

  • pd.Series.str.zfillcenterljustrjustpad 中传递非整数时,未引发 TypeError。(GH 13598

  • 在检查 TimedeltaIndex 中是否存在任何空对象时,始终返回 True。(GH 13603

  • Series 进行算术运算时,如果包含 object dtype 的日期时间,则引发 TypeError。(GH 13043

  • Series.isnull()Series.notnull() 中忽略 Period('NaT')。(GH 13737

  • Series.fillna()Series.dropna() 中不影响 Period('NaT')。(GH 13737

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

  • 在扩展 dtype 创建中存在的 Bug,创建的类型不是 / 不完全相同。(GH 13285

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

  • NaT - Period 中引发 AttributeError。(GH 13071

  • Series 比较中,如果 rhs 包含 NaT,可能会输出错误的结果。(GH 9005

  • SeriesIndex 比较中,如果包含 object dtype 的 NaT,可能会输出不正确的结果。(GH 13592

  • Period 相加时,如果右侧是 Period,会引发 TypeError。(GH 13069

  • PeriodSeriesIndex 比较中引发 TypeError。(GH 13200

  • Bug in pd.set_eng_float_format() 会导致 NaN 和 Inf 的格式化失败(GH 11981

  • .unstack 中,使用 Categorical dtype 会重置 .orderedTrue。(GH 13249

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

  • factorize中存在错误,如果数据包含接近 DST 边界的日期时间,则会引发AmbiguousTimeErrorGH 13750

  • .set_index中存在错误,如果新索引包含 DST 边界和多级时会引发AmbiguousTimeErrorGH 12920

  • 在数据包含接近 DST 边界的日期时间时,使用.shift会引发AmbiguousTimeError的错误(GH 13926

  • pd.read_hdf()中存在错误,当DataFrame具有categorical列且查询不匹配任何值时,返回的结果可能不正确(GH 13792

  • 在使用非 lexsorted MultiIndex 进行索引时,使用.iloc存在错误(GH 13797

  • 在使用日期字符串进行索引时,如果是逆排序的DatetimeIndex,在.loc中存在错误(GH 14316

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

  • .combine_first中存在错误,可能会返回不正确的dtypeGH 7630GH 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

  • 在使用pd.to_numeric时存在错误,当errors='coerce'且输入包含非可哈希对象时(GH 13324

  • 在无效的Timedelta算术和比较中可能会引发ValueError而不是TypeErrorGH 13624

  • to_datetimeDatetimeIndex中存在无效日期时间解析的错误,可能会引发TypeError而不是ValueErrorGH 11169GH 11287

  • 在使用时区感知的Timestamp创建的Index中存在错误,并且tz选项不匹配时,会错误地强制转换时区(GH 13692

  • 在纳秒频率的DatetimeIndex中存在错误,不包括使用end指定的时间戳(GH 13672

  • Series 中存在 Bug,在使用 np.timedelta64 设置切片时 (GH 14155)

  • Index 中存在 Bug,如果 datetime 超出 datetime64[ns] 的范围,则会引发 OutOfBoundsDatetime 错误,而不是强制转换为 object 数据类型 (GH 13663)

  • Index 中存在 Bug,可能会忽略作为 dtype 传递的指定的 datetime64timedelta64 (GH 13981)

  • RangeIndex 中存在 Bug,可以创建无参数的 RangeIndex 而不是引发 TypeError (GH 13793)

  • .value_counts() 中存在 Bug,如果数据超出 datetime64[ns] 的范围,则会引发 OutOfBoundsDatetime 错误 (GH 13663)

  • DatetimeIndex 中存在 Bug,如果输入的 np.datetime64 单位不是 ns,可能会引发 OutOfBoundsDatetime 错误 (GH 9114)

  • 在创建具有其他单位而不是 nsnp.datetime64Series 时存在 Bug,将 object 数据类型结果设置为不正确的值 (GH 13876)

  • 在带有 timedelta 数据的 resample 中存在 Bug,数据被转换为浮点数 (GH 13119)

  • 使用 pd.isnull()pd.notnull() 存在 Bug,如果输入的日期时间类型不是 ns 单位,则会引发 TypeError (GH 13389)

  • pd.merge() 中存在 Bug,如果输入的日期时间类型不是 ns 单位,则可能会引发 TypeError (GH 13389)

  • HDFStore/read_hdf() 中存在 Bug,如果设置了 tz,则会丢弃 DatetimeIndex.name (GH 13884)

  • Categorical.remove_unused_categories() 中存在 Bug,会将 .codes 的数据类型更改为平台整数 (GH 13261)

  • groupby 中存在 Bug,使用 as_index=False 在多个列上进行分组时,包括一个分类列,会返回所有 NaN 值 (GH 13204)

  • df.groupby(...)[...] 中存在 Bug,在使用 Int64Index 进行取项时可能会引发错误 (GH 13731)

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

  • pd.read_gbq() 中存在 Bug,可能会引发 ImportError: No module named discovery,因为与另一个名为 apiclient 的 python 包存在命名冲突 (GH 13454)

  • Index.union 中存在 Bug,在具有命名空索引的情况下返回错误的结果 (GH 13432)

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

  • 将具有时区的 datetime.datetime 从具有时区的 datetime64 series 中减去的 bug (GH 14088)

  • 当 DataFrame 包含具有 NaN 值的标签的 MultiIndex 时,在 .to_excel() 中存在 bug (GH 13511)

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

  • 对于具有 RangeIndex 索引级别的分层框架,在 concatgroupby 中存在 bug (GH 13542)。

  • 对于只包含 object dtype 的 NaN 值的 Series,Series.str.contains() 中存在 bug (GH 14171)

  • 在 groupby dataframe 上的 agg() 函数中存在 bug,会将 datetime64[ns] 列的 dtype 更改为 float64 (GH 12821)

  • 使用 NumPy 的 ufunc 与 PeriodIndex 结合使用进行整数加法或减法会引发 IncompatibleFrequency 错误。建议使用标准运算符如 +-,因为标准运算符使用更高效的路径 (GH 13980)

  • 在对 NaT 进行操作时返回 float 而不是 datetime64[ns] 的 bug (GH 12941)

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

  • 在具有 MultiIndex 列的 DataFrame.to_csv() 中添加了多余的空行的 bug (GH 6618)

  • DatetimeIndexTimedeltaIndexPeriodIndex.equals() 中存在 bug,当输入不是 Index 但包含相同值时可能返回 True (GH 13107)

  • 在具有时区的 datetime 进行赋值时可能不起作用,如果它包含接近 DST 边界的 datetime (GH 14146)

  • pd.eval()HDFStore 查询中,使用 python 2 会截断长浮点数文字的 bug (GH 14241)

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

  • 当频率具有组合偏移别名时,PeriodPeriodIndex 创建错误日期的 bug (GH 13874)

  • 在带有整数 line_widthindex=False 的情况下调用 .to_string() 时会引发 UnboundLocalError 异常,因为 idx 在赋值之前被引用。

  • eval() 中的错误,resolvers 参数不接受列表(GH 14095

  • stackget_dummiesmake_axis_dummies 中的错误,不会保留(多重)索引中的分类数据类型(GH 13854

  • PeriodIndex 现在可以接受包含 pd.NaTlistarrayGH 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) +
    )

  • Index 中存在 Bug,如果 datetime 超出 datetime64[ns] 的范围,则会引发 OutOfBoundsDatetime 错误,而不是强制转换为 object 数据类型 (GH 13663)

  • Index 中存在 Bug,可能会忽略作为 dtype 传递的指定的 datetime64timedelta64 (GH 13981)

  • RangeIndex 中存在 Bug,可以创建无参数的 RangeIndex 而不是引发 TypeError (GH 13793)

  • .value_counts() 中存在 Bug,如果数据超出 datetime64[ns] 的范围,则会引发 OutOfBoundsDatetime 错误 (GH 13663)

  • DatetimeIndex 中存在 Bug,如果输入的 np.datetime64 单位不是 ns,可能会引发 OutOfBoundsDatetime 错误 (GH 9114)

  • 在创建具有其他单位而不是 nsnp.datetime64Series 时存在 Bug,将 object 数据类型结果设置为不正确的值 (GH 13876)

  • 在带有 timedelta 数据的 resample 中存在 Bug,数据被转换为浮点数 (GH 13119)

  • 使用 pd.isnull()pd.notnull() 存在 Bug,如果输入的日期时间类型不是 ns 单位,则会引发 TypeError (GH 13389)

  • pd.merge() 中存在 Bug,如果输入的日期时间类型不是 ns 单位,则可能会引发 TypeError (GH 13389)

  • HDFStore/read_hdf() 中存在 Bug,如果设置了 tz,则会丢弃 DatetimeIndex.name (GH 13884)

  • Categorical.remove_unused_categories() 中存在 Bug,会将 .codes 的数据类型更改为平台整数 (GH 13261)

  • groupby 中存在 Bug,使用 as_index=False 在多个列上进行分组时,包括一个分类列,会返回所有 NaN 值 (GH 13204)

  • df.groupby(...)[...] 中存在 Bug,在使用 Int64Index 进行取项时可能会引发错误 (GH 13731)

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

  • pd.read_gbq() 中存在 Bug,可能会引发 ImportError: No module named discovery,因为与另一个名为 apiclient 的 python 包存在命名冲突 (GH 13454)

  • Index.union 中存在 Bug,在具有命名空索引的情况下返回错误的结果 (GH 13432)

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

  • 将具有时区的 datetime.datetime 从具有时区的 datetime64 series 中减去的 bug (GH 14088)

  • 当 DataFrame 包含具有 NaN 值的标签的 MultiIndex 时,在 .to_excel() 中存在 bug (GH 13511)

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

  • 对于具有 RangeIndex 索引级别的分层框架,在 concatgroupby 中存在 bug (GH 13542)。

  • 对于只包含 object dtype 的 NaN 值的 Series,Series.str.contains() 中存在 bug (GH 14171)

  • 在 groupby dataframe 上的 agg() 函数中存在 bug,会将 datetime64[ns] 列的 dtype 更改为 float64 (GH 12821)

  • 使用 NumPy 的 ufunc 与 PeriodIndex 结合使用进行整数加法或减法会引发 IncompatibleFrequency 错误。建议使用标准运算符如 +-,因为标准运算符使用更高效的路径 (GH 13980)

  • 在对 NaT 进行操作时返回 float 而不是 datetime64[ns] 的 bug (GH 12941)

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

  • 在具有 MultiIndex 列的 DataFrame.to_csv() 中添加了多余的空行的 bug (GH 6618)

  • DatetimeIndexTimedeltaIndexPeriodIndex.equals() 中存在 bug,当输入不是 Index 但包含相同值时可能返回 True (GH 13107)

  • 在具有时区的 datetime 进行赋值时可能不起作用,如果它包含接近 DST 边界的 datetime (GH 14146)

  • pd.eval()HDFStore 查询中,使用 python 2 会截断长浮点数文字的 bug (GH 14241)

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

  • 当频率具有组合偏移别名时,PeriodPeriodIndex 创建错误日期的 bug (GH 13874)

  • 在带有整数 line_widthindex=False 的情况下调用 .to_string() 时会引发 UnboundLocalError 异常,因为 idx 在赋值之前被引用。

  • eval() 中的错误,resolvers 参数不接受列表(GH 14095

  • stackget_dummiesmake_axis_dummies 中的错误,不会保留(多重)索引中的分类数据类型(GH 13854

  • PeriodIndex 现在可以接受包含 pd.NaTlistarrayGH 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) +

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值