版本 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 中的重构将两个参数的构造函数从“代码/标签和级别”改为“值和级别(现在称为‘类别’)”。这可能会导致细微的错误。如果你直接使用 Categorical,请在更新到这个pandas版本之前审查你的代码,并将其改为使用 from_codes() 构造函数。更多关于 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)。

欲查看完整文档,请参见 分类介绍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 已被移除。作为替代,构建一个数据框并使用 df.groupby(<group>).agg(<func>)

  • 不再支持向 Categorical 构造函数提供“代码/标签和级别”。现在向构造函数提供两个参数被解释为“值和级别(现在称为‘类别’)”。请更改您的代码以使用 from_codes() 构造函数。

  • Categorical.labels 属性已重命名为 Categorical.codes 并且是只读的。如果你想操作代码,请使用 Categoricals 的 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')]
  • Series 的迭代,例如 list(Series(...))timedelta64[ns] 在 v0.15.0 之前会为每个元素返回 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.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: 284.1+ 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         5800
Length: 9, dtype: int64

Series.dt 访问器#

Series 获得了一个访问器,可以简洁地返回 values 的类似日期时间的属性,如果它是一个类似日期时间/周期的 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]: zoneinfo.ZoneInfo(key='US/Eastern')

你也可以将这些类型的操作链接起来:

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]

时区处理改进#

  • 对于时区感知的 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)

  • 当插入到 Series/DataFrame 时,本地化为 UTC 的时间序列将保留 UTC 时区(而不是天真的 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 参数(见 list),因为当 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 开始,这是第二个(因为 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() 中存在一个错误,返回的结果按列名排序,并对非唯一列产生错误;现在处理非唯一列并按原始顺序返回列(除了两个 DataFrame 且 pairwise=False 的情况,行为不变)(GH 7542)

  • rolling_count()expanding_*() 函数在处理零长度数据时,不必要地产生错误信息 (GH 8056)

  • rolling_apply()expanding_apply()min_periods=0 解释为 min_periods=1 的错误 (GH 8080)

  • 对于单个值,expanding_std()expanding_var() 中的错误产生了一个令人困惑的错误消息 (GH 7900)

  • rolling_std()rolling_var() 中的错误,对于单个值产生 0 而不是 NaN (GH 7900)

  • bias=False``(默认值)时,:func:`ewmstd`、:func:`ewmvol`、:func:`ewmvar` :func:`ewmcov` 计算去偏因子时存在错误。之前使用了基于 ``adjust=Trueignore_na=True 和一个无限数量观测值的错误常数因子。现在每个条目使用不同的因子,基于实际权重(类似于通常的 N/(N-1) 因子)。特别是,当 bias=False 时,对于单个点返回 NaN 值,而之前返回的值大约为 0

    例如,考虑以下 ewmvar(..., bias=False) 在0.15.0版本之前的计算结果,以及相应的去偏因子:

    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 构造函数从两个参数从“代码/标签和级别”改为“值和级别(现在称为‘类别’)”。这可能导致细微的错误。如果你直接使用 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 改为对象(或根据调用报错)。现在使用 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和Python引擎,都忽略输入中的空行以及只要 sep 不是空白字符就忽略空白字符填充的行。这是一个可以通过关键字参数 skip_blank_lines 控制的API更改。请参阅 文档 (GH 4466)

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

  • 在从字典构造 DataFrame 时,传递带有未保留时区的 DatetimeIndex 的错误 (GH 7822)

    在之前的版本中,这会丢弃时区,现在它会保留时区,但会给出一列 object 数据类型:

    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 数据类型列,但没有时区信息。

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

  • 当传递多个级别给 stack() 时,如果级别不是所有的级别名称或所有的级别编号,它现在会引发一个 ValueError (GH 7660)。请参见 通过堆叠和解堆重塑

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

  • SettingWithCopy 根据选项 mode.chained_assignment 的设置,现在会在使用链式赋值对混合数据类型的 DataFrame 进行切片赋值时发出 raise/警告。(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)。

  • 之前,使用混合数据类型框架进行扩充的行为与 .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,而是继承 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 数组的方式类似)

  • MultiIndexes 现在在真值测试方面会与其他 pandas 对象类似地引发错误,请参见 这里 (GH 7897)。

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

弃用#

  • 属性 Categorical labelslevels 属性已被弃用,并重命名为 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']))
    
  • infer_types 参数在 read_html() 中现在没有效果并且已被弃用 (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)

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

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

  • 来自 DataFrame.plot 的箱形图,使用 kind='box' (GH 7998),参见 文档

其他:

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

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

  • describe() 在混合类型的 DataFrame 上更加灵活。现在可以通过 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 支持与 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() 现在支持选择多个第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 的频率是 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]')
    
  • 增加了与 openpyxl 版本 >= 2.0 的实验性兼容性。 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)

错误修复#

  • 在使用边距和字典aggfunc时,pivot_table中的错误 (GH 8349)

  • read_csv 中的一个错误,当 squeeze=True 时会返回一个视图 (GH 8217)

  • 在某些情况下 read_sql 中检查表名时存在错误 (GH 7826)。

  • DataFrame.groupby 中的错误,其中 Grouper 在指定频率时不识别级别 (GH 7885)

  • 当 DataFrame 保存到 SQL 表时,多索引 dtypes 混淆的错误 (GH 8021)

  • Series 中浮点数和整数操作数数据类型在0除法中的错误 (GH 7785)

  • Series.astype("unicode") 中的错误未正确调用 unicode 处理值 (GH 7758)

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

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

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

  • DatetimeIndexPeriodIndex 的就地加法和减法与正常操作的结果不同 (GH 6527)

  • 在加减 PeriodIndexPeriodIndex 时出现 TypeError 的错误 (GH 7741)

  • combine_firstPeriodIndex 数据中存在错误,引发 TypeError (GH 3367)

  • 使用缺失索引器进行 MultiIndex 切片时的错误 (GH 7866)

  • 在各种边缘情况下使用 MultiIndex 切片时的错误 (GH 8132)

  • 在带有非标量类型对象的 MultiIndex 索引中的回归 (GH 7914)

  • Timestamp 使用 ==int64 dtype 进行比较时的错误 (GH 8058)

  • pickles 中的错误包含 DateOffset 可能在内部引用 normalize 属性时引发 AttributeError (GH 7748)

  • 当使用 major_xscopy=False 时,Panel 中的错误(由于缺少 warnings 导致弃用警告失败)(GH 8152)。

  • 在反序列化 pickle 时出现的错误,对于带有重复项的 pre-0.14.1 容器失败,试图避免在匹配块和管理器项时的歧义,当只有一个块时没有歧义 (GH 7794)

  • PeriodIndex 放入 Series 中的错误会转换为 int64 数据类型,而不是 Periodsobject (GH 7932)

  • 在传递 where 时 HDFStore 迭代中的 Bug (GH 8014)

  • 在传递未排序的键时 DataFrameGroupby.transform 中的错误 (GH 8046, GH 8430)

  • 重复的时间序列线和区域图中的错误可能导致 ValueError 或不正确的类型 (GH 7733)

  • MultiIndex 中使用 datetime.date 输入的推理错误 (GH 7888)

  • get 中的一个错误,其中 IndexError 不会导致返回默认值 (GH 7725)

  • offsets.apply, rollforwardrollback 中的错误可能会重置纳秒 (GH 7697)

  • offsets.applyrollforwardrollback 中的错误可能会在 Timestamp 具有 dateutil tzinfo 时引发 AttributeError (GH 7697)

  • 在带有 Float64Index 的多索引框架中排序的错误 (GH 8017)

  • 在为对齐设置 DataFrame 的 rhs 时,面板 setitem 不一致的错误 (GH 7763)

  • is_superperiodis_subperiod 中的错误无法处理高于 S 的频率(GH 7760, GH 7772, GH 7803

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

  • PeriodIndex.unique 中的错误返回 int64 np.ndarray (GH 7540)

  • groupby.apply 中在函数中存在不影响结果的突变的问题 (GH 8467)

  • DataFrame.reset_index 中的错误,当 MultiIndex 包含 PeriodIndex 或带时区的 DatetimeIndex 时会引发 ValueError (GH 7746, GH 7793)

  • DataFrame.plot 中使用 subplots=True 时可能会绘制不必要的次要 xticks 和 yticks (GH 7801)

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

  • StataReader 中的一个错误,其中字符串总是被转换为244个字符的固定宽度,而不考虑底层字符串的大小 (GH 7858)

  • DataFrame.plotSeries.plot 中的错误可能会忽略 rotfontsize 关键字 (GH 7844)

  • DatetimeIndex.value_counts 中的错误不保留时区 (GH 7735)

  • PeriodIndex.value_counts 中的错误导致 Int64Index (GH 7735)

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

  • GroupBy.transform() 中存在一个错误,当使用不保留索引的转换对整数组进行分组时,结果会被错误地截断 (GH 7972)。

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

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

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

  • Series.str.cat 中存在一个错误,该错误发生在索引被过滤为不包括第一个项目的情况下 (GH 7857)

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

  • Timestamp 中带有字符串偏移和 tz 导致结果不正确 (GH 7833)

  • tslib.tz_converttslib.tz_convert_single 中的错误可能会返回不同的结果 (GH 7798)

  • DatetimeIndex.intersection 中,非重叠时间戳与时区引发 IndexError (GH 7880)

  • 与 TimeOps 对齐的错误和非唯一索引 (GH 8363)

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

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

  • to_excel() 中的一个错误,正无穷大前加了一个负号,而负无穷大前没有负号 (GH 7949)

  • stacked=True 时,区域图中的错误会在图例中以不正确的 alpha 绘制 (GH 8027)

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

  • Holiday 中没有偏移或遵守的错误 (GH 7987)

  • 当列或索引是 MultiIndex 时,DataFrame.to_latex 格式化中的错误 (GH 7982)。

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

  • DataFrame.shift 中的一个错误,在 numpy 1.7 上会导致空列抛出 ZeroDivisionError (GH 8019)

  • 安装中的一个错误,其中 html_encoding/*.html 没有被安装,因此一些测试没有正确运行 (GH 7927)。

  • read_html 中的 bytes 对象在 _read 中未被测试的错误 (GH 7927)。

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

  • DataFrame 中广播 numpy 标量时出现错误 (GH 8116)

  • pivot_table 中使用无名的 indexcolumns 会引发 KeyError (GH 8103)

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

  • Float64Index 中的错误,其中 iatat 未经过测试并失败 (GH 8092)。

  • DataFrame.boxplot() 中存在一个错误,当生成多个轴时,y 轴限制设置不正确 (GH 7528, GH 5517)。

  • read_csv 中的一个错误,当给定自定义行终止符或 delim_whitespace=True 时,行注释未正确处理 (GH 8122)。

  • read_html 中的一个错误,空表导致 StopIteration (GH 7575)

  • 在设置相同数据类型块中的列时进行类型转换的错误 (GH 7704)

  • 当原始分组器是一个元组时,从 GroupBy 访问组的错误 (GH 8121)。

  • .at 中的一个错误,该错误会在非整数索引上接受整数索引器并进行回退 (GH 7814)

  • kde 图和 NaN 的错误 (GH 8182)

  • GroupBy.count 中使用 float32 数据类型时,nan 值未被排除的错误 (GH 8169)。

  • 带有堆叠条形图和 NaNs 的错误 (GH 8175)。

  • 在非均匀可除偏移量(例如 ‘7s’)下的重采样错误 (GH 8371)

  • 在使用 limit 关键字时的插值方法中存在错误,当不需要插值时 (GH 7173)。

  • header=False 时,col_spaceDataFrame.to_string() 中被忽略的错误 (GH 8230)。

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

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

  • DataFrame.__setitem__ 中的一个错误,当将数据框列设置为稀疏数组时会导致错误 (GH 8131)

  • 当整个列都为空时,Dataframe.boxplot() 失败的错误 (GH 8181)。

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

  • 在使用 limit 关键字时的插值方法中存在错误,当不需要插值时 (GH 7173)。

  • header=False 时,col_spaceDataFrame.to_string() 中被忽略的错误 (GH 8230)。

  • to_clipboard 中的错误会导致长列数据被剪切 (GH 8305)

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

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

  • DataFrame.dropna 中的一个错误,将子集参数中不存在的列解释为 ‘最后一列’ (GH 8303)

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

  • 在掩码系列赋值中存在一个错误,当类型不匹配时会破坏对齐 (GH 8387)

  • NDFrame.equals 中的错误在 dtype=object 时给出假阴性 (GH 8437)

  • 在索引器赋值中的错误,类型多样性会破坏对齐 (GH 8258)

  • 当目标是一个列表/ndarray时,NDFrame.loc 索引中的错误导致行/列名称丢失 (GH 6552)

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

  • Series 中的一个错误,允许它通过一个会产生意外结果的 DataFrame 进行索引。这种索引不再被允许 (GH 8444)

  • 在具有 MultiIndex 列的 DataFrame 的项目分配中存在一个错误,其中右侧列未对齐 (GH 7655)

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

  • DataFrame.eval() 中的一个错误,其中 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 +