Версия 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