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

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

警告

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 和 levels”更改为“values 和 levels(现在称为 'categories')”。这可能导致一些不易察觉的 bug。如果您直接使用 Categorical,请在更新到此 pandas 版本之前审计您的代码,并将其更改为使用 from_codes() 构造函数。更多关于 Categorical 的信息详见此处

新特性#

Series/DataFrame 中的 Categorical#

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

有关完整文档,请参阅Categorical 介绍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 和 levels”不再受支持。向构造函数提供两个参数现在被解释为“values 和 levels(现在称为 'categories')”。请更改您的代码以使用 from_codes() 构造函数。

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

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

TimedeltaIndex/标量#

我们引入了一种新的标量类型 Timedelta,它是 datetime.timedelta 的子类,行为类似,但兼容 np.timedelta64 类型,并提供一系列自定义表示、解析和属性。此类型与 Timestamp 处理 datetimes 的方式非常相似。它是该类型的一个便捷 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 返回 hoursminutesseconds 的总秒数。相比之下,pandas 的 Timedelta 分别列出 hours、minutes、microseconds 和 nanoseconds。

# 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 对于 list-like/Series 输入会返回 Series,对于标量输入会返回 np.timedelta64。现在,它对于 list-like 输入将返回 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')]
  • Series 进行迭代,例如 list(Series(...))timedelta64[ns] 在 v0.15.0 之前会为每个元素返回 np.timedelta64。现在,这些元素将被封装在 Timedelta 中。

内存使用#

实现了查找 DataFrame 内存使用情况的方法。更多信息请参阅FAQ。(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 的的日期时间类属性。(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 dtypes。

# 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]

时区处理改进#

  • 对于感知时区的 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 时区(而不是成为朴素的 datetime64[ns]),其 dtype 为 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
    
  • 在使用 center=True 时,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() 之前会返回与输入 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)

  • 文档化了 expanding_var(), expanding_std(), rolling_var()rolling_std()ddof 参数。这些函数对 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,之前在返回结果时会按名称对列进行排序,并且对非唯一列产生错误;现在该 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=Trueignore_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 版本的结果在条目 0 处为 NaN,去偏差因子正在减小(趋向于 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)。

  • 使用 read_sql_tableto_sql 函数时,添加了对指定 schema 进行读/写的支持 (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 和 levels”更改为“values 和 levels(现在称为‘categories’)”。这可能导致细微的 Bug。如果直接使用 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

    对于 object 容器,我们现在保留 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 引擎和 Python 引擎都忽略输入中的空行和仅包含空白字符的行,只要 sep 不是空白字符即可。这是一个 API 更改,可以通过关键字参数 skip_blank_lines 控制。请参见 文档 (GH 4466)

  • 将本地化为 UTC 的时间序列/索引插入到 Series/DataFrame 中时,将保留 UTC 时区并以 object dtype 插入,而不是转换为朴素的 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 设置值时,将发出 SettingWithCopy 错误/警告(根据选项 mode.chained_assignment)(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
    
  • mergeDataFrame.mergeordered_merge 现在返回与 left 参数相同的类型 (GH 7737)。

  • 以前,使用混合 dtype 帧进行扩展(enlargement)时的行为与保留 dtypes 的 .append 不同(相关 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 的子类,而是像其他 pandas 对象一样成为 PandasObject 的子类。这一更改使得子类化和创建新的索引类型变得非常容易。这应该是一个透明的更改,对 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 docs

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

  • MultiIndex 现在在真值测试(truth testing)方面会像其他 pandas 对象一样引发错误,请参见 此处 (GH 7897)。

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

废弃#

  • Categoricallabelslevels 属性已废弃,并更名为 codescategories

  • pd.DataFrame.to_dictouttype 参数已废弃,推荐使用 orient (GH 7840)。

  • convert_dummies 方法已废弃,推荐使用 get_dummies (GH 8140)

  • tz_localize 中的 infer_dst 参数将废弃,推荐使用 ambiguous 参数,以便更灵活地处理夏令时(DST)转换。将 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.plothistboxplot 传递多个轴 (GH 5353, GH 6970, GH 7069)

  • kind='scatter'DataFrame.plot 添加了对 ccolormapcolorbar 参数的支持 (GH 7780)

  • 使用 kind='hist'DataFrame.plot 生成直方图 (GH 7809),请参见 文档

  • 使用 kind='box'DataFrame.plot 生成箱线图 (GH 7998),请参见 文档

其他

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

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

  • 对混合类型 DataFrame 执行 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_dictorient 参数中添加了选项 split (GH 7840)。

  • get_dummies 方法现在可以在 DataFrame 上使用。默认情况下,仅将分类列编码为 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 支持 resolution 参数,与 DatetimeIndex 相同 (GH 7708)

  • pandas.tseries.holiday 添加了对更多假期和假期观察方式的支持 (GH 7070)

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

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

  • GroupBy.nth() 现在支持选择多个第 n 个值 (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 的频率(freq)是 DHTSLUN 中的一种,并且结果可以保持相同的频率,则可以添加 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]')
    
  • 添加了对 openpyxl 2.0 及更高版本的实验性兼容支持。DataFrame.to_excel 方法的 engine 关键字现在识别 openpyxl1openpyxl2,它们分别明确要求 openpyxl v1 和 v2 版本,如果所需的版本不可用则会失败。openpyxl 引擎现在是一个元引擎(meta-engine),它会自动使用安装的任何 openpyxl 版本 (GH 7177)。

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

  • 现在,当传递多个级别编号时,向 stack() 传递多个级别将会起作用 (GH 7660)。请参见 通过堆叠和非堆叠进行重塑

  • set_names()set_labels()set_levels() 方法现在接受一个可选的 level 关键字参数,用于修改 MultiIndex 的指定级别。此外,当作用于 IndexMultiIndex 的特定级别时,set_names() 现在接受一个标量字符串值 (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/cython 化版本 (GH 7722)

  • 将数据写入 sql(to_sql)的性能提升高达 50% (GH 8208)。

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

  • 改进了 CustomBusinessDayCustomBusinessMonth 的性能 (GH 8236)

  • 改进了包含 datetime 的多级索引的 MultiIndex.values 的性能 (GH 8543)

Bug 修复#

  • 修复了 pivot_table 在使用 margins 和 dict aggfunc 时的 bug (GH 8349)

  • 修复了 read_csv 中当 squeeze=True 时返回 view 的 bug (GH 8217)

  • 修复了 read_sql 在某些情况下检查表名时的 bug (GH 7826)。

  • 修复了 DataFrame.groupby 中当指定频率时 Grouper 不识别级别的 bug (GH 7885)

  • 修复了将 DataFrame 保存到 SQL 表时 multiindexes dtypes 混淆的 bug (GH 8021)

  • 修复了 Series 在浮点数和整数操作数类型之间进行 0 除操作时的 bug (GH 7785)

  • 修复了 Series.astype("unicode") 未正确在值上调用 unicode 的 bug (GH 7758)

  • 修复了 DataFrame.as_matrix() 在混合 datetime64[ns]timedelta64[ns] 数据类型时的 bug (GH 7778)

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

  • 修复了 to_datetime 在指定 format='%Y%m%d'coerce=True 时返回 object 数组(而不是带有 NaT 的强制转换时间序列)的 bug (GH 7930)

  • 修复了 DatetimeIndexPeriodIndex 原位加减运算导致与正常运算结果不同的 bug (GH 6527)

  • 修复了 PeriodIndexPeriodIndex 相加减时引发 TypeError 的 bug (GH 7741)

  • 修复了 combine_first 处理 PeriodIndex 数据时引发 TypeError 的 bug (GH 3367)

  • 修复了 MultiIndex 切片时缺少索引器的 bug (GH 7866)

  • 修复了 MultiIndex 切片时各种边缘情况的 bug (GH 8132)

  • 修复了 MultiIndex 使用非标量类型对象进行索引时的回归问题 (GH 7914)

  • 修复了 Timestamp==int64 数据类型进行比较时的 bug (GH 8058)

  • 修复了包含 DateOffset 的 pickle 文件在内部引用 normalize 属性时可能引发 AttributeError 的 bug (GH 7748)

  • 修复了 Panel 在使用 major_xs 并传入 copy=False 时(由于缺少 warnings 导致废弃警告失败)的 bug (GH 8152)。

  • 修复了 pickle 反序列化 bug,该 bug 导致早于 0.14.1 版本的容器在匹配块和管理器项时(当只有一个块时不存在歧义)因重复项而失败 (GH 7794)

  • 修复了将 PeriodIndex 放入 Series 时会转换为 int64 数据类型,而不是 Periodsobject 类型的 bug (GH 7932)

  • 修复了 HDFStore 在传递 where 参数进行迭代时的 bug (GH 8014)

  • 修复了 DataFrameGroupby.transform 在使用传入的未排序键进行转换时的 bug (GH 8046, GH 8430)

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

  • 修复了 MultiIndex 使用 datetime.date 输入进行推断时的 bug (GH 7888)

  • 修复了 getIndexError 不会导致返回默认值的 bug (GH 7725)

  • 修复了 offsets.applyrollforwardrollback 可能重置纳秒的 bug (GH 7697)

  • 修复了 offsets.applyrollforwardrollbackTimestamp 具有 dateutil 时区信息时可能引发 AttributeError 的 bug (GH 7697)

  • 修复了使用 Float64Index 对 MultiIndex frame 进行排序时的 bug (GH 8017)

  • 修复了 panel 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 中包含 PeriodIndex 或带 tz 的 DatetimeIndexMultiIndex 引发 ValueError 的 bug (GH 7746, GH 7793)

  • 修复了 DataFrame.plot 设置 subplots=True 时可能绘制不必要的次要 xticks 和 yticks 的 bug (GH 7801)

  • 修复了 StataReader 由于 Stata 文档与实现之间的差异,未读取 117 文件中的变量标签的 bug (GH 7816)

  • 修复了 StataReader 中无论底层字符串大小如何,字符串始终转换为 244 字符固定宽度的 bug (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() 中整数组使用未保留索引的 transform 时被错误截断的 bug (GH 7972)。

  • 修复了 groupby 中不带 name 属性的可调用对象会走错路径,并生成 DataFrame 而非 Series 的 bug (GH 7929)

  • 修复了 groupby 中 DataFrame 分组列重复时的错误消息 bug (GH 7511)

  • 修复了 read_htmlinfer_types 参数错误地强制转换日期类型数据的 bug (GH 7762, GH 7032)。

  • 修复了 Series.str.cat 在使用过滤掉第一个元素的索引时的 bug (GH 7857)

  • 修复了 Timestamp 无法从字符串解析 nanosecond 的 bug (GH 7878)

  • 修复了 Timestamp 使用字符串 offset 和 tz 导致结果不正确的 bug (GH 7833)

  • 修复了 tslib.tz_converttslib.tz_convert_single 可能返回不同结果的 bug (GH 7798)

  • 修复了 DatetimeIndex.intersection 处理不重叠的带 tz 的时间戳时引发 IndexError 的 bug (GH 7880)

  • 修复了 TimeOps 和非唯一索引对齐时的 bug (GH 8363)

  • 修复了 GroupBy.filter() 中快速路径与慢速路径导致过滤器返回看起来有效但实际上无效的非标量值的 bug (GH 7870)。

  • 修复了 date_range()/DatetimeIndex() 在从输入日期推断时区时,跨 DST 边界返回不正确时间的 bug (GH 7835, GH 7901)。

  • 修复了 to_excel() 中正无穷大被添加负号而负无穷大没有的 bug (GH 7949)

  • 修复了面积图在设置 stacked=True 时图例绘制的 alpha 不正确的 bug (GH 8027)

  • PeriodPeriodIndexnp.timedelta64 相加减导致内部表示不正确的 bug (GH 7740)

  • 修复了 Holiday 没有 offset 或 observance 的 bug (GH 7987)

  • 修复了 DataFrame.to_latex 在列或索引是 MultiIndex 时的格式化 bug (GH 7982)。

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

  • 修复了 DataFrame.shift 中空列在 numpy 1.7 上会抛出 ZeroDivisionError 的 bug (GH 8019)

  • 修复了安装 bug,其中 html_encoding/*.html 未安装,导致某些测试未能正确运行 (GH 7927)。

  • 修复了 read_html 中未在 _read 中测试 bytes 对象的 bug (GH 7927)。

  • 修复了 DataFrame.stack() 中当其中一个列级别是日期类型时的 bug (GH 8039)

  • 修复了将 numpy 标量广播到 DataFrame 时的 bug (GH 8116)

  • 修复了 pivot_table 使用无名 indexcolumns 执行时引发 KeyError 的 bug (GH 8103)

  • 修复了 DataFrame.plot(kind='scatter') 在颜色由 c 关键字指定时,绘制点和误差条颜色不同的 bug (GH 8081)

  • 修复了 Float64Indexiatat 未测试且失败的 bug (GH 8092)。

  • 修复了 DataFrame.boxplot() 在生成多个轴时 y 轴范围未正确设置的 bug (GH 7528, GH 5517)。

  • 修复了 read_csv 在给定自定义行结束符或 delim_whitespace=True 时,行注释未正确处理的 bug (GH 8122)。

  • 修复了 read_html 中空表导致 StopIteration 的 bug (GH 7575)

  • 修复了在同数据类型块中设置列时类型转换的 bug (GH 7704)

  • 修复了从 GroupBy 访问组时,原始 grouper 是元组时的 bug (GH 8121)。

  • 修复了 .at 在非整数索引上接受整数索引器并进行回退的 bug (GH 7814)

  • 修复了 kde 图和 NaNs 相关的 bug (GH 8182)

  • 修复了 GroupBy.count 在 float32 数据类型中未排除 nan 值的 bug (GH 8169)。

  • 修复了堆叠条形图和 NaNs 相关的 bug (GH 8175)。

  • 修复了 resample 在使用不能被均匀整除的 offset(如 ‘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__ 在将 dataframe 列设置为稀疏数组时导致错误的 bug (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 设置为零未触发 df 自动调整大小以适应终端宽度/高度 (GH 7180)。

  • 修复了 OLS 中使用 “cluster” 和 “nw_lags” 参数运行时不正确,但也不抛出错误的 bug (GH 5884)。

  • 修复了 DataFrame.dropna 中 subset 参数中不存在的列被解释为“最后一列”的 bug (GH 8303)

  • 修复了 Index.intersection 处理非单调非唯一索引时的 bug (GH 8362)。

  • 修复了 masked series 赋值中类型不匹配会破坏对齐的 bug (GH 8387)

  • 修复了 NDFrame.equals 在 dtype=object 时给出假阴性结果的 bug (GH 8437)

  • 修复了使用索引器进行赋值时,类型多样性会破坏对齐的 bug (GH 8258)

  • 修复了 NDFrame.loc 索引时,目标是 list/ndarray 会丢失行/列名称的 bug (GH 6552)

  • 修复了 NDFrame.loc 索引时,如果目标是空 list/ndarray,行/列会转换为 Float64Index 的回归问题 (GH 7774)

  • 修复了 Series 允许通过 DataFrame 索引导致意外结果的 bug。此类索引不再允许 (GH 8444)

  • 修复了具有 MultiIndex 列的 DataFrame 项目赋值时,右手边列未对齐的 bug (GH 7655)

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

  • 修复了 DataFrame.eval()not 运算符(~)的数据类型未被正确推断为 bool 的 bug。

贡献者#

共有 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 +