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

这是从0.18.1版本以来的一个重大发布,包括许多API更改、几个新功能、增强功能和性能改进,以及大量错误修复。我们建议所有用户升级到此版本。

亮点包括:

  • merge_asof() 用于 asof 样式的时间序列连接,请参见 这里

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

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

  • 已添加一个函数 union_categorical() 用于组合分类,请参见 这里

  • PeriodIndex 现在有了自己的 period 数据类型,并且变得更与其他 Index 类一致。请参见 这里

  • 稀疏数据结构对 intbool dtypes 的支持得到了增强,详见 这里

  • Series 的比较操作不再忽略索引,有关 API 更改的概述,请参见 这里

  • 介绍一个用于实用函数的 pandas 开发 API,请参见 这里

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

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

警告

pandas >= 0.19.0 在导入时将不再静默 numpy ufunc 警告,请参见 这里

新功能#

函数 merge_asof 用于 asof 样式的时间序列连接#

通过 merge_asof() 函数添加了一个长期请求的功能,以支持时间序列的 asof 风格连接(GH 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 /home/pandas/pandas/io/parsers/readers.py:849, 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, skip_blank_lines, parse_dates, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, low_memory, memory_map, float_precision, storage_options, dtype_backend)
    837 kwds_defaults = _refine_defaults_read(
    838     dialect,
    839     delimiter,
   (...)
    845     dtype_backend=dtype_backend,
    846 )
    847 kwds.update(kwds_defaults)
--> 849 return _read(filepath_or_buffer, kwds)

File /home/pandas/pandas/io/parsers/readers.py:707, in _read(filepath_or_buffer, kwds)
    704 nrows = kwds.get("nrows", None)
    706 # Check for duplicates in names.
--> 707 _validate_names(kwds.get("names", None))
    709 # Create the parser.
    710 parser = TextFileReader(filepath_or_buffer, **kwds)

File /home/pandas/pandas/io/parsers/readers.py:661, in _validate_names(names)
    659 if names is not None:
    660     if len(names) != len(set(names)):
--> 661         raise ValueError("Duplicate names are not allowed.")
    662     if not (
    663         is_list_like(names, allow_sets=False) or isinstance(names, abc.KeysView)
    664     ):
    665         raise ValueError("Names should be an ordered collection.")

ValueError: Duplicate names are not allowed.

方法 read_csv 支持直接解析 Categorical#

read_csv() 函数现在支持在指定为 dtype 时解析 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

备注

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

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

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

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

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

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

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

分类级联#

  • 已添加一个函数 union_categoricals() 用于组合分类,请参见 组合分类 (GH 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 中,以使其与 SeriesDataFrame API 更加一致。

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

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

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

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

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

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

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

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

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

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

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

Index 现在支持 .str.extractall() ,它返回一个 DataFrame ,请参阅 这里的文档 (GH 10008, GH 13156)

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

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

[3 rows x 1 columns]

Index.astype() 现在接受一个可选的布尔参数 copy,它允许在满足 dtype 要求的情况下进行可选复制 (GH 13209)

Google BigQuery 增强功能#

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

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

细粒度的 NumPy errstate#

在 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 中将值向下转换为可能的最小 dtype#

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

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

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

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

pandas 开发 API#

作为使 pandas API 在未来更加统一和可访问的一部分,我们创建了一个标准的 pandas 子包 pandas.api 来存放公共 API。我们首先在 pandas.api.types 中公开了类型自省函数。更多子包和官方认可的 API 将在未来版本的 pandas 中发布 (GH 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_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.Path, py.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_values, converters, keep_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 属性,类似于 Index (GH 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,而不是引发 ValueError (GH 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 中混合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 访问器获得了一个 .is_leap_year 属性,用于检查日期是否属于闰年。(GH 13727)

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

  • pd.read_jsonDataFrame.to_json 增加了对使用 lines 选项读写 json lines 的支持,参见 行分隔的 json (GH 9180)

  • read_excel() 现在支持 true_values 和 false_values 关键字参数 (GH 13347)

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

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

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

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

  • SeriesIndex 现在支持 divmod,这将返回一个系列或索引的元组。这行为类似于标准二元运算符,关于广播规则 (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)

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

  • Series 逻辑运算符对齐左右两侧的 index

警告

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

因此,SeriesDataFrame 操作符的行为如下:

算术运算符#

算术运算符对齐 ``index``(无变化)。

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

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

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

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

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

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

[4 rows x 1 columns]

比较运算符#

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

之前的行为 (Series):

Series 比较值时忽略 .index,只要两者长度相同:

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

新行为 (Series):

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

备注

要达到与以前版本相同的结果(基于位置比较值忽略 .index),请比较两者的 .values

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

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

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

当前行为 (DataFrame, 无变化):

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

逻辑运算符#

逻辑运算符对齐左右两侧的 .index

之前的行为 (Series),只保留了左边的 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 灵活的比较方法如 eq, ne, le, lt, gegt 现在对齐两个 index。如果你想比较两个具有不同 indexSeries,请使用这些运算符。

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

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

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

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

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

Series 在赋值时的类型提升#

一个 Series 现在会正确地将其数据类型提升为与当前数据类型不兼容的赋值 (GH 13234)

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

之前的行为:

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

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

新行为:

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

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

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

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

函数 .to_datetime() 转换#

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

之前的行为:

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

当前行为:

这将现在使用默认单位 ns 转换整数/浮点数。

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

.to_datetime() 相关的错误修复:

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

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

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

  • pd.to_datetime() 中的错误在 NaN 和另一个字符串无效时引发 AttributeErrorerrors='ignore' 时 (GH 12424)

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

合并更改#

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

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

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

[1 rows x 2 columns]

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

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

[2 rows x 2 columns]

之前的行为:

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

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

新行为:

我们能够保留连接键

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

[3 rows x 2 columns]

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

当然,如果你引入了缺失值,那么结果的 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)

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 数据类型是 pandas 扩展数据类型,类似于 category时区感知数据类型 (datetime64[ns, tz]) (GH 13941)。因此,PeriodIndex 不再具有整数数据类型:

之前的行为:

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

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

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

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

新行为:

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

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

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

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

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

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

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

之前,Period 有其自己的 Period('NaT') 表示,不同于 pd.NaT。现在 Period('NaT') 已被改为返回 pd.NaT。(GH 12759, GH 13582)

之前的行为:

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

新行为:

这些结果会导致 pd.NaT 而不提供 freq 选项。

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, GH 14127)。

之前的行为:

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

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

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

请注意,数字索引对象已经执行了逐元素操作。例如,添加两个整数索引的行为保持不变。基础 Index 现在与这种行为保持一致。

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[s]', freq=None)

Index.difference.symmetric_difference 变化#

Index.differenceIndex.symmetric_difference 现在将更一致地对待 NaN 值,如同对待其他值一样。(GH 13514)

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

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

之前的行为:

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

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

新行为:

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

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

Index.unique 始终返回 Index#

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

之前的行为:

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

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

新行为:

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

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

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

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

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

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

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

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

之前的行为:

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

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

新行为:现在单层是一个 CategoricalIndex

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

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

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

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

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

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

之前的行为:

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

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

新行为:

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

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

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

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

函数 read_csv 将逐步枚举块#

当使用 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 处理更多数据类型的稀疏数据,并致力于使数据处理体验更加流畅。

类型 int64bool 支持增强功能#

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

之前,稀疏数据默认是 float64 数据类型,即使所有输入都是 intbool 数据类型。你必须显式指定 dtype 来创建 int64 数据类型的稀疏数据。此外,必须显式指定 fill_value,因为默认值是 np.nan,它不出现在 int64bool 数据中。

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

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

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

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

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

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

更多详情请参见 文档

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

  • 稀疏数据结构现在可以在算术运算后保留 dtype (GH 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 数据类型现在支持逻辑(布尔)运算符 (GH 14000)

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

  • SparseSeries 中使用 MultiIndex [] 索引可能导致结果具有普通 Index 的错误 (GH 13144)

  • SparseDataFrame 中的一个错误,其中 axis=None 没有默认设置为 axis=0 (GH 13048)

  • SparseSeriesSparseDataFrame 创建时,使用 object 数据类型可能会引发 TypeError (GH 11633)

  • SparseDataFrame 中的错误不尊重传递的 SparseArraySparseSeries 的 dtype 和 fill_value (GH 13866)

  • SparseArraySparseSeries 中的错误不会将 ufunc 应用于 fill_value (GH 13853)

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

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

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

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

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

  • bool dtype 的 SparseSeries 表示中存在一个错误,可能会引发 IndexError (GH 13110)

  • SparseSeriesSparseDataFrame 中的 boolint64 数据类型中的错误可能会像 float64 数据类型一样显示其值 (GH 13110)

  • 使用 SparseArraybool 数据类型进行稀疏索引时可能返回不正确的结果 (GH 13985)

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

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

索引器数据类型更改#

备注

此更改仅影响在 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 更改#

  • Timestamp.to_pydatetimewarn=True 时会发出一个 UserWarning,当实例有非零的纳秒数时,之前这会打印一条消息到标准输出 (GH 14101)。

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

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

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

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

  • evalfloat32 类型的上转换规则已更新,以更符合 NumPy 的规则。新行为在将 pandas float32 对象乘以标量 float64 时不会上转换为 float64 (GH 12388)。

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

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

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

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

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

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

  • Period 以多个频率传递给普通的 Index 现在返回 Index 并带有 object 数据类型 (GH 13664)

  • PeriodIndex.fillna 使用 Period 现在强制转换为 object 数据类型 (GH 13664)

  • 来自 DataFrame.boxplot(by=col) 的分面箱线图现在在 return_type 不为 None 时返回一个 Series。以前这些返回一个 OrderedDict。请注意,当 return_type=None 时,默认情况下,这些仍然返回一个二维的 NumPy 数组 (GH 12216, GH 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 现在将在包含混合 int64uint64 类型的 DataFrame 中返回 float64,符合 np.find_common_type (GH 10364, GH 13917)

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

弃用#

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

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

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

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

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

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

  • DataFrame.to_html()DataFrame.to_latex() 已经弃用了 colSpace 参数,改为使用 col_space (GH 13857)

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

  • 已弃用的 read_csv 关键字:

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

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

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

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

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

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

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

  • pd.tseries.util.isleapyear 已被弃用,并将在后续版本中移除。类似日期时间的对象现在有一个 .is_leap_year 属性 (GH 13727)

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

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

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

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

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

  • SparsePanel 类已被移除 (GH 13778)

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

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

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

  • DataFrame.to_csv() 已经移除了 engine 参数,因为这在 0.17.1 版本中已被弃用 (GH 11274, GH 13419)

  • DataFrame.to_dict() 已经移除了 outtype 参数,改为使用 orient (GH 13627, GH 8486)

  • pd.Categorical 已经取消了直接设置 ordered 属性的功能,改为使用 set_ordered 方法 (GH 13671)

  • pd.Categorical 已经弃用了 levels 属性,改为使用 categories (GH 8376)

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

  • Panel.shift() 已经取消了 lags 参数,改为使用 periods (GH 14041)

  • pd.Index 已经弃用了 diff 方法,转而使用 difference (GH 13669)

  • pd.DataFrame 已经弃用了 to_wide 方法,转而使用 to_panel 方法 (GH 14039)

  • Series.to_csv 已经取消了 nanRep 参数,改为使用 na_rep (GH 13804)

  • Series.xs, DataFrame.xs, Panel.xs, Panel.major_xs, 和 Panel.minor_xs 已经移除了 copy 参数 (GH 13781)

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

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

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

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

性能提升#

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

  • 当块的数量很大时,使用 BlockIndex 改进了稀疏算术的性能,尽管在这种情况下推荐使用 IntIndex (GH 13082)

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

  • 改进了 float64 哈希表操作的性能,修复了 Python 3 中一些非常慢的索引和分组操作 (GH 13166, GH 13334)

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

  • 改进了 IndexSeries .duplicated 的性能 (GH 10235)

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

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

  • DatetimeIndex 中提高了日期时间字符串解析的性能 (GH 13692)

  • 改进了 Period 的哈希性能 (GH 12817)

  • 改进了带时区的 factorize 的性能 (GH 13750)

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

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

  • 在检查内存使用情况时,不必要的 MultiIndex 具体化 (GH 14308)

错误修复#

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

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

  • pd.to_timedelta() 中的一个错误,其中 errors 参数未被尊重 (GH 13613)

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

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

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

  • DataFrame 赋值中存在一个错误,当 Index 是对象类型时,结果列可以变异为原始对象。(GH 13522)

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

  • 在使用固定格式和指定 start 和/或 stopHDFStore 中选择时存在的错误,现在将返回所选范围 (GH 8287)

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

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

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

  • 当同一个对象被多次调用时,.groupby(..).resample(..) 中的错误 (GH 13174)

  • 当索引名称为一个unicode字符串时,.to_records() 中的错误 (GH 13172)

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

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

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

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

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

  • Series.str.extractall() 中使用 str 索引引发 ValueError 的错误 (GH 13156)

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

  • DatetimeIndexPeriod 减法中的错误引发 ValueErrorAttributeError 而不是 TypeError (GH 13078)

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

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

  • PeriodIndexPeriod 减法中的错误引发 AttributeError (GH 13071)

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

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

  • .resample(..) 中使用 PeriodIndex 时,当 DataFrame 为空时,未能适当保留其类型或名称的错误 (GH 13212)

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

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

  • 在依赖于索引排序以获得正确结果的时区感知 DateTimeIndex 上的 .tz_convert 中的错误 (GH 13306)

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

  • DatetimeTZDtype dtype 中使用 dateutil.tz.tzlocal 的错误不能被视为有效 dtype (GH 13583)

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

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

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

  • 在打印 pd.DataFrame 时存在一个错误,其中 object dtype 的异常元素导致段错误 (GH 13717)

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

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

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

  • DatetimeIndex.is_normalized 中的错误在本地时区的情况下对规范化的 date_range 返回不正确 (GH 13459)

  • pd.concat.append 中的错误可能会将 datetime64timedelta 强制转换为包含 python 内置 datetimetimedeltaobject 数据类型,而不是 TimestampTimedelta (GH 13626)

  • PeriodIndex.append 中的错误可能会在结果为 object 类型时引发 AttributeError (GH 13221)

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

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

  • SeriesDataFrame.append 中的错误在数据包含接近夏令时边界的时间时会引发 AmbiguousTimeError (GH 13626)

  • DataFrame.to_csv() 中的一个错误,即使只指定对非数字值加引号,浮点值也被引号包围 (GH 12922, GH 13259)

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

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

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

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

  • cartesian_productMultiIndex.from_product 中的错误,可能会在输入数组为空时引发 (GH 12258)

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

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

  • pd.read_csv() 中的一个错误,导致 BOM 文件在解析时没有忽略 BOM 而被错误解析 (GH 4793)

  • pd.read_csv() 中使用 engine='python' 时,当为 usecols 传递一个 numpy 数组时会引发错误 (GH 12546)

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

  • pd.read_csv() 中使用 engine='python' 时的一个错误,在数据转换为数值后无法检测到 NaN 值 (GH 13314)

  • pd.read_csv() 中的一个错误,其中 nrows 参数在两个引擎中都没有得到正确验证 (GH 10476)

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

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

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

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

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

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

  • pd.read_csv() 中使用 engine='c' 时出现的错误,即使 quoting 被指定为 None,也不接受 NULL quotechar (GH 13411)

  • pd.read_csv() 中使用 engine='c' 时的一个错误,当指定引用为非数字时,字段未正确转换为浮点数 (GH 13411)

  • 在 Python 2.x 中 pd.read_csv() 的错误,处理非 UTF-8 编码、多字符分隔的数据 (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 中存在一个错误,当引发错误时文件未正确关闭。(GH 13940)

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

  • 在传递非整数时,pd.Series.str.zfillcenterljustrjustpad 中的错误,没有引发 TypeError (GH 13598)

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

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

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

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

  • category 类型的 Series 上使用 .fillna(value=np.nan) 时,错误地引发 KeyError 的 Bug (GH 14021)

  • 扩展 dtype 创建中的错误,其中创建的类型不是 is/identical (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)

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

  • 使用 Categorical 数据类型的 .unstack 中的错误将 .ordered 重置为 True (GH 13249)

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

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

  • .set_index 中的错误在新的索引包含DST边界和多层级时会引发 AmbiguousTimeError (GH 12920)

  • .shift 中的错误在数据包含接近夏令时边界的时间时会引发 AmbiguousTimeError (GH 13926)

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

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

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

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

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

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

  • groupby(..).nth() 中的错误,当在 .head()/.tail() 之后调用时,组键包含不一致 (GH 12839)

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

  • DataFrame.iterrows() 中的错误,如果没有定义则不会产生 Series 子类 (GH 13977)

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

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

  • to_datetimeDatetimeIndex 中解析无效的 datetime 时,可能会引发 TypeError 而不是 ValueError (GH 11169, GH 11287)

  • 使用 tz-aware Timestamp 和匹配错误的 tz 选项创建的 Index 中的错误不正确地强制时区 (GH 13692)

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

  • Series 中设置带有 np.timedelta64 的切片时出现的错误 (GH 14155)

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

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

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

  • .value_counts() 中的错误在数据超出 datetime64[ns] 范围时引发 OutOfBoundsDatetime (GH 13663)

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

  • Series 创建中使用 np.datetime64 时,如果单位不是 ns 而是 object 类型,会导致不正确的值 (GH 13876)

  • resample 中使用 timedelta 数据时,数据被转换为浮点数的问题 (GH 13119)。

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

  • pd.merge() 中的错误如果在输入的类似日期时间的数据中使用了除 ns 以外的单位,可能会引发 TypeError (GH 13389)

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

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

  • groupby 中使用 as_index=False 时,当按包括分类列在内的多个列分组时返回所有 NaN (GH 13204)

  • df.groupby(...)[...] 中的错误,其中使用 Int64Index 的 getitem 引发了错误 (GH 13731)

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

  • pd.read_gbq() 可能会抛出 ImportError: No module named discovery 的错误,这是由于与另一个名为 apiclient 的 Python 包命名冲突导致的 (GH 13454)

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

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

  • 在从 tz-aware datetime64 系列中减去 tz-aware datetime.datetime 时出现的错误 (GH 14088)

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

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

  • concatgroupby 在带有 RangeIndex 级别的多级框架中存在错误 (GH 13542)。

  • 在包含仅包含 object dtype 的 NaN 值的 Series 中,Series.str.contains() 存在错误 (GH 14171)

  • 在 groupby dataframe 上的 agg() 函数中的 Bug 将 datetime64[ns] 列的数据类型更改为 float64 (GH 12821)

  • 在使用 PeriodIndex 与 NumPy ufunc 添加或减去整数时出现 IncompatibleFrequency 错误。请注意,推荐使用标准运算符如 +-,因为标准运算符使用更高效的路径 (GH 13980)

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

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

  • MultiIndex 列中使用 DataFrame.to_csv() 时出现了一个多余的空行 (GH 6618)

  • DatetimeIndexTimedeltaIndexPeriodIndex.equals() 中的错误可能会在输入不是 Index 但包含相同值时返回 True (GH 13107)

  • 在具有时区的日期时间赋值中的错误可能无法正常工作,如果它包含接近夏令时边界的日期时间 (GH 14146)

  • pd.eval()HDFStore 查询在 Python 2 中截断长浮点字面量的错误 (GH 14241)

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

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

  • 当使用整数 line_widthindex=False 调用 .to_string() 时,由于 idx 在赋值前被引用,会引发 UnboundLocalError 异常。

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

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

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

  • df.groupby 中的一个错误,当分组后的数据框包含空箱时,.median() 返回任意值 (GH 13629)

  • Index.copy() 中的错误,其中 name 参数被忽略 (GH 14302)

贡献者#

共有 117 人为此版本贡献了补丁。名字后面带有 “+” 的人首次贡献了补丁。

  • Adrien Emery +

  • Alex Alekseyev

  • Alex Vig +

  • Allen Riddell +

  • Amol +

  • Amol Agrawal +

  • Andy R. Terrel +

  • Anthonios Partheniou

  • Ben Kandel +

  • Bob Baxley +

  • Brett Rosen +

  • Camilo Cota +

  • Chris

  • Chris Grinolds

  • Chris Warth

  • Christian Hudon

  • Christopher C. Aycock

  • Daniel Siladji +

  • Douglas McNeil

  • Drewrey Lupton +

  • Eduardo Blancas Reyes +

  • Elliot Marsden +

  • Evan Wright

  • Felix Marczinowski +

  • Francis T. O’Donovan

  • Geraint Duck +

  • Giacomo Ferroni +

  • Grant Roch +

  • Gábor Lipták

  • Haleemur Ali +

  • Hassan Shamim +

  • Iulius Curt +

  • Ivan Nazarov +

  • Jeff Reback

  • Jeffrey Gerard +

  • Jenn Olsen +

  • Jim Crist

  • Joe Jevnik

  • John Evans +

  • John Freeman

  • John Liekezer +

  • John W. O’Brien

  • John Zwinck +

  • Johnny Gill +

  • Jordan Erenrich +

  • Joris Van den Bossche

  • Josh Howes +

  • Jozef Brandys +

  • Ka Wo Chen

  • Kamil Sindi +

  • Kerby Shedden

  • Kernc +

  • Kevin Sheppard

  • Matthieu Brucher +

  • Maximilian Roos

  • Michael Scherer +

  • Mike Graham +

  • Mortada Mehyar

  • Muhammad Haseeb Tariq +

  • Nate George +

  • Neil Parley +

  • Nicolas Bonnotte

  • OXPHOS

  • Pan Deng / Zora +

  • Paul +

  • Paul Mestemaker +

  • Pauli Virtanen

  • Pawel Kordek +

  • Pietro Battiston

  • Piotr Jucha +

  • Ravi Kumar Nimmi +

  • Robert Gieseke

  • Robert Kern +

  • Roger Thomas

  • Roy Keyes +

  • Russell Smith +

  • Sahil Dua +

  • Sanjiv Lobo +

  • Sašo Stanovnik +

  • Shawn Heide +

  • Sinhrks

  • Stephen Kappel +

  • Steve Choi +

  • Stewart Henderson +

  • Sudarshan Konge +

  • Thomas A Caswell

  • Tom Augspurger

  • Tom Bird +

  • Uwe Hoffmann +

  • WillAyd +

  • Xiang Zhang +

  • YG-Riku +

  • Yadunandan +

  • Yaroslav Halchenko

  • Yuichiro Kaneko +

  • adneu

  • agraboso +

  • babakkeyvani +

  • c123w +

  • chris-b1

  • cmazzullo +

  • conquistador1492 +

  • cr3 +

  • dsm054

  • gfyoung

  • harshul1610 +

  • iamsimha +

  • jackieleng +

  • mpuels +

  • pijucha +

  • priyankjain +

  • sinhrks

  • wcwagner +

  • yui-knk +

  • zhangjinjie +

  • znmean +

  • 颜发才(Yan Facai) +