版本 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