版本 0.15.0 (2014年10月18日)#

这是从 0.14.1 版本以来的一个主要发布,包含少量 API 更改、一些新功能、增强功能和性能改进,以及大量的错误修复。我们建议所有用户升级到此版本。

警告

pandas >= 0.15.0 将不再支持与 NumPy 1.7.0 以下版本的兼容性。如果您想使用最新版本的 pandas,请升级到 NumPy >= 1.7.0 (GH 7711)

警告

在 0.15.0 中,Index 内部已重构为不再是 ndarray 的子类,而是 PandasObject 的子类,与其余 pandas 对象类似。此更改允许非常容易地创建新的索引类型和子类化。这应该是一个透明的更改,API 影响非常有限(详见内部重构

警告

Categorical 的重构将双参数构造函数从“codes/labels and levels”更改为“values and levels (现在称为 'categories')”。这可能导致细微的错误。如果您直接使用Categorical,请在更新到此 pandas 版本之前审查您的代码,并将其更改为使用from_codes() 构造函数。有关 Categorical 的更多信息,请参阅此处

新功能#

Series/DataFrame 中的分类类型#

Categorical 现在可以包含在 SeriesDataFrames 中,并获得了新的操作方法。感谢 Jan Schulz 为此 API/实现做出了很大贡献。(GH 3943, GH 5313, GH 5314, GH 7444, GH 7839, GH 7848, GH 7864, GH 7914, GH 7768, GH 8006, GH 3678, GH 8075, GH 8076, GH 8143, GH 8453, GH 8518)。

有关完整文档,请参阅分类类型简介API 文档

In [1]: df = pd.DataFrame({"id": [1, 2, 3, 4, 5, 6],
   ...:                    "raw_grade": ['a', 'b', 'b', 'a', 'a', 'e']})
   ...: 

In [2]: df["grade"] = df["raw_grade"].astype("category")

In [3]: df["grade"]
Out[3]: 
0    a
1    b
2    b
3    a
4    a
5    e
Name: grade, Length: 6, dtype: category
Categories (3, object): ['a', 'b', 'e']

# Rename the categories
In [4]: df["grade"] = df["grade"].cat.rename_categories(["very good", "good", "very bad"])

# Reorder the categories and simultaneously add the missing categories
In [5]: df["grade"] = df["grade"].cat.set_categories(["very bad", "bad",
   ...:                                               "medium", "good", "very good"])
   ...: 

In [6]: df["grade"]
Out[6]: 
0    very good
1         good
2         good
3    very good
4    very good
5     very bad
Name: grade, Length: 6, dtype: category
Categories (5, object): ['very bad', 'bad', 'medium', 'good', 'very good']

In [7]: df.sort_values("grade")
Out[7]: 
   id raw_grade      grade
5   6         e   very bad
1   2         b       good
2   3         b       good
0   1         a  very good
3   4         a  very good
4   5         a  very good

[6 rows x 3 columns]

In [8]: df.groupby("grade", observed=False).size()
Out[8]: 
grade
very bad     1
bad          0
medium       0
good         2
very good    3
Length: 5, dtype: int64
  • pandas.core.group_aggpandas.core.factor_agg 已被移除。作为替代方案,请构建一个 DataFrame 并使用 df.groupby(<group>).agg(<func>)

  • 不再支持向 Categorical 构造函数提供“codes/labels and levels”。向构造函数提供两个参数现在被解释为“values and levels (现在称为 'categories')”。请更改您的代码以使用from_codes() 构造函数。

  • Categorical.labels 属性已重命名为 Categorical.codes 并且是只读的。如果您想操作代码,请使用分类类型上的 API 方法之一。

  • Categorical.levels 属性已重命名为 Categorical.categories

TimedeltaIndex/标量#

我们引入了一个新的标量类型 Timedelta,它是 datetime.timedelta 的子类,行为方式类似,但也支持与 np.timedelta64 类型以及大量自定义表示、解析和属性兼容。此类型与 Timestampdatetimes 的工作方式非常相似。它是该类型的一个很好的 API 封装。请参阅文档。(GH 3009, GH 4533, GH 8209, GH 8187, GH 8190, GH 7869, GH 7661, GH 8345, GH 8471)

警告

Timedelta 标量(和 TimedeltaIndex)的组件字段与 datetime.timedelta 对象上的组件字段*不同*。例如,datetime.timedelta 对象上的 .seconds 返回小时、分钟和秒的总和。相比之下,pandas 的 Timedelta 分别列出小时、分钟、微秒和纳秒。

# Timedelta accessor
In [9]: tds = pd.Timedelta('31 days 5 min 3 sec')

In [10]: tds.minutes
Out[10]: 5L

In [11]: tds.seconds
Out[11]: 3L

# datetime.timedelta accessor
# this is 5 minutes * 60 + 3 seconds
In [12]: tds.to_pytimedelta().seconds
Out[12]: 303

注意:从 v0.16.0 开始,这不再是事实,该版本引入了与 datetime.timedelta 的完全兼容性。详见0.16.0 版本新特性条目

警告

在 0.15.0 之前,pd.to_timedelta 对于列表式/Series 输入会返回一个 Series,对于标量输入会返回一个 np.timedelta64。现在它将对列表式输入返回一个 TimedeltaIndex,对 Series 输入返回一个 Series,对标量输入返回一个 Timedelta

pd.to_timedelta 的参数现在是 (arg,unit='ns',box=True,coerce=False),以前是 (arg,box=True,unit='ns'),因为现在这些更合乎逻辑。

构造一个标量

In [9]: pd.Timedelta('1 days 06:05:01.00003')
Out[9]: Timedelta('1 days 06:05:01.000030')

In [10]: pd.Timedelta('15.5us')
Out[10]: Timedelta('0 days 00:00:00.000015500')

In [11]: pd.Timedelta('1 hour 15.5us')
Out[11]: Timedelta('0 days 01:00:00.000015500')

# negative Timedeltas have this string repr
# to be more consistent with datetime.timedelta conventions
In [12]: pd.Timedelta('-1us')
Out[12]: Timedelta('-1 days +23:59:59.999999')

# a NaT
In [13]: pd.Timedelta('nan')
Out[13]: NaT

访问 Timedelta 的字段

In [14]: td = pd.Timedelta('1 hour 3m 15.5us')

In [15]: td.seconds
Out[15]: 3780

In [16]: td.microseconds
Out[16]: 15

In [17]: td.nanoseconds
Out[17]: 500

构造一个 TimedeltaIndex

In [18]: pd.TimedeltaIndex(['1 days', '1 days, 00:00:05',
   ....:                    np.timedelta64(2, 'D'),
   ....:                    datetime.timedelta(days=2, seconds=2)])
   ....: 
Out[18]: 
TimedeltaIndex(['1 days 00:00:00', '1 days 00:00:05', '2 days 00:00:00',
                '2 days 00:00:02'],
               dtype='timedelta64[ns]', freq=None)

使用常规范围构造 TimedeltaIndex

In [19]: pd.timedelta_range('1 days', periods=5, freq='D')
Out[19]: TimedeltaIndex(['1 days', '2 days', '3 days', '4 days', '5 days'], dtype='timedelta64[ns]', freq='D')
In [20]: pd.timedelta_range(start='1 days', end='2 days', freq='30T')
Out[20]:
TimedeltaIndex(['1 days 00:00:00', '1 days 00:30:00', '1 days 01:00:00',
                '1 days 01:30:00', '1 days 02:00:00', '1 days 02:30:00',
                '1 days 03:00:00', '1 days 03:30:00', '1 days 04:00:00',
                '1 days 04:30:00', '1 days 05:00:00', '1 days 05:30:00',
                '1 days 06:00:00', '1 days 06:30:00', '1 days 07:00:00',
                '1 days 07:30:00', '1 days 08:00:00', '1 days 08:30:00',
                '1 days 09:00:00', '1 days 09:30:00', '1 days 10:00:00',
                '1 days 10:30:00', '1 days 11:00:00', '1 days 11:30:00',
                '1 days 12:00:00', '1 days 12:30:00', '1 days 13:00:00',
                '1 days 13:30:00', '1 days 14:00:00', '1 days 14:30:00',
                '1 days 15:00:00', '1 days 15:30:00', '1 days 16:00:00',
                '1 days 16:30:00', '1 days 17:00:00', '1 days 17:30:00',
                '1 days 18:00:00', '1 days 18:30:00', '1 days 19:00:00',
                '1 days 19:30:00', '1 days 20:00:00', '1 days 20:30:00',
                '1 days 21:00:00', '1 days 21:30:00', '1 days 22:00:00',
                '1 days 22:30:00', '1 days 23:00:00', '1 days 23:30:00',
                '2 days 00:00:00'],
               dtype='timedelta64[ns]', freq='30T')

您现在可以使用 TimedeltaIndex 作为 pandas 对象的索引

In [20]: s = pd.Series(np.arange(5),
   ....:               index=pd.timedelta_range('1 days', periods=5, freq='s'))
   ....: 

In [21]: s
Out[21]: 
1 days 00:00:00    0
1 days 00:00:01    1
1 days 00:00:02    2
1 days 00:00:03    3
1 days 00:00:04    4
Freq: s, Length: 5, dtype: int64

您可以使用部分字符串选择进行选择

In [22]: s['1 day 00:00:02']
Out[22]: 2

In [23]: s['1 day':'1 day 00:00:02']
Out[23]: 
1 days 00:00:00    0
1 days 00:00:01    1
1 days 00:00:02    2
Freq: s, Length: 3, dtype: int64

最后,TimedeltaIndexDatetimeIndex 的组合允许某些组合操作,这些操作会保留 NaT

In [24]: tdi = pd.TimedeltaIndex(['1 days', pd.NaT, '2 days'])

In [25]: tdi.tolist()
Out[25]: [Timedelta('1 days 00:00:00'), NaT, Timedelta('2 days 00:00:00')]

In [26]: dti = pd.date_range('20130101', periods=3)

In [27]: dti.tolist()
Out[27]: 
[Timestamp('2013-01-01 00:00:00'),
 Timestamp('2013-01-02 00:00:00'),
 Timestamp('2013-01-03 00:00:00')]

In [28]: (dti + tdi).tolist()
Out[28]: [Timestamp('2013-01-02 00:00:00'), NaT, Timestamp('2013-01-05 00:00:00')]

In [29]: (dti - tdi).tolist()
Out[29]: [Timestamp('2012-12-31 00:00:00'), NaT, Timestamp('2013-01-01 00:00:00')]
  • 在 v0.15.0 之前,对 Series (例如 list(Series(...))) 的 timedelta64[ns] 迭代会为每个元素返回 np.timedelta64。现在这些将包装在 Timedelta 中。

内存使用#

实现了查找 DataFrame 内存使用情况的方法。更多信息请参阅常见问题。(GH 6852)。

一个新的显示选项 display.memory_usage (详见选项和设置) 设置了 df.info() 方法中 memory_usage 参数的默认行为。默认情况下,display.memory_usageTrue

In [30]: dtypes = ['int64', 'float64', 'datetime64[ns]', 'timedelta64[ns]',
   ....:           'complex128', 'object', 'bool']
   ....: 

In [31]: n = 5000

In [32]: data = {t: np.random.randint(100, size=n).astype(t) for t in dtypes}

In [33]: df = pd.DataFrame(data)

In [34]: df['categorical'] = df['object'].astype('category')

In [35]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5000 entries, 0 to 4999
Data columns (total 8 columns):
 #   Column           Non-Null Count  Dtype          
---  ------           --------------  -----          
 0   int64            5000 non-null   int64          
 1   float64          5000 non-null   float64        
 2   datetime64[ns]   5000 non-null   datetime64[ns] 
 3   timedelta64[ns]  5000 non-null   timedelta64[ns]
 4   complex128       5000 non-null   complex128     
 5   object           5000 non-null   object         
 6   bool             5000 non-null   bool           
 7   categorical      5000 non-null   category       
dtypes: bool(1), category(1), complex128(1), datetime64[ns](1), float64(1), int64(1), object(1), timedelta64[ns](1)
memory usage: 288.2+ KB

此外,memory_usage() 是 DataFrame 对象的一个可用方法,它返回每列的内存使用情况。

In [36]: df.memory_usage(index=True)
Out[36]: 
Index                128
int64              40000
float64            40000
datetime64[ns]     40000
timedelta64[ns]    40000
complex128         80000
object             40000
bool                5000
categorical         9968
Length: 9, dtype: int64

Series.dt 访问器#

Series 获得了一个访问器,可以简洁地返回 Series *值*的日期时间类属性,如果它是日期时间/周期类 Series。(GH 7207) 这将返回一个 Series,其索引与现有 Series 相同。详见文档

# datetime
In [37]: s = pd.Series(pd.date_range('20130101 09:10:12', periods=4))

In [38]: s
Out[38]: 
0   2013-01-01 09:10:12
1   2013-01-02 09:10:12
2   2013-01-03 09:10:12
3   2013-01-04 09:10:12
Length: 4, dtype: datetime64[ns]

In [39]: s.dt.hour
Out[39]: 
0    9
1    9
2    9
3    9
Length: 4, dtype: int32

In [40]: s.dt.second
Out[40]: 
0    12
1    12
2    12
3    12
Length: 4, dtype: int32

In [41]: s.dt.day
Out[41]: 
0    1
1    2
2    3
3    4
Length: 4, dtype: int32

In [42]: s.dt.freq
Out[42]: 'D'

这使得诸如此类的简洁表达式成为可能

In [43]: s[s.dt.day == 2]
Out[43]: 
1   2013-01-02 09:10:12
Length: 1, dtype: datetime64[ns]

您可以轻松生成时区感知转换

In [44]: stz = s.dt.tz_localize('US/Eastern')

In [45]: stz
Out[45]: 
0   2013-01-01 09:10:12-05:00
1   2013-01-02 09:10:12-05:00
2   2013-01-03 09:10:12-05:00
3   2013-01-04 09:10:12-05:00
Length: 4, dtype: datetime64[ns, US/Eastern]

In [46]: stz.dt.tz
Out[46]: <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>

您还可以链式执行这些操作

In [47]: s.dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
Out[47]: 
0   2013-01-01 04:10:12-05:00
1   2013-01-02 04:10:12-05:00
2   2013-01-03 04:10:12-05:00
3   2013-01-04 04:10:12-05:00
Length: 4, dtype: datetime64[ns, US/Eastern]

.dt 访问器适用于 period 和 timedelta 数据类型。

# period
In [48]: s = pd.Series(pd.period_range('20130101', periods=4, freq='D'))

In [49]: s
Out[49]: 
0    2013-01-01
1    2013-01-02
2    2013-01-03
3    2013-01-04
Length: 4, dtype: period[D]

In [50]: s.dt.year
Out[50]: 
0    2013
1    2013
2    2013
3    2013
Length: 4, dtype: int64

In [51]: s.dt.day
Out[51]: 
0    1
1    2
2    3
3    4
Length: 4, dtype: int64
# timedelta
In [52]: s = pd.Series(pd.timedelta_range('1 day 00:00:05', periods=4, freq='s'))

In [53]: s
Out[53]: 
0   1 days 00:00:05
1   1 days 00:00:06
2   1 days 00:00:07
3   1 days 00:00:08
Length: 4, dtype: timedelta64[ns]

In [54]: s.dt.days
Out[54]: 
0    1
1    1
2    1
3    1
Length: 4, dtype: int64

In [55]: s.dt.seconds
Out[55]: 
0    5
1    6
2    7
3    8
Length: 4, dtype: int32

In [56]: s.dt.components
Out[56]: 
   days  hours  minutes  seconds  milliseconds  microseconds  nanoseconds
0     1      0        0        5             0             0            0
1     1      0        0        6             0             0            0
2     1      0        0        7             0             0            0
3     1      0        0        8             0             0            0

[4 rows x 7 columns]

时区处理改进#

  • tz-aware TimestampDatetimeIndextz_localize(None) 现在会移除持有本地时间的时区,以前这会导致 ExceptionTypeError (GH 7812)

    In [58]: ts = pd.Timestamp('2014-08-01 09:00', tz='US/Eastern')
    
    In[59]: ts
    Out[59]: Timestamp('2014-08-01 09:00:00-0400', tz='US/Eastern')
    
    In [60]: ts.tz_localize(None)
    Out[60]: Timestamp('2014-08-01 09:00:00')
    
    In [61]: didx = pd.date_range(start='2014-08-01 09:00', freq='H',
       ....:                      periods=10, tz='US/Eastern')
       ....:
    
    In [62]: didx
    Out[62]:
    DatetimeIndex(['2014-08-01 09:00:00-04:00', '2014-08-01 10:00:00-04:00',
                   '2014-08-01 11:00:00-04:00', '2014-08-01 12:00:00-04:00',
                   '2014-08-01 13:00:00-04:00', '2014-08-01 14:00:00-04:00',
                   '2014-08-01 15:00:00-04:00', '2014-08-01 16:00:00-04:00',
                   '2014-08-01 17:00:00-04:00', '2014-08-01 18:00:00-04:00'],
                  dtype='datetime64[ns, US/Eastern]', freq='H')
    
    In [63]: didx.tz_localize(None)
    Out[63]:
    DatetimeIndex(['2014-08-01 09:00:00', '2014-08-01 10:00:00',
                   '2014-08-01 11:00:00', '2014-08-01 12:00:00',
                   '2014-08-01 13:00:00', '2014-08-01 14:00:00',
                   '2014-08-01 15:00:00', '2014-08-01 16:00:00',
                   '2014-08-01 17:00:00', '2014-08-01 18:00:00'],
                  dtype='datetime64[ns]', freq=None)
    
  • tz_localize 现在接受 ambiguous 关键字,它允许传入一个布尔数组来指示日期是否属于夏令时,'NaT' 用于将转换时间设置为 NaT,'infer' 用于推断夏令时/非夏令时,以及 'raise'(默认)用于抛出 AmbiguousTimeError。更多详细信息请参阅文档 (GH 7943)

  • DataFrame.tz_localizeDataFrame.tz_convert 现在接受一个可选的 level 参数,用于定位 MultiIndex 的特定级别 (GH 7846)

  • Timestamp.tz_localizeTimestamp.tz_convert 现在在错误情况下抛出 TypeError,而不是 Exception (GH 8025)

  • 本地化到 UTC 的时间序列/索引在插入到 Series/DataFrame 中时将保留 UTC 时区(而不是作为 naive datetime64[ns])作为 object 数据类型 (GH 8411)

  • Timestamp.__repr__ 显示 dateutil.tz.tzoffset 信息 (GH 7907)

滚动/扩展矩改进#

  • rolling_min(), rolling_max(), rolling_cov(), 和 rolling_corr() 现在在 len(arg) < min_periods <= window 时返回包含所有 NaN 的对象,而不是抛出异常。(这使得所有滚动函数在此行为上保持一致)。(GH 7766)

    0.15.0 之前

    In [57]: s = pd.Series([10, 11, 12, 13])
    
    In [15]: pd.rolling_min(s, window=10, min_periods=5)
    ValueError: min_periods (5) must be <= window (4)
    

    新行为

    In [4]: pd.rolling_min(s, window=10, min_periods=5)
    Out[4]:
    0   NaN
    1   NaN
    2   NaN
    3   NaN
    dtype: float64
    
  • rolling_max(), rolling_min(), rolling_sum(), rolling_mean(), rolling_median(), rolling_std(), rolling_var(), rolling_skew(), rolling_kurt(), rolling_quantile(), rolling_cov(), rolling_corr(), rolling_corr_pairwise(), rolling_window(), 和 rolling_apply()center=True 时,以前会返回与输入 arg 相同结构的结果,并在最后 (window-1)/2 个条目中包含 NaN

    现在,结果的最后 (window-1)/2 个条目会像输入 arg 后面跟着 (window-1)/2NaN 值一样计算(或者在 rolling_apply() 的情况下,使用收缩窗口)。(GH 7925, GH 8269)

    之前的行为(注意最终值为 NaN

    In [7]: pd.rolling_sum(Series(range(4)), window=3, min_periods=0, center=True)
    Out[7]:
    0     1
    1     3
    2     6
    3   NaN
    dtype: float64
    

    新行为(注意最终值为 5 = sum([2, 3, NaN])

    In [7]: pd.rolling_sum(pd.Series(range(4)), window=3,
      ....:                min_periods=0, center=True)
    Out[7]:
    0    1
    1    3
    2    6
    3    5
    dtype: float64
    
  • rolling_window() 现在在滚动均值模式 (mean=True) 中正确地标准化权重,使得计算出的加权平均值(例如“triang”、“gaussian”)分布在与不加权计算(即“boxcar”)相同的平均值附近。有关更多详细信息,请参阅归一化说明。(GH 7618)

    In [58]: s = pd.Series([10.5, 8.8, 11.4, 9.7, 9.3])
    

    0.15.0 之前的行为

    In [39]: pd.rolling_window(s, window=3, win_type='triang', center=True)
    Out[39]:
    0         NaN
    1    6.583333
    2    6.883333
    3    6.683333
    4         NaN
    dtype: float64
    

    新行为

    In [10]: pd.rolling_window(s, window=3, win_type='triang', center=True)
    Out[10]:
    0       NaN
    1     9.875
    2    10.325
    3    10.025
    4       NaN
    dtype: float64
    
  • 从所有 expanding_ 函数(详见列表)中移除了 center 参数,因为当 center=True 时产生的结果没有太大意义。(GH 7925)

  • expanding_cov()rolling_cov() 添加了可选的 ddof 参数。1 的默认值是向后兼容的。(GH 8279)

  • 记录了 ddof 参数到 expanding_var(), expanding_std(), rolling_var(), 和 rolling_std()。这些函数对 ddof 参数(默认值为 1)的支持以前没有文档记录。(GH 8064)

  • ewma(), ewmstd(), ewmvol(), ewmvar(), ewmcov(), 和 ewmcorr() 现在以与 rolling_*()expanding_*() 函数相同的方式解释 min_periods:如果(在此情况下)扩展窗口不包含至少 min_periods 个值,则给定结果条目将为 NaN。之前的行为是将从第一个非 NaN 值开始的 min_periods 条目设置为 NaN。(GH 7977)

    之前的行为(注意值从索引 2 开始,这是索引 0(第一个非空值的索引)之后 min_periods

    In [59]: s  = pd.Series([1, None, None, None, 2, 3])
    
    In [51]: pd.ewma(s, com=3., min_periods=2)
    Out[51]:
    0         NaN
    1         NaN
    2    1.000000
    3    1.000000
    4    1.571429
    5    2.189189
    dtype: float64
    

    新行为(注意值从索引 4 开始,这是第 2 个(因为 min_periods=2)非空值的位置)

    In [2]: pd.ewma(s, com=3., min_periods=2)
    Out[2]:
    0         NaN
    1         NaN
    2         NaN
    3         NaN
    4    1.759644
    5    2.383784
    dtype: float64
    
  • ewmstd(), ewmvol(), ewmvar(), ewmcov(), 和 ewmcorr() 现在有一个可选的 adjust 参数,就像 ewma() 一样,影响权重的计算方式。adjust 的默认值为 True,这是向后兼容的。详见指数加权矩函数。(GH 7911)

  • ewma(), ewmstd(), ewmvol(), ewmvar(), ewmcov(), 和 ewmcorr() 现在有一个可选的 ignore_na 参数。当 ignore_na=False(默认值)时,缺失值会被纳入权重计算。当 ignore_na=True(重现 0.15.0 之前的行为)时,缺失值在权重计算中被忽略。(GH 7543)

    In [7]: pd.ewma(pd.Series([None, 1., 8.]), com=2.)
    Out[7]:
    0    NaN
    1    1.0
    2    5.2
    dtype: float64
    
    In [8]: pd.ewma(pd.Series([1., None, 8.]), com=2.,
      ....:         ignore_na=True)  # pre-0.15.0 behavior
    Out[8]:
    0    1.0
    1    1.0
    2    5.2
    dtype: float64
    
    In [9]: pd.ewma(pd.Series([1., None, 8.]), com=2.,
      ....:         ignore_na=False)  # new default
    Out[9]:
    0    1.000000
    1    1.000000
    2    5.846154
    dtype: float64
    

    警告

    默认情况下(ignore_na=False),ewm*() 函数在存在缺失值时的权重计算与 0.15.0 之前的版本不同。要重现 0.15.0 之前存在缺失值时的权重计算,必须显式指定 ignore_na=True

  • 修复了 expanding_cov(), expanding_corr(), rolling_cov(), rolling_cor(), ewmcov(), 和 ewmcorr() 中返回按名称排序的列并为非唯一列产生错误的 bug;现在可以处理非唯一列并按原始顺序返回列(除了两个 DataFrame 带有 pairwise=False 的情况,其行为不变)(GH 7542)

  • 修复了 rolling_count()expanding_*() 函数中不必要地为零长度数据产生错误消息的 bug (GH 8056)

  • 修复了 rolling_apply()expanding_apply() 中将 min_periods=0 解释为 min_periods=1 的 bug (GH 8080)

  • 修复了 expanding_std()expanding_var() 中单个值产生令人困惑的错误消息的 bug (GH 7900)

  • 修复了 rolling_std()rolling_var() 中单个值产生 0 而不是 NaN 的 bug (GH 7900)

  • 修复了 ewmstd(), ewmvol(), ewmvar(), 和 ewmcov()bias=False(默认)时去偏置因子计算中的 bug。以前使用了一个不正确的常数因子,基于 adjust=True, ignore_na=True, 和无限数量的观测值。现在根据实际权重(类似于通常的 N/(N-1) 因子)为每个条目使用不同的因子。特别是,对于单个点,当 bias=False 时返回 NaN 值,而以前返回(大约)0 值。

    例如,考虑以下 0.15.0 之前的 ewmvar(..., bias=False) 结果以及相应的去偏置因子

    In [60]: s = pd.Series([1., 2., 0., 4.])
    
    In [89]: pd.ewmvar(s, com=2., bias=False)
    Out[89]:
    0   -2.775558e-16
    1    3.000000e-01
    2    9.556787e-01
    3    3.585799e+00
    dtype: float64
    
    In [90]: pd.ewmvar(s, com=2., bias=False) / pd.ewmvar(s, com=2., bias=True)
    Out[90]:
    0    1.25
    1    1.25
    2    1.25
    3    1.25
    dtype: float64
    

    请注意,条目 0 大约是 0,去偏置因子是常数 1.25。相比之下,以下 0.15.0 结果的条目 0NaN,去偏置因子正在减小(趋向 1.25)

    In [14]: pd.ewmvar(s, com=2., bias=False)
    Out[14]:
    0         NaN
    1    0.500000
    2    1.210526
    3    4.089069
    dtype: float64
    
    In [15]: pd.ewmvar(s, com=2., bias=False) / pd.ewmvar(s, com=2., bias=True)
    Out[15]:
    0         NaN
    1    2.083333
    2    1.583333
    3    1.425439
    dtype: float64
    

    详见指数加权矩函数。(GH 7912)

SQL IO 模块的改进#

  • to_sql 函数添加了对 chunksize 参数的支持。这允许 DataFrame 分块写入,并避免数据包大小溢出错误 (GH 8062)。

  • read_sql 函数添加了对 chunksize 参数的支持。指定此参数将返回一个查询结果块的迭代器 (GH 2908)。

  • 添加了使用 to_sql 写入 datetime.datedatetime.time 对象列的支持 (GH 6932)。

  • 添加了指定 schema 来使用 read_sql_tableto_sql 进行读写的支持 (GH 7441, GH 7952)。例如

    df.to_sql('table', engine, schema='other_schema')  # noqa F821
    pd.read_sql_table('table', engine, schema='other_schema')  # noqa F821
    
  • 添加了使用 to_sql 写入 NaN 值的支持 (GH 2754)。

  • 添加了对所有数据库类型使用 to_sql 写入 datetime64 列的支持 (GH 7103)。

向后不兼容的 API 更改#

重大更改#

Categorical 相关的 API 更改(详见此处

  • 带有两个参数的 Categorical 构造函数从“codes/labels and levels”更改为“values and levels (现在称为 'categories')”。这可能导致细微的错误。如果您直接使用Categorical,请通过将其更改为使用from_codes() 构造函数来审查您的代码。

    旧函数调用,例如 (0.15.0 之前)

    pd.Categorical([0,1,0,2,1], levels=['a', 'b', 'c'])
    

    为了保持相同行为,必须适应以下更改

    In [2]: pd.Categorical.from_codes([0,1,0,2,1], categories=['a', 'b', 'c'])
    Out[2]:
    [a, b, a, c, b]
    Categories (3, object): [a, b, c]
    

与引入 Timedelta 标量相关的 API 更改(详见上文

  • 在 0.15.0 之前,to_timedelta() 对于列表式/Series 输入会返回一个 Series,对于标量输入会返回一个 np.timedelta64。现在它将对列表式输入返回一个 TimedeltaIndex,对 Series 输入返回一个 Series,对标量输入返回一个 Timedelta

有关滚动和扩展函数相关的 API 更改,请参阅上文的详细概述。

其他值得注意的 API 更改

  • 在使用 .loc 和列表式索引器且未找到值时的索引一致性。

    In [61]: df = pd.DataFrame([['a'], ['b']], index=[1, 2])
    
    In [62]: df
    Out[62]: 
       0
    1  a
    2  b
    
    [2 rows x 1 columns]
    

    在以前的版本中,这两种构造存在差异

    • df.loc[[3]] 将返回一个由 3 重新索引的框架(所有值为 np.nan

    • df.loc[[3],:] 将引发 KeyError

    两者现在都将引发 KeyError。规则是,当使用列表式和 .loc 时,必须找到*至少 1 个*索引器 (GH 7999)

    此外,在以前的版本中,这些也不同

    • df.loc[[1,3]] 将返回一个由 [1,3] 重新索引的框架

    • df.loc[[1,3],:] 将引发 KeyError

    两者现在都将返回一个由 [1,3] 重新索引的框架。例如

    In [3]: df.loc[[1, 3]]
    Out[3]:
         0
    1    a
    3  NaN
    
    In [4]: df.loc[[1, 3], :]
    Out[4]:
         0
    1    a
    3  NaN
    

    这也可以在带有 Panel 的多轴索引中看到。

    >>> p = pd.Panel(np.arange(2 * 3 * 4).reshape(2, 3, 4),
    ...              items=['ItemA', 'ItemB'],
    ...              major_axis=[1, 2, 3],
    ...              minor_axis=['A', 'B', 'C', 'D'])
    >>> p
    <class 'pandas.core.panel.Panel'>
    Dimensions: 2 (items) x 3 (major_axis) x 4 (minor_axis)
    Items axis: ItemA to ItemB
    Major_axis axis: 1 to 3
    Minor_axis axis: A to D
    

    以下将在 0.15.0 之前引发 KeyError

    In [5]:
    Out[5]:
       ItemA  ItemD
    1      3    NaN
    2      7    NaN
    3     11    NaN
    

    此外,如果在使用列表式索引器的 MultiIndex 中找不到值,.loc 将引发异常

    In [63]: s = pd.Series(np.arange(3, dtype='int64'),
       ....:               index=pd.MultiIndex.from_product([['A'],
       ....:                                                ['foo', 'bar', 'baz']],
       ....:                                                names=['one', 'two'])
       ....:               ).sort_index()
       ....: 
    
    In [64]: s
    Out[64]: 
    one  two
    A    bar    1
         baz    2
         foo    0
    Length: 3, dtype: int64
    
    In [65]: try:
       ....:     s.loc[['D']]
       ....: except KeyError as e:
       ....:     print("KeyError: " + str(e))
       ....: 
    KeyError: "['D'] not in index"
    
  • 现在为 None 赋值时会考虑 dtype,以选择“空”值 (GH 7941)。

    以前,在数值容器中赋值为 None 会将 dtype 更改为 object(或根据调用方式报错)。它现在使用 NaN

    In [66]: s = pd.Series([1., 2., 3.])
    
    In [67]: s.loc[0] = None
    
    In [68]: s
    Out[68]: 
    0    NaN
    1    2.0
    2    3.0
    Length: 3, dtype: float64
    

    NaT 现在也类似地用于日期时间容器。

    对于对象容器,我们现在保留 None 值(以前这些值会转换为 NaN 值)。

    In [69]: s = pd.Series(["a", "b", "c"])
    
    In [70]: s.loc[0] = None
    
    In [71]: s
    Out[71]: 
    0    None
    1       b
    2       c
    Length: 3, dtype: object
    

    要插入 NaN,您必须显式使用 np.nan。详见文档

  • 在以前的版本中,就地更新 pandas 对象不会反映在对此对象的其他 python 引用中。(GH 8511, GH 5104)

    In [72]: s = pd.Series([1, 2, 3])
    
    In [73]: s2 = s
    
    In [74]: s += 1.5
    

    v0.15.0 之前的行为

    # the original object
    In [5]: s
    Out[5]:
    0    2.5
    1    3.5
    2    4.5
    dtype: float64
    
    
    # a reference to the original object
    In [7]: s2
    Out[7]:
    0    1
    1    2
    2    3
    dtype: int64
    

    这现在是正确的行为

    # the original object
    In [75]: s
    Out[75]: 
    0    2.5
    1    3.5
    2    4.5
    Length: 3, dtype: float64
    
    # a reference to the original object
    In [76]: s2
    Out[76]: 
    0    2.5
    1    3.5
    2    4.5
    Length: 3, dtype: float64
    
  • 使 read_csvread_table 的 C-based 和 Python 引擎都忽略输入中的空行以及填充空白的行,只要 sep 不是空白字符。这是一个 API 更改,可以通过关键字参数 skip_blank_lines 控制。详见文档 (GH 4466)

  • 本地化为 UTC 的时间序列/索引在插入到 Series/DataFrame 中时将保留 UTC 时区,并作为 object 数据类型插入,而不是转换为 naive datetime64[ns] (GH 8411)。

  • 修复了从字典构造 DataFrame 时,传递带有未保留时区的 DatetimeIndex 的 bug (GH 7822)

    在以前的版本中,这将删除时区,现在它保留时区,但会生成一个 object dtype 的列

    In [77]: i = pd.date_range('1/1/2011', periods=3, freq='10s', tz='US/Eastern')
    
    In [78]: i
    Out[78]: 
    DatetimeIndex(['2011-01-01 00:00:00-05:00', '2011-01-01 00:00:10-05:00',
                   '2011-01-01 00:00:20-05:00'],
                  dtype='datetime64[ns, US/Eastern]', freq='10s')
    
    In [79]: df = pd.DataFrame({'a': i})
    
    In [80]: df
    Out[80]: 
                              a
    0 2011-01-01 00:00:00-05:00
    1 2011-01-01 00:00:10-05:00
    2 2011-01-01 00:00:20-05:00
    
    [3 rows x 1 columns]
    
    In [81]: df.dtypes
    Out[81]: 
    a    datetime64[ns, US/Eastern]
    Length: 1, dtype: object
    

    以前这将生成一个 datetime64 dtype 的列,但没有时区信息。

    将列分配给现有 DataFrame 的行为,如 df['a'] = i 保持不变(这已经返回了一个带有有时区的 object 列)。

  • 当将多个级别传递给 stack() 时,如果级别不是全部为级别名称或全部为级别号,它现在将引发 ValueError (GH 7660)。详见通过堆叠和取消堆叠进行重塑

  • 如果 df 具有非唯一列,则在 df.to_hdf 中以“fixed”格式引发 ValueError,因为生成的文件将损坏 (GH 7761)

  • 当使用链式赋值在切片混合 dtype DataFrame 上设置值时,现在将根据选项 mode.chained_assignment 发出 SettingWithCopy 警告/错误。(GH 7845, GH 7950)

    In [1]: df = pd.DataFrame(np.arange(0, 9), columns=['count'])
    
    In [2]: df['group'] = 'b'
    
    In [3]: df.iloc[0:5]['group'] = 'a'
    /usr/local/bin/ipython:1: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead
    
    See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
    
  • merge, DataFrame.merge, 和 ordered_merge 现在返回与 left 参数相同的类型 (GH 7737)。

  • 以前,使用混合 dtype 框架进行扩展的行为与 .append 不同,后者会保留 dtype(相关 GH 2578, GH 8176

    In [82]: df = pd.DataFrame([[True, 1], [False, 2]],
       ....:                   columns=["female", "fitness"])
       ....: 
    
    In [83]: df
    Out[83]: 
       female  fitness
    0    True        1
    1   False        2
    
    [2 rows x 2 columns]
    
    In [84]: df.dtypes
    Out[84]: 
    female      bool
    fitness    int64
    Length: 2, dtype: object
    
    # dtypes are now preserved
    In [85]: df.loc[2] = df.loc[1]
    
    In [86]: df
    Out[86]: 
       female  fitness
    0    True        1
    1   False        2
    2   False        2
    
    [3 rows x 2 columns]
    
    In [87]: df.dtypes
    Out[87]: 
    female      bool
    fitness    int64
    Length: 2, dtype: object
    
  • Series.to_csv() 现在在 path=None 时返回一个字符串,与 DataFrame.to_csv() 的行为匹配 (GH 8215)。

  • 当传入不存在的文件时,read_hdf 现在会引发 IOError。以前,会创建一个新的空文件,并引发一个 KeyError (GH 7715)。

  • DataFrame.info() 现在以换行符结束其输出 (GH 8114)

  • 连接空对象现在将引发 ValueError 而不是简单的 Exception

  • 合并错误现在将是 ValueError 的子类,而不是原始的 Exception (GH 8501)

  • DataFrame.plotSeries.plot 的关键字现在具有一致的顺序 (GH 8037)

内部重构#

在 0.15.0 中,Index 内部已重构为不再是 ndarray 的子类,而是 PandasObject 的子类,与其余 pandas 对象类似。此更改允许非常容易地创建新的索引类型和子类化。这应该是一个透明的更改,API 影响非常有限 (GH 5080, GH 7439, GH 7796, GH 8024, GH 8367, GH 7997, GH 8522)

  • 您可能需要使用 pd.read_pickle 而不是 pickle.load 来解封 pandas 0.15.0 版本之前的 pickle 文件。详见pickle 文档

  • 当使用 PeriodIndex 绘图时,matplotlib 内部轴现在将是 Period 数组而不是 PeriodIndex(这类似于 DatetimeIndex 现在传递 datetimes 数组的方式)

  • MultiIndex 现在在真值测试方面将像其他 pandas 对象一样引发异常,详见此处 (GH 7897)。

  • 当直接使用 matplotlib 的 plot 函数绘制 DatetimeIndex 时,轴标签将不再格式化为日期,而是格式化为整数(datetime64 的内部表示)。更新:这在 0.15.1 中已修复,详见此处

弃用#

  • Categoricallabelslevels 属性已弃用,并重命名为 codescategories

  • outtype 参数传递给 pd.DataFrame.to_dict 已弃用,转而使用 orient。(GH 7840)

  • convert_dummies 方法已弃用,转而使用 get_dummies (GH 8140)

  • tz_localize 中的 infer_dst 参数将弃用,转而使用 ambiguous,以允许在处理夏令时转换时有更大的灵活性。将 infer_dst=True 替换为 ambiguous='infer' 以获得相同行为 (GH 7943)。更多详细信息请参阅文档

  • 顶级 pd.value_range 已弃用,可以使用 .describe() 替换 (GH 8481)

  • Index 集合操作 +- 已弃用,以便为某些索引类型上的数值类型操作提供这些操作。+ 可以用 .union()| 替换,而 - 可以用 .difference() 替换。此外,方法名 Index.diff() 已弃用,可以使用 Index.difference() 替换 (GH 8226)

    # +
    pd.Index(['a', 'b', 'c']) + pd.Index(['b', 'c', 'd'])
    
    # should be replaced by
    pd.Index(['a', 'b', 'c']).union(pd.Index(['b', 'c', 'd']))
    
    # -
    pd.Index(['a', 'b', 'c']) - pd.Index(['b', 'c', 'd'])
    
    # should be replaced by
    pd.Index(['a', 'b', 'c']).difference(pd.Index(['b', 'c', 'd']))
    
  • 传递给 read_html()infer_types 参数现在无效并已弃用 (GH 7762, GH 7032)。

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

  • 移除 DataFrame.delevel 方法,转而使用 DataFrame.reset_index

增强功能#

Stata 文件导入/导出功能增强

  • to_stata 中添加了对 bool、uint8、uint16 和 uint32 数据类型的支持 (GH 7097, GH 7365)

  • 导入 Stata 文件时添加了转换选项 (GH 8527)

  • DataFrame.to_stataStataWriter 检查字符串长度是否与 dta 文件中施加的限制兼容,其中固定宽度字符串必须包含 244 个或更少字符。尝试写入字符串长度超过 244 个字符的 Stata dta 文件会引发 ValueError。(GH 7858)

  • read_stataStataReader 可以通过将参数 convert_missing 设置为 True 来将缺失数据信息导入到 DataFrame 中。使用此选项时,缺失值将作为 StataMissingValue 对象返回,并且包含缺失值的列将具有 object 数据类型。(GH 8045)

绘图功能增强

  • DataFrame.plot 添加了 layout 关键字。您可以传入一个 (rows, columns) 元组,其中一个可以是 -1 以自动推断 (GH 6667, GH 8071)。

  • 允许将多个轴传递给 DataFrame.plot, histboxplot (GH 5353, GH 6970, GH 7069)

  • DataFrame.plot 添加了对 c, colormapcolorbar 参数的支持,带有 kind='scatter' (GH 7780)

  • 来自 DataFrame.plot 的直方图,带有 kind='hist' (GH 7809),详见文档

  • 来自 DataFrame.plot 的箱线图,带有 kind='box' (GH 7998),详见文档

其他

  • read_csv 现在有一个关键字参数 float_precision,它指定 C 引擎在解析期间应使用哪个浮点转换器,详见此处 (GH 8002, GH 8044)

  • Series 对象添加了 searchsorted 方法 (GH 7447)

  • 在混合类型 DataFrames 上的 describe() 更灵活。现在可以通过 include/exclude 参数进行基于类型的列过滤。详见文档 (GH 8164)。

    In [88]: df = pd.DataFrame({'catA': ['foo', 'foo', 'bar'] * 8,
       ....:                    'catB': ['a', 'b', 'c', 'd'] * 6,
       ....:                    'numC': np.arange(24),
       ....:                    'numD': np.arange(24.) + .5})
       ....: 
    
    In [89]: df.describe(include=["object"])
    Out[89]: 
           catA catB
    count    24   24
    unique    2    4
    top     foo    a
    freq     16    6
    
    [4 rows x 2 columns]
    
    In [90]: df.describe(include=["number", "object"], exclude=["float"])
    Out[90]: 
           catA catB       numC
    count    24   24  24.000000
    unique    2    4        NaN
    top     foo    a        NaN
    freq     16    6        NaN
    mean    NaN  NaN  11.500000
    std     NaN  NaN   7.071068
    min     NaN  NaN   0.000000
    25%     NaN  NaN   5.750000
    50%     NaN  NaN  11.500000
    75%     NaN  NaN  17.250000
    max     NaN  NaN  23.000000
    
    [11 rows x 3 columns]
    

    可以使用简写“all”请求所有列

    In [91]: df.describe(include='all')
    Out[91]: 
           catA catB       numC       numD
    count    24   24  24.000000  24.000000
    unique    2    4        NaN        NaN
    top     foo    a        NaN        NaN
    freq     16    6        NaN        NaN
    mean    NaN  NaN  11.500000  12.000000
    std     NaN  NaN   7.071068   7.071068
    min     NaN  NaN   0.000000   0.500000
    25%     NaN  NaN   5.750000   6.250000
    50%     NaN  NaN  11.500000  12.000000
    75%     NaN  NaN  17.250000  17.750000
    max     NaN  NaN  23.000000  23.500000
    
    [11 rows x 4 columns]
    

    如果没有这些参数,describe 将像以前一样,只包含数值列,或者如果没有数值列,则只包含分类列。另请参阅文档

  • pd.DataFrame.to_dict 中,将 split 作为 orient 参数的一个选项添加。(GH 7840)

  • get_dummies 方法现在可以在 DataFrames 上使用。默认情况下,只有分类列被编码为 0 和 1,而其他列保持不变。

    In [92]: df = pd.DataFrame({'A': ['a', 'b', 'a'], 'B': ['c', 'c', 'b'],
       ....:                 'C': [1, 2, 3]})
       ....: 
    
    In [93]: pd.get_dummies(df)
    Out[93]: 
       C    A_a    A_b    B_b    B_c
    0  1   True  False  False   True
    1  2  False   True  False   True
    2  3   True  False   True  False
    
    [3 rows x 5 columns]
    
  • PeriodIndex 支持与 DatetimeIndex 相同的 resolution (GH 7708)

  • pandas.tseries.holiday 增加了对其他假期和观察假期方式的支持 (GH 7070)

  • pandas.tseries.holiday.Holiday 现在支持 Python3 中的偏移量列表 (GH 7070)

  • pandas.tseries.holiday.Holiday 现在支持 days_of_week 参数 (GH 7070)

  • GroupBy.nth() 现在支持选择多个 nth 值 (GH 7910)

    In [94]: business_dates = pd.date_range(start='4/1/2014', end='6/30/2014', freq='B')
    
    In [95]: df = pd.DataFrame(1, index=business_dates, columns=['a', 'b'])
    
    # get the first, 4th, and last date index for each month
    In [96]: df.groupby([df.index.year, df.index.month]).nth([0, 3, -1])
    Out[96]: 
                a  b
    2014-04-01  1  1
    2014-04-04  1  1
    2014-04-30  1  1
    2014-05-01  1  1
    2014-05-06  1  1
    2014-05-30  1  1
    2014-06-02  1  1
    2014-06-05  1  1
    2014-06-30  1  1
    
    [9 rows x 2 columns]
    
  • PeriodPeriodIndex 支持与 timedelta 类进行加/减操作 (GH 7966)

    如果 Period 频率是 D, H, T, S, L, U, N,则可以添加 Timedelta 类,如果结果可以具有相同的频率。否则,只能添加相同的 offsets

    In [104]: idx = pd.period_range('2014-07-01 09:00', periods=5, freq='H')
    
    In [105]: idx
    Out[105]:
    PeriodIndex(['2014-07-01 09:00', '2014-07-01 10:00', '2014-07-01 11:00',
                 '2014-07-01 12:00', '2014-07-01 13:00'],
                dtype='period[H]')
    
    In [106]: idx + pd.offsets.Hour(2)
    Out[106]:
    PeriodIndex(['2014-07-01 11:00', '2014-07-01 12:00', '2014-07-01 13:00',
                 '2014-07-01 14:00', '2014-07-01 15:00'],
                dtype='period[H]')
    
    In [107]: idx + pd.Timedelta('120m')
    Out[107]:
    PeriodIndex(['2014-07-01 11:00', '2014-07-01 12:00', '2014-07-01 13:00',
                 '2014-07-01 14:00', '2014-07-01 15:00'],
                dtype='period[H]')
    
    In [108]: idx = pd.period_range('2014-07', periods=5, freq='M')
    
    In [109]: idx
    Out[109]: PeriodIndex(['2014-07', '2014-08', '2014-09', '2014-10', '2014-11'], dtype='period[M]')
    
    In [110]: idx + pd.offsets.MonthEnd(3)
    Out[110]: PeriodIndex(['2014-10', '2014-11', '2014-12', '2015-01', '2015-02'], dtype='period[M]')
    
  • 添加了对版本 >= 2.0 的 openpyxl 的实验性兼容性。DataFrame.to_excel 方法的 engine 关键字现在识别 openpyxl1openpyxl2,这将分别明确要求 openpyxl v1 和 v2,如果请求的版本不可用则失败。openpyxl 引擎现在是一个元引擎,它会自动使用安装的任何版本的 openpyxl。(GH 7177)

  • DataFrame.fillna 现在可以接受 DataFrame 作为填充值 (GH 8377)

  • 当传递多个级别号时,将多个级别传递给 stack() 现在将起作用 (GH 7660)。详见通过堆叠和取消堆叠进行重塑

  • set_names(), set_labels(), 和 set_levels() 方法现在接受一个可选的 level 关键字参数,以修改 MultiIndex 的特定级别。此外,set_names() 现在在操作 IndexMultiIndex 的特定级别时接受标量字符串值 (GH 7792)

    In [97]: idx = pd.MultiIndex.from_product([['a'], range(3), list("pqr")],
       ....:                                  names=['foo', 'bar', 'baz'])
       ....: 
    
    In [98]: idx.set_names('qux', level=0)
    Out[98]: 
    MultiIndex([('a', 0, 'p'),
                ('a', 0, 'q'),
                ('a', 0, 'r'),
                ('a', 1, 'p'),
                ('a', 1, 'q'),
                ('a', 1, 'r'),
                ('a', 2, 'p'),
                ('a', 2, 'q'),
                ('a', 2, 'r')],
               names=['qux', 'bar', 'baz'])
    
    In [99]: idx.set_names(['qux', 'corge'], level=[0, 1])
    Out[99]: 
    MultiIndex([('a', 0, 'p'),
                ('a', 0, 'q'),
                ('a', 0, 'r'),
                ('a', 1, 'p'),
                ('a', 1, 'q'),
                ('a', 1, 'r'),
                ('a', 2, 'p'),
                ('a', 2, 'q'),
                ('a', 2, 'r')],
               names=['qux', 'corge', 'baz'])
    
    In [100]: idx.set_levels(['a', 'b', 'c'], level='bar')
    Out[100]: 
    MultiIndex([('a', 'a', 'p'),
                ('a', 'a', 'q'),
                ('a', 'a', 'r'),
                ('a', 'b', 'p'),
                ('a', 'b', 'q'),
                ('a', 'b', 'r'),
                ('a', 'c', 'p'),
                ('a', 'c', 'q'),
                ('a', 'c', 'r')],
               names=['foo', 'bar', 'baz'])
    
    In [101]: idx.set_levels([['a', 'b', 'c'], [1, 2, 3]], level=[1, 2])
    Out[101]: 
    MultiIndex([('a', 'a', 1),
                ('a', 'a', 2),
                ('a', 'a', 3),
                ('a', 'b', 1),
                ('a', 'b', 2),
                ('a', 'b', 3),
                ('a', 'c', 1),
                ('a', 'c', 2),
                ('a', 'c', 3)],
               names=['foo', 'bar', 'baz'])
    
  • Index.isin 现在支持 level 参数,以指定用于成员资格测试的索引级别 (GH 7892, GH 7890)

    In [1]: idx = pd.MultiIndex.from_product([[0, 1], ['a', 'b', 'c']])
    
    In [2]: idx.values
    Out[2]: array([(0, 'a'), (0, 'b'), (0, 'c'), (1, 'a'), (1, 'b'), (1, 'c')], dtype=object)
    
    In [3]: idx.isin(['a', 'c', 'e'], level=1)
    Out[3]: array([ True, False,  True,  True, False,  True], dtype=bool)
    
  • Index 现在支持 duplicateddrop_duplicates。(GH 4060)

    In [102]: idx = pd.Index([1, 2, 3, 4, 1, 2])
    
    In [103]: idx
    Out[103]: Index([1, 2, 3, 4, 1, 2], dtype='int64')
    
    In [104]: idx.duplicated()
    Out[104]: array([False, False, False, False,  True,  True])
    
    In [105]: idx.drop_duplicates()
    Out[105]: Index([1, 2, 3, 4], dtype='int64')
    
  • pd.concat 添加 copy=True 参数,以允许传递完整块 (GH 8252)

  • 添加了对 numpy 1.8+ 数据类型 (bool_, int_, float_, string_) 的支持,用于转换为 R DataFrame (GH 8400)

性能#

  • DatetimeIndex.__iter__ 中进行了性能改进,以实现更快的迭代 (GH 7683)

  • Period 创建(以及 PeriodIndex setitem)中进行了性能改进 (GH 5155)

  • 在 Series.transform 中进行了改进,以显著提高性能(修订版)(GH 6496)

  • 在读取大型文件时,StataReader 的性能改进 (GH 8040, GH 8073)

  • 在写入大型文件时,StataWriter 的性能改进 (GH 8079)

  • 多键 groupby 的性能和内存使用改进 (GH 8128)

  • groupby.agg.apply 方法的性能改进,其中内置的 max/min 未映射到 numpy/cythonized 版本 (GH 7722)

  • 写入 SQL (to_sql) 的性能提升高达 50% (GH 8208)。

  • 对 ngroups 大值进行 groupby 的性能基准测试 (GH 6787)

  • CustomBusinessDayCustomBusinessMonth 的性能改进 (GH 8236)

  • 包含日期时间的多级索引的 MultiIndex.values 的性能改进 (GH 8543)

Bug 修复#

  • pivot_table 中的 Bug,在使用 margins 和 dict aggfunc 时出现 (GH 8349)

  • read_csv 中的 Bug,其中 squeeze=True 会返回一个视图 (GH 8217)

  • read_sql 在某些情况下检查表名时的 Bug (GH 7826)。

  • DataFrame.groupby 中的 Bug,其中指定频率时 Grouper 无法识别 level (GH 7885)

  • 多级索引的 dtype 在 DataFrame 保存到 SQL 表时混淆的 Bug (GH 8021)

  • Series 中浮点和整数操作数 dtype 的 0 除 Bug (GH 7785)

  • Series.astype("unicode") 未正确调用值的 unicode 的 Bug (GH 7758)

  • DataFrame.as_matrix() 中混合 datetime64[ns]timedelta64[ns] dtypes 的 Bug (GH 7778)

  • HDFStore.select_column() 在选择 DatetimeIndex 时未保留 UTC 时区信息的 Bug (GH 7777)

  • to_datetime 中的 Bug,当指定 format='%Y%m%d'coerce=True 时,之前返回的是一个对象数组(而不是带有 NaT 的强制转换时间序列)(GH 7930)

  • DatetimeIndexPeriodIndex 的原地加减操作导致结果与常规操作不同 (GH 6527)

  • PeriodIndexPeriodIndex 相加减时引发 TypeError 的 Bug (GH 7741)

  • 使用 PeriodIndex 数据进行 combine_first 时引发 TypeError 的 Bug (GH 3367)

  • MultiIndex 切片时缺少索引器的 Bug (GH 7866)

  • MultiIndex 切片在各种边缘情况下的 Bug (GH 8132)

  • MultiIndex 使用非标量类型对象索引时的回归 Bug (GH 7914)

  • Timestamp==int64 dtype 比较时的 Bug (GH 8058)

  • 包含 DateOffset 的 pickle 在内部引用 normalize 属性时可能引发 AttributeError 的 Bug (GH 7748)

  • Panel 中的 Bug,当使用 major_xs 并传入 copy=False 时(由于缺少 warnings 导致弃用警告失败)(GH 8152)。

  • pickle 反序列化中的 Bug,对于带有重复项的 0.14.1 之前版本容器在匹配块和管理器项时试图避免歧义,而当只有一个块时则没有歧义 (GH 7794)

  • PeriodIndex 放入 Series 时会转换为 int64 dtype 而不是 Periodsobject dtype 的 Bug (GH 7932)

  • 在传入 where 条件时 HDFStore 迭代中的 Bug (GH 8014)

  • DataFrameGroupby.transform 在使用传入的非排序键进行转换时的 Bug (GH 8046, GH 8430)

  • 重复的时间序列折线图和面积图可能导致 ValueError 或不正确的类型 (GH 7733)

  • MultiIndex 在 datetime.date 输入时的推断 Bug (GH 7888)

  • get 方法中的 Bug,IndexError 不会导致默认值被返回 (GH 7725)

  • offsets.applyrollforwardrollback 方法中的 Bug,可能重置纳秒 (GH 7697)

  • offsets.applyrollforwardrollback 方法中的 Bug,如果 Timestamp 具有 dateutil tzinfo 则可能引发 AttributeError (GH 7697)

  • 使用 Float64Index 排序 MultiIndex 框架时的 Bug (GH 8017)

  • 面板 setitem 与 DataFrame 的右侧不对齐时的 Bug (GH 7763)

  • is_superperiodis_subperiod 无法处理高于 S 的频率的 Bug (GH 7760, GH 7772, GH 7803)

  • 32 位平台上 Series.shift 的 Bug (GH 8129)

  • PeriodIndex.unique 返回 int64 np.ndarray 的 Bug (GH 7540)

  • groupby.apply 中函数内存在非影响性变异的 Bug (GH 8467)

  • DataFrame.reset_index 中的 Bug,当其 MultiIndex 包含 PeriodIndex 或带有 tz 的 DatetimeIndex 时引发 ValueError (GH 7746, GH 7793)

  • DataFrame.plotsubplots=True 可能绘制不必要的次要 x 轴和 y 轴刻度线的 Bug (GH 7801)

  • StataReader 中的 Bug,由于 Stata 文档和实现之间的差异,导致无法读取 117 个文件中的变量标签 (GH 7816)

  • StataReader 中的 Bug,其中字符串始终被转换为 244 个字符的固定宽度,无论底层字符串大小如何 (GH 7858)

  • DataFrame.plotSeries.plot 可能忽略 rotfontsize 关键字的 Bug (GH 7844)

  • DatetimeIndex.value_counts 不保留 tz 的 Bug (GH 7735)

  • PeriodIndex.value_counts 导致 Int64Index 的 Bug (GH 7735)

  • DataFrame.join 在对索引进行左连接且存在多个匹配时的 Bug (GH 5391)

  • GroupBy.transform() 中的 Bug,其中整数组在转换时未保留索引导致被错误截断 (GH 7972)。

  • groupby 中的 Bug,其中没有 name 属性的可调用对象会走错误的路径,并生成 DataFrame 而不是 Series (GH 7929)

  • groupby 错误消息中的 Bug,当 DataFrame 分组列重复时 (GH 7511)

  • read_html 中的 Bug,其中 infer_types 参数错误地强制转换日期类数据 (GH 7762, GH 7032)。

  • Series.str.cat 中的 Bug,其中索引被过滤,不包含第一个项目 (GH 7857)

  • Timestamp 无法从字符串解析 nanosecond 的 Bug (GH 7878)

  • 带有字符串偏移量和 tzTimestamp 结果不正确的 Bug (GH 7833)

  • tslib.tz_converttslib.tz_convert_single 可能返回不同结果的 Bug (GH 7798)

  • 带有 tz 的非重叠时间戳的 DatetimeIndex.intersection 引发 IndexError 的 Bug (GH 7880)

  • TimeOps 和非唯一索引对齐时的 Bug (GH 8363)

  • GroupBy.filter() 中的 Bug,其中快速路径与慢速路径导致过滤器返回一个看似有效但实际上不是的非标量值 (GH 7870)。

  • date_range()/DatetimeIndex() 中的 Bug,当从输入日期推断时区但在跨越夏令时边界时返回不正确的时间 (GH 7835, GH 7901)。

  • to_excel() 中的 Bug,其中正无穷大前附加了一个负号,而负无穷大却缺少负号 (GH 7949)

  • 面积图在 stacked=True 时绘制的图例 alpha 不正确的 Bug (GH 8027)

  • PeriodPeriodIndexnp.timedelta64 进行加减运算导致内部表示不正确的 Bug (GH 7740)

  • 没有偏移量或遵守规则的 Holiday 的 Bug (GH 7987)

  • DataFrame.to_latex 在列或索引为 MultiIndex 时格式化不正确的 Bug (GH 7982)。

  • DateOffset 在夏令时附近产生意外结果的 Bug (GH 5175)。

  • DataFrame.shift 中的 Bug,其中空列在 numpy 1.7 上会抛出 ZeroDivisionError (GH 8019)

  • 安装中的 Bug,其中 html_encoding/*.html 未安装,因此某些测试未正确运行 (GH 7927)。

  • read_html 中的 Bug,其中 bytes 对象在 _read 中未被测试 (GH 7927)。

  • DataFrame.stack() 中的 Bug,当其中一个列级别是日期类型时 (GH 8039)

  • DataFrame 广播 numpy 标量时的 Bug (GH 8116)

  • 使用无名 indexcolumns 执行 pivot_table 时引发 KeyError 的 Bug (GH 8103)

  • DataFrame.plot(kind='scatter') 中的 Bug,当颜色由 c 关键字指定时,点和误差条会以不同颜色绘制 (GH 8081)

  • Float64Index 中的 Bug,其中 iatat 未经测试且失败 (GH 8092)。

  • DataFrame.boxplot() 中的 Bug,其中在生成多个轴时 y 轴限制未正确设置 (GH 7528, GH 5517)。

  • read_csv 中的 Bug,其中在给定自定义行终止符或 delim_whitespace=True 时,行注释未正确处理 (GH 8122)。

  • read_html 中的 Bug,其中空表导致 StopIteration (GH 7575)

  • 在相同 dtype 块中设置列时类型转换的 Bug (GH 7704)

  • 当原始 grouper 是元组时,从 GroupBy 访问组的 Bug (GH 8121)。

  • .at 中的 Bug,它会在非整数索引上接受整数索引器并执行回退 (GH 7814)

  • kde 图和 NaNs 的 Bug (GH 8182)

  • GroupBy.count 中 float32 数据类型未排除 nan 值的 Bug (GH 8169)。

  • 堆叠条形图和 NaNs 的 Bug (GH 8175)。

  • resample 中非均匀可除偏移量(例如 '7s')的 Bug (GH 8371)

  • 在不需要插值时,插值方法中 limit 关键字的 Bug (GH 7173)。

  • DataFrame.to_string() 中当 header=False 时忽略 col_space 的 Bug (GH 8230)。

  • DatetimeIndex.asof 错误匹配部分字符串并返回错误日期的 Bug (GH 8245)。

  • 绘图方法修改全局 matplotlib rcParams 的 Bug (GH 8242)。

  • DataFrame.__setitem__ 中的 Bug,将 DataFrame 列设置为稀疏数组时导致错误 (GH 8131)

  • Dataframe.boxplot() 在整个列为空时失败的 Bug (GH 8181)。

  • radviz 可视化中变量混乱的 Bug (GH 8199)。

  • 在不需要插值时,插值方法中 limit 关键字的 Bug (GH 7173)。

  • DataFrame.to_string() 中当 header=False 时忽略 col_space 的 Bug (GH 8230)。

  • to_clipboard 中的 Bug,会裁剪长列数据 (GH 8305)

  • DataFrame 终端显示中的 Bug:将 max_column/max_rows 设置为零不会触发 dfs 自动调整大小以适应终端宽度/高度 (GH 7180)。

  • OLS 中的 Bug,其中使用“cluster”和“nw_lags”参数运行时未正确工作,但也未抛出错误 (GH 5884)。

  • DataFrame.dropna 中的 Bug,它将子集参数中不存在的列解释为“最后一列” (GH 8303)

  • Index.intersection 在非单调非唯一索引上的 Bug (GH 8362)。

  • 掩码序列赋值中的 Bug,其中类型不匹配会破坏对齐 (GH 8387)

  • NDFrame.equals 在 dtype=object 时产生假阴性的 Bug (GH 8437)

  • 使用索引器进行赋值时的 Bug,其中类型多样性会破坏对齐 (GH 8258)

  • NDFrame.loc 索引中的 Bug,当目标是列表/ndarray 时行/列名称丢失 (GH 6552)

  • NDFrame.loc 索引中的回归 Bug,当目标是空列表/ndarray 时行/列被转换为 Float64Index (GH 7774)

  • Series 中的 Bug,允许其被 DataFrame 索引,导致意外结果。此类索引不再被允许 (GH 8444)

  • DataFrame 的 MultiIndex 列的项赋值中的 Bug,其中右侧列未对齐 (GH 7655)

  • 抑制 NumPy 在比较包含 NaN 的对象数组是否相等时生成的 FutureWarning (GH 7065)

  • DataFrame.eval() 中的 Bug,其中 not 运算符 (~) 的 dtype 未正确推断为 bool

贡献者#

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

  • Aaron Schumacher +

  • Adam Greenhall

  • Andy Hayden

  • Anthony O’Brien +

  • Artemy Kolchinsky +

  • Ben Schiller +

  • Benedikt Sauer

  • Benjamin Thyreau +

  • BorisVerk +

  • Chris Reynolds +

  • Chris Stoafer +

  • DSM

  • Dav Clark +

  • FragLegs +

  • German Gomez-Herrero +

  • Hsiaoming Yang +

  • Huan Li +

  • Hyungtae Kim +

  • Isaac Slavitt +

  • Jacob Schaer

  • Jacob Wasserman +

  • Jan Schulz

  • Jeff Reback

  • Jeff Tratner

  • Jesse Farnham +

  • Joe Bradish +

  • Joerg Rittinger +

  • John W. O’Brien

  • Joris Van den Bossche

  • Kevin Sheppard

  • Kyle Meyer

  • Max Chang +

  • Michael Mueller

  • Michael W Schatzow +

  • Mike Kelly

  • Mortada Mehyar

  • Nathan Sanders +

  • Nathan Typanski +

  • Paul Masurel +

  • Phillip Cloud

  • Pietro Battiston

  • RenzoBertocchi +

  • Ross Petchler +

  • Shahul Hameed +

  • Shashank Agarwal +

  • Stephan Hoyer

  • Tom Augspurger

  • TomAugspurger

  • Tony Lorenzo +

  • Wes Turner

  • Wilfred Hughes +

  • Yevgeniy Grechka +

  • Yoshiki Vázquez Baeza +

  • behzad nouri +

  • benjamin

  • bjonen +

  • dlovell +

  • dsm054

  • hunterowens +

  • immerrr

  • ischwabacher

  • jmorris0x0 +

  • jnmclarty +

  • jreback

  • klonuo +

  • lexual

  • mcjcode +

  • mtrbean +

  • onesandzeroes

  • rockg

  • seth-p

  • sinhrks

  • someben +

  • stahlous +

  • stas-sl +

  • thatneat +

  • tom-alcorn +

  • unknown

  • unutbu

  • zachcp +