Версия 0.22.0 (29 декабря 2017)#
Это крупный релиз по сравнению с версией 0.21.1 и включает одно изменение, нарушающее обратную совместимость API. Рекомендуем всем пользователям обновиться до этой версии после внимательного прочтения примечания к выпуску (единственного!).
Обратно несовместимые изменения API#
pandas 0.22.0 изменяет обработку пустых и полностьюNA суммы и произведения. Резюме заключается в том, что
Сумма пустого или всехNA
Seriesтеперь0Произведение пустого или полностьюNA
Seriesтеперь1Мы добавили
min_countпараметр для.sum()и.prod()управление минимальным количеством допустимых значений для валидности результата. Если меньше, чемmin_countне-NA значения присутствуют, результат NA. По умолчанию0. Чтобы вернутьNaN, поведение версии 0.21, используйтеmin_count=1.
Немного предыстории: В pandas 0.21 мы исправили давнюю несогласованность
в возвращаемом значении всех-NA series в зависимости от того, установлен ли bottleneck
или нет. См. Сумма/произведение всех-NaN или пустых Series/DataFrames теперь последовательно возвращает 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]: 0.0
Поведение по умолчанию такое же, как в pandas 0.20.3 с установленным bottleneck. Оно
также соответствует поведению NumPy np.nansum на пустых и полностью-NA массивы.
Чтобы сумма пустой серии возвращала NaN (поведение по умолчанию
pandas 0.20.3 без bottleneck, или pandas 0.21.x), используйте min_count
ключевое слово.
In [3]: pd.Series([]).sum(min_count=1)
Out[3]: nan
Благодаря skipna параметр, .sum на полностьюNA
series концептуально то же самое, что и .sum пустого с
skipna=True (по умолчанию).
In [4]: pd.Series([np.nan]).sum(min_count=1) # skipna=True by default
Out[4]: nan
The 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]: 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
Length: 2, 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
Length: 2, dtype: float64
Resample#
Сумма и произведение всех-NA bins изменился с NaN to 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
В частности, затронуты повышение частоты и взятие суммы или произведения, так как повышение частоты вводит пропущенные значения, даже если исходный ряд был полностью валидным.
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
Rolling и expanding#
Rolling и expanding уже имеют min_periods ключевое слово, которое ведет себя
аналогично min_count. Единственный случай, который изменяется, — это когда выполняется скользящая
или расширяющаяся сумма с min_periods=0. Ранее это возвращало NaN,
когда меньше чем min_periods не-NA значения были в окне. Теперь он
возвращает 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 [14]: s = pd.Series([np.nan, np.nan])
In [15]: s.rolling(2, min_periods=0).sum()
Out[15]:
0 0.0
1 0.0
Length: 2, 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
Обратите внимание, что несоответствие в возвращаемом значении для всех-NA series все еще существует для pandas 0.20.3 и более ранних версий. Избегание pandas 0.21 поможет только с пустым случаем.
Участники#
Всего 1 человек внесли патчи в этот выпуск. Люди с "+" рядом с именами внесли патч впервые.
Tom Augspurger