版本 0.22.0 (2017 年 12 月 29 日)#

這是繼 0.21.1 後的主要版本釋出,包含一項 API 變更。我們建議所有使用者在仔細閱讀發行說明(單數!)後升級到此版本。

向後不相容的 API 更改#

pandas 0.22.0 更改了空值和全 NA 求和與求積的處理方式。總結如下:

  • 空值或全 NA Series 的和現在為 0

  • 空值或全 NA Series 的積現在為 1

  • 我們為 .sum().prod() 添加了一個 min_count 引數,該引數控制結果有效所需的最小有效值數量。如果存在少於 min_count 個非 NA 值,則結果為 NA。預設值為 0。要返回 NaN(0.21 的行為),請使用 min_count=1

背景:在 pandas 0.21 中,我們修復了 all-NA Series 的返回值中一個長期存在的與是否安裝 bottleneck 相關的 Lisp 錯誤。請參閱 全 NaN 或空 Series/DataFrame 的求和/積現在一致為 NaN。同時,我們將空 Series 的求和與求積也改為 NaN

根據反饋,我們部分撤銷了這些更改。

算術運算#

空值或全 NA Series 的預設和現在為 0

pandas 0.21.x

In [1]: pd.Series([]).sum()
Out[1]: nan

In [2]: pd.Series([np.nan]).sum()
Out[2]: nan

pandas 0.22.0

In [1]: pd.Series([]).sum()
Out[1]: 0

In [2]: pd.Series([np.nan]).sum()
Out[2]: np.float64(0.0)

預設行為與安裝了 bottleneck 的 pandas 0.20.3 相同。它也與 NumPy 的 np.nansum 在處理空值和全 NA 陣列時的行為匹配。

要使空 Series 的和返回 NaN(pandas 0.20.3 未安裝 bottleneck 或 pandas 0.21.x 的預設行為),請使用 min_count 關鍵字。

In [3]: pd.Series([]).sum(min_count=1)
Out[3]: nan

感謝 skipna 引數,all-NA Series 的 .sum 在概念上與 skipna=True(預設值)的空 Series 的 .sum 相同。

In [4]: pd.Series([np.nan]).sum(min_count=1)  # skipna=True by default
Out[4]: np.float64(nan)

min_count 引數指的是非 NA 和或積所需的最小*非空*值的數量。

Series.prod() 已更新,行為與 Series.sum() 相同,返回 1

In [5]: pd.Series([]).prod()
Out[5]: 1

In [6]: pd.Series([np.nan]).prod()
Out[6]: np.float64(1.0)

In [7]: pd.Series([]).prod(min_count=1)
Out[7]: nan

這些更改也影響了 DataFrame.sum()DataFrame.prod()。最後,pandas 中一些不太明顯的地方也受到了此更改的影響。

按分類進行分組#

Categorical 分組並求和,對於沒有觀察值的類別,現在返回 0 而不是 NaN。求積現在返回 1 而不是 NaN

pandas 0.21.x

In [8]: grouper = pd.Categorical(['a', 'a'], categories=['a', 'b'])

In [9]: pd.Series([1, 2]).groupby(grouper, observed=False).sum()
Out[9]:
a    3.0
b    NaN
dtype: float64

pandas 0.22

In [8]: grouper = pd.Categorical(["a", "a"], categories=["a", "b"])

In [9]: pd.Series([1, 2]).groupby(grouper, observed=False).sum()
Out[9]: 
a    3
b    0
dtype: int64

要恢復 0.21 中為未觀察到的組返回 NaN 的行為,請使用 min_count>=1

In [10]: pd.Series([1, 2]).groupby(grouper, observed=False).sum(min_count=1)
Out[10]: 
a    3.0
b    NaN
dtype: float64

重取樣#

NA bin 的和與積已從 NaN 更改為求和為 0,求積為 1

pandas 0.21.x

In [11]: s = pd.Series([1, 1, np.nan, np.nan],
   ....:               index=pd.date_range('2017', periods=4))
   ....: s
Out[11]:
2017-01-01    1.0
2017-01-02    1.0
2017-01-03    NaN
2017-01-04    NaN
Freq: D, dtype: float64

In [12]: s.resample('2d').sum()
Out[12]:
2017-01-01    2.0
2017-01-03    NaN
Freq: 2D, dtype: float64

pandas 0.22.0

In [11]: s = pd.Series([1, 1, np.nan, np.nan],
   ....:               index=pd.date_range("2017", periods=4))

In [12]: s.resample("2d").sum()
Out[12]:
2017-01-01    2.0
2017-01-03    0.0
Freq: 2D, Length: 2, dtype: float64

要恢復 0.21 中返回 NaN 的行為,請使用 min_count>=1

In [13]: s.resample("2d").sum(min_count=1)
Out[13]:
2017-01-01    2.0
2017-01-03    NaN
Freq: 2D, Length: 2, dtype: float64

特別是,上取樣和求和或求積會受到影響,因為上取樣即使在原始 Series 完全有效的情況下也會引入缺失值。

pandas 0.21.x

In [14]: idx = pd.DatetimeIndex(['2017-01-01', '2017-01-02'])

In [15]: pd.Series([1, 2], index=idx).resample('12H').sum()
Out[15]:
2017-01-01 00:00:00    1.0
2017-01-01 12:00:00    NaN
2017-01-02 00:00:00    2.0
Freq: 12H, dtype: float64

pandas 0.22.0

In [14]: idx = pd.DatetimeIndex(["2017-01-01", "2017-01-02"])
In [15]: pd.Series([1, 2], index=idx).resample("12H").sum()
Out[15]:
2017-01-01 00:00:00    1
2017-01-01 12:00:00    0
2017-01-02 00:00:00    2
Freq: 12H, Length: 3, dtype: int64

再次強調,min_count 關鍵字可用於恢復 0.21 的行為。

In [16]: pd.Series([1, 2], index=idx).resample("12H").sum(min_count=1)
Out[16]:
2017-01-01 00:00:00    1.0
2017-01-01 12:00:00    NaN
2017-01-02 00:00:00    2.0
Freq: 12H, Length: 3, dtype: float64

滾動和展開#

滾動和展開已經有一個 min_periods 關鍵字,其行為類似於 min_count。唯一變化的案例是當進行滾動或展開求和且 min_periods=0 時。以前,當視窗中的非 NA 值少於 min_periods 時,此操作會返回 NaN。現在它返回 0

pandas 0.21.1

In [17]: s = pd.Series([np.nan, np.nan])

In [18]: s.rolling(2, min_periods=0).sum()
Out[18]:
0   NaN
1   NaN
dtype: float64

pandas 0.22.0

In [11]: s = pd.Series([np.nan, np.nan])

In [12]: s.rolling(2, min_periods=0).sum()
Out[12]: 
0    0.0
1    0.0
dtype: float64

min_periods=None 的預設行為(表示 min_periods 等於視窗大小)保持不變。

相容性#

如果您維護一個需要跨 pandas 版本工作的庫,最簡單的方法可能是將 pandas 0.21 從您的需求中排除。否則,您所有的 sum() 呼叫都需要在求和之前檢查 Series 是否為空。

使用 setuptools,在您的 setup.py 中使用

install_requires=['pandas!=0.21.*', ...]

使用 conda,請使用

requirements:
  run:
    - pandas !=0.21.0,!=0.21.1

請注意,all-NA Series 返回值的 Lisp 錯誤在 pandas 0.20.3 及更早版本中仍然存在。避免 pandas 0.21 只會對空值情況有幫助。

貢獻者#

共有 1 人為本次釋出貢獻了補丁。名字旁邊帶有“+”的人是首次貢獻補丁。

  • Tom Augspurger