Что нового в 0.25.0 (18 июля 2019)#

Предупреждение

Начиная с серии выпусков 0.25.x, pandas поддерживает только Python 3.5.3 и выше. См. Удаление Python 2.7 для получения дополнительной информации.

Предупреждение

Минимальная поддерживаемая версия Python будет повышена до 3.6 в будущем релизе.

Предупреждение

Panel был полностью удален. Для N-мерных помеченных структур данных, пожалуйста, используйте xarray

Предупреждение

read_pickle() и read_msgpack() гарантируется обратная совместимость только до версии pandas 0.20.3 (GH 27082)

Это изменения в pandas 0.25.0. См. Примечания к выпуску для полного списка изменений, включая другие версии pandas.

Улучшения#

Агрегация GroupBy с переименованием#

pandas добавил специальное поведение groupby, известное как "именованная агрегация", для именования выходных столбцов при применении нескольких агрегационных функций к определенным столбцам (GH 18366, GH 26512).

In [1]: animals = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
   ...:                         'height': [9.1, 6.0, 9.5, 34.0],
   ...:                         'weight': [7.9, 7.5, 9.9, 198.0]})
   ...: 

In [2]: animals
Out[2]: 
  kind  height  weight
0  cat     9.1     7.9
1  dog     6.0     7.5
2  cat     9.5     9.9
3  dog    34.0   198.0

[4 rows x 3 columns]

In [3]: animals.groupby("kind").agg(
   ...:     min_height=pd.NamedAgg(column='height', aggfunc='min'),
   ...:     max_height=pd.NamedAgg(column='height', aggfunc='max'),
   ...:     average_weight=pd.NamedAgg(column='weight', aggfunc="mean"),
   ...: )
   ...: 
Out[3]: 
      min_height  max_height  average_weight
kind                                        
cat          9.1         9.5            8.90
dog          6.0        34.0          102.75

[2 rows x 3 columns]

Передайте желаемые имена столбцов как **kwargs to .agg. Значения **kwargs должны быть кортежами, где первый элемент - выбор столбца, а второй - агрегирующая функция для применения. pandas предоставляет pandas.NamedAgg namedtuple для более ясного обозначения аргументов функции, но также принимаются обычные кортежи.

In [4]: animals.groupby("kind").agg(
   ...:     min_height=('height', 'min'),
   ...:     max_height=('height', 'max'),
   ...:     average_weight=('weight', 'mean'),
   ...: )
   ...: 
Out[4]: 
      min_height  max_height  average_weight
kind                                        
cat          9.1         9.5            8.90
dog          6.0        34.0          102.75

[2 rows x 3 columns]

Именованная агрегация — рекомендуемая замена устаревшего подхода «словарь словарей» для именования вывода агрегаций по столбцам (Устаревание groupby.agg() со словарём при переименовании).

Аналогичный подход теперь доступен и для объектов groupby Series. Поскольку нет необходимости в выборе столбцов, значениями могут быть просто применяемые функции

In [5]: animals.groupby("kind").height.agg(
   ...:     min_height="min",
   ...:     max_height="max",
   ...: )
   ...: 
Out[5]: 
      min_height  max_height
kind                        
cat          9.1         9.5
dog          6.0        34.0

[2 rows x 2 columns]

Этот тип агрегации является рекомендуемой альтернативой устаревшему поведению при передаче словаря в агрегацию группировки Series (Устаревание groupby.agg() со словарём при переименовании).

См. Именованная агрегация подробнее.

Групповая агрегация с несколькими лямбда-функциями#

Теперь вы можете предоставить несколько лямбда-функций для агрегации в виде списка в GroupBy.agg (GH 26430).

In [6]: animals.groupby('kind').height.agg([
   ...:     lambda x: x.iloc[0], lambda x: x.iloc[-1]
   ...: ])
   ...: 
Out[6]: 
        
kind                        
cat          9.1         9.5
dog          6.0        34.0

[2 rows x 2 columns]

In [7]: animals.groupby('kind').agg([
   ...:     lambda x: x.iloc[0] - x.iloc[1],
   ...:     lambda x: x.iloc[0] + x.iloc[1]
   ...: ])
   ...: 
Out[7]: 
         height                weight           
        
kind                                            
cat        -0.4       18.6       -2.0       17.8
dog       -28.0       40.0     -190.5      205.5

[2 rows x 4 columns]

Ранее это вызывало SpecificationError.

Улучшенное repr для MultiIndex#

Печать MultiIndex экземпляры теперь показывают кортежи каждой строки и обеспечивают вертикальное выравнивание элементов кортежа, что упрощает понимание структуры MultiIndex. (GH 13480):

Теперь repr выглядит так:

In [8]: pd.MultiIndex.from_product([['a', 'abc'], range(500)])
Out[8]: 
MultiIndex([(  'a',   0),
            (  'a',   1),
            (  'a',   2),
            (  'a',   3),
            (  'a',   4),
            (  'a',   5),
            (  'a',   6),
            (  'a',   7),
            (  'a',   8),
            (  'a',   9),
            ...
            ('abc', 490),
            ('abc', 491),
            ('abc', 492),
            ('abc', 493),
            ('abc', 494),
            ('abc', 495),
            ('abc', 496),
            ('abc', 497),
            ('abc', 498),
            ('abc', 499)],
           length=1000)

Ранее вывод MultiIndex выводились все levels и codes из MultiIndex, что было визуально непривлекательно и затрудняло навигацию по выводу. Например (ограничивая диапазон до 5):

In [1]: pd.MultiIndex.from_product([['a', 'abc'], range(5)])
Out[1]: MultiIndex(levels=[['a', 'abc'], [0, 1, 2, 3]],
   ...:            codes=[[0, 0, 0, 0, 1, 1, 1, 1], [0, 1, 2, 3, 0, 1, 2, 3]])

В новом представлении все значения будут показаны, если количество строк меньше чем options.display.max_seq_items (по умолчанию: 100 элементов). По горизонтали вывод будет обрезан, если он шире, чем options.display.width (по умолчанию: 80 символов).

Сокращённое представление для Series и DataFrame#

В настоящее время параметры отображения pandas по умолчанию гарантируют, что когда Series или DataFrame содержит более 60 строк, их repr обрезается до этого максимума в 60 строк ( display.max_rows опция). Однако это все равно дает repr, занимающий большую часть вертикального пространства экрана. Поэтому новая опция display.min_rows вводится со значением по умолчанию 10, которое определяет количество строк, отображаемых в усечённом представлении:

  • Для небольших Series или DataFrame, до max_rows показывается количество строк (по умолчанию: 60).

  • Для больших Series или DataFrame с длиной выше max_rows, только min_rows показывается количество строк (по умолчанию: 10, т.е. первые и последние 5 строк).

Эта двойная опция позволяет по-прежнему видеть полное содержимое относительно небольших объектов (например, df.head(20) показывает все 20 строк), давая краткое представление для больших объектов.

Чтобы восстановить предыдущее поведение с одним порогом, установите pd.options.display.min_rows = None.

JSON normalize с поддержкой параметра max_level#

json_normalize() нормализует предоставленный входной словарь на всех вложенных уровнях. Новый параметр max_level обеспечивает больший контроль над уровнем, на котором завершить нормализацию (GH 23843):

Теперь repr выглядит так:

from pandas.io.json import json_normalize
data = [{
    'CreatedBy': {'Name': 'User001'},
    'Lookup': {'TextField': 'Some text',
               'UserField': {'Id': 'ID001', 'Name': 'Name001'}},
    'Image': {'a': 'b'}
}]
json_normalize(data, max_level=1)

Series.explode для разделения спископодобных значений на строки#

Series и DataFrame получили DataFrame.explode() методы преобразования списков в отдельные строки. См. раздел о преобразовании столбца со списком в документации для получения дополнительной информации (GH 16538, GH 10511)

Вот типичный случай использования. У вас есть строка, разделенная запятыми, в столбце.

In [9]: df = pd.DataFrame([{'var1': 'a,b,c', 'var2': 1},
   ...:                    {'var1': 'd,e,f', 'var2': 2}])
   ...: 

In [10]: df
Out[10]: 
    var1  var2
0  a,b,c     1
1  d,e,f     2

[2 rows x 2 columns]

Создание длинной формы DataFrame теперь просто с использованием цепочечных операций

In [11]: df.assign(var1=df.var1.str.split(',')).explode('var1')
Out[11]: 
  var1  var2
0    a     1
0    b     1
0    c     1
1    d     2
1    e     2
1    f     2

[6 rows x 2 columns]

Другие улучшения#

  • DataFrame.plot() ключевые слова logy, logx и loglog теперь может принимать значение 'sym' для симметричного логарифмического масштабирования. (GH 24867)

  • Добавлена поддержка формата недельного года ISO ('%G-%V-%u') при разборе дат и времени с использованием to_datetime() (GH 16607)

  • Индексирование DataFrame и Series теперь принимает zerodim np.ndarray (GH 24919)

  • Timestamp.replace() теперь поддерживает fold аргумент для устранения неоднозначности времён перехода на летнее время (GH 25017)

  • DataFrame.at_time() и Series.at_time() теперь поддерживает datetime.time объекты с часовыми поясами (GH 24043)

  • DataFrame.pivot_table() теперь принимает observed параметр, который передается в базовые вызовы DataFrame.groupby() для ускорения группировки категориальных данных. (GH 24923)

  • Series.str получил Series.str.casefold() метод для удаления всех различий регистра, присутствующих в строке (GH 25405)

  • DataFrame.set_index() теперь работает для экземпляров abc.Iterator, при условии, что их вывод имеет ту же длину, что и вызывающий фрейм (GH 22484, GH 24984)

  • DatetimeIndex.union() теперь поддерживает sort аргумент. Поведение параметра sort соответствует поведению Index.union() (GH 24994)

  • RangeIndex.union() теперь поддерживает sort аргумент. Если sort=False несортированный Int64Index всегда возвращается. sort=None является значением по умолчанию и возвращает монотонно возрастающий RangeIndex если возможно, или отсортированный Int64Index если не (GH 24471)

  • TimedeltaIndex.intersection() теперь также поддерживает sort ключевое слово (GH 24471)

  • DataFrame.rename() теперь поддерживает errors аргумент для вызова ошибок при попытке переименовать несуществующие ключи (GH 13473)

  • Добавлен Sparse аксессор для работы с DataFrame значения которых разрежены (GH 25681)

  • RangeIndex получил start, stop, и step атрибуты (GH 25710)

  • datetime.timezone объекты теперь поддерживаются в качестве аргументов для методов и конструкторов часовых поясов (GH 25065)

  • DataFrame.query() и DataFrame.eval() теперь поддерживает заключение имен столбцов в обратные кавычки для ссылки на имена с пробелами (GH 6508)

  • merge_asof() теперь выдает более понятное сообщение об ошибке, когда ключи слияния — категориальные, но не равны (GH 26136)

  • Rolling() поддерживает экспоненциальный (или Пуассоновский) тип окна (GH 21303)

  • Сообщение об ошибке для отсутствующих обязательных импортов теперь включает текст исходной ошибки импорта (GH 23868)

  • DatetimeIndex и TimedeltaIndex теперь имеют mean метод (GH 24757)

  • DataFrame.describe() теперь форматирует целые процентили без десятичной точки (GH 26660)

  • Добавлена поддержка чтения файлов SPSS .sav с использованием read_spss() (GH 26537)

  • Добавлена новая опция plotting.backend чтобы иметь возможность выбрать бэкенд построения графиков, отличный от существующего matplotlib один. Используйте pandas.set_option('plotting.backend', '') где это библиотека, реализующая API построения графиков pandas (GH 14130)

  • pandas.offsets.BusinessHour поддерживает несколько интервалов рабочего времени (GH 15481)

  • read_excel() теперь может использовать openpyxl для чтения файлов Excel через engine='openpyxl' аргумент. Это станет значением по умолчанию в будущем релизе (GH 11499)

  • pandas.io.excel.read_excel() поддерживает чтение таблиц OpenDocument. Укажите engine='odf' для включения. Обратитесь к Руководство пользователя IO для дополнительных деталей (GH 9070)

  • Interval, IntervalIndex, и IntervalArray получили is_empty атрибут, указывающий, являются ли заданные интервалы пустыми (GH 27219)

Обратно несовместимые изменения API#

Индексирование строк дат со смещениями UTC#

Индексирование DataFrame или Series с DatetimeIndex с датой в строковом формате со смещением UTC ранее игнорировало смещение UTC. Теперь смещение UTC учитывается при индексировании. (GH 24076, GH 16785)

In [12]: df = pd.DataFrame([0], index=pd.DatetimeIndex(['2019-01-01'], tz='US/Pacific'))

In [13]: df
Out[13]: 
                           0
2019-01-01 00:00:00-08:00  0

[1 rows x 1 columns]

Предыдущее поведение:

In [3]: df['2019-01-01 00:00:00+04:00':'2019-01-01 01:00:00+04:00']
Out[3]:
                           0
2019-01-01 00:00:00-08:00  0

Новое поведение:

In [14]: df['2019-01-01 12:00:00+04:00':'2019-01-01 13:00:00+04:00']
Out[14]: 
                           0
2019-01-01 00:00:00-08:00  0

[1 rows x 1 columns]

MultiIndex построенный из уровней и кодов#

Создание MultiIndex с NaN ранее допускались уровни или значения кодов < -1. Теперь создание со значением кода < -1 не допускается и NaN соответствующие коды уровней будут переназначены как -1. (GH 19387)

Предыдущее поведение:

In [1]: pd.MultiIndex(levels=[[np.nan, None, pd.NaT, 128, 2]],
   ...:               codes=[[0, -1, 1, 2, 3, 4]])
   ...:
Out[1]: MultiIndex(levels=[[nan, None, NaT, 128, 2]],
                   codes=[[0, -1, 1, 2, 3, 4]])

In [2]: pd.MultiIndex(levels=[[1, 2]], codes=[[0, -2]])
Out[2]: MultiIndex(levels=[[1, 2]],
                   codes=[[0, -2]])

Новое поведение:

In [15]: pd.MultiIndex(levels=[[np.nan, None, pd.NaT, 128, 2]],
   ....:               codes=[[0, -1, 1, 2, 3, 4]])
   ....: 
Out[15]: 
MultiIndex([(nan,),
            (nan,),
            (nan,),
            (nan,),
            (128,),
            (  2,)],
           )

In [16]: pd.MultiIndex(levels=[[1, 2]], codes=[[0, -2]])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[16], line 1
----> 1 pd.MultiIndex(levels=[[1, 2]], codes=[[0, -2]])

File ~/work/pandas/pandas/pandas/core/indexes/multi.py:365, in MultiIndex.__new__(cls, levels, codes, sortorder, names, dtype, copy, name, verify_integrity)
    362     result.sortorder = sortorder
    364 if verify_integrity:
--> 365     new_codes = result._verify_integrity()
    366     result._codes = new_codes
    368 result._reset_identity()

File ~/work/pandas/pandas/pandas/core/indexes/multi.py:452, in MultiIndex._verify_integrity(self, codes, levels, levels_to_verify)
    446     raise ValueError(
    447         f"On level {i}, code max ({level_codes.max()}) >= length of "
    448         f"level ({len(level)}). NOTE: this index is in an "
    449         "inconsistent state"
    450     )
    451 if len(level_codes) and level_codes.min() < -1:
--> 452     raise ValueError(f"On level {i}, code value ({level_codes.min()}) < -1")
    453 if not level.is_unique:
    454     raise ValueError(
    455         f"Level values must be unique: {list(level)} on level {i}"
    456     )

ValueError: On level 0, code value (-2) < -1

GroupBy.apply на DataFrame оценивает первую группу только один раз#

Реализация DataFrameGroupBy.apply() ранее выполнял предоставленную функцию дважды для первой группы чтобы определить, безопасно ли использовать быстрый путь выполнения. Особенно для функций с побочными эффектами это было нежелательным поведением и могло приводить к неожиданностям. (GH 2936, GH 2656, GH 7739, GH 10519, GH 12155, GH 20084, GH 21417)

Теперь каждая группа вычисляется только один раз.

In [17]: df = pd.DataFrame({"a": ["x", "y"], "b": [1, 2]})

In [18]: df
Out[18]: 
   a  b
0  x  1
1  y  2

[2 rows x 2 columns]

In [19]: def func(group):
   ....:     print(group.name)
   ....:     return group
   ....: 

Предыдущее поведение:

In [3]: df.groupby('a').apply(func)
x
x
y
Out[3]:
   a  b
0  x  1
1  y  2

Новое поведение:

In [3]: df.groupby('a').apply(func)
x
y
Out[3]:
   a  b
0  x  1
1  y  2

Объединение разреженных значений#

При передаче DataFrame, значения которых являются разреженными, concat() теперь возвращает Series или DataFrame с разреженными значениями, а не с SparseDataFrame (GH 25702).

In [20]: df = pd.DataFrame({"A": pd.arrays.SparseArray([0, 1])})

Предыдущее поведение:

In [2]: type(pd.concat([df, df]))
pandas.core.sparse.frame.SparseDataFrame

Новое поведение:

In [21]: type(pd.concat([df, df]))
Out[21]: pandas.core.frame.DataFrame

Теперь это соответствует существующему поведению concat на Series со значениями sparse. concat() продолжит возвращать SparseDataFrame когда все значения являются экземплярами SparseDataFrame.

Это изменение также затрагивает процедуры, использующие concat() внутренне, как get_dummies(), который теперь возвращает DataFrame во всех случаях (ранее SparseDataFrame возвращалось, если все столбцы были закодированы как фиктивные, и DataFrame в противном случае).

Предоставление любого SparseSeries или SparseDataFrame to concat() вызовет SparseSeries или SparseDataFrame для возврата, как и раньше.

The .str-аксессор выполняет более строгие проверки типов#

Из-за отсутствия более детальных типов данных, Series.str пока что проверял только, были ли данные object тип данных. Series.str теперь будет определять тип данных внутри Series; в частности, 'bytes'-only данные вызовут исключение (кроме Series.str.decode(), Series.str.get(), Series.str.len(), Series.str.slice()), см. GH 23163, GH 23011, GH 23551.

Предыдущее поведение:

In [1]: s = pd.Series(np.array(['a', 'ba', 'cba'], 'S'), dtype=object)

In [2]: s
Out[2]:
0      b'a'
1     b'ba'
2    b'cba'
dtype: object

In [3]: s.str.startswith(b'a')
Out[3]:
0     True
1    False
2    False
dtype: bool

Новое поведение:

In [22]: s = pd.Series(np.array(['a', 'ba', 'cba'], 'S'), dtype=object)

In [23]: s
Out[23]: 
0      b'a'
1     b'ba'
2    b'cba'
Length: 3, dtype: object

In [24]: s.str.startswith(b'a')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[24], line 1
----> 1 s.str.startswith(b'a')

File ~/work/pandas/pandas/pandas/core/strings/accessor.py:139, in forbid_nonstring_types.._forbid_nonstring_types..wrapper(self, *args, **kwargs)
    134 if self._inferred_dtype not in allowed_types:
    135     msg = (
    136         f"Cannot use .str.{func_name} with values of "
    137         f"inferred dtype '{self._inferred_dtype}'."
    138     )
--> 139     raise TypeError(msg)
    140 return func(self, *args, **kwargs)

TypeError: Cannot use .str.startswith with values of inferred dtype 'bytes'.

Категориальные типы данных сохраняются во время GroupBy#

Ранее столбцы, которые были категориальными, но не являлись ключами группировки, преобразовывались в object dtype во время операций groupby. Теперь pandas будет сохранять эти dtypes. (GH 18502)

In [25]: cat = pd.Categorical(["foo", "bar", "bar", "qux"], ordered=True)

In [26]: df = pd.DataFrame({'payload': [-1, -2, -1, -2], 'col': cat})

In [27]: df
Out[27]: 
   payload  col
0       -1  foo
1       -2  bar
2       -1  bar
3       -2  qux

[4 rows x 2 columns]

In [28]: df.dtypes
Out[28]: 
payload       int64
col        category
Length: 2, dtype: object

Предыдущее поведение:

In [5]: df.groupby('payload').first().col.dtype
Out[5]: dtype('O')

Новое поведение:

In [29]: df.groupby('payload').first().col.dtype
Out[29]: CategoricalDtype(categories=['bar', 'foo', 'qux'], ordered=True, categories_dtype=object)

Несовместимые объединения типов индексов#

При выполнении Index.union() nan Index типа данных object. Это поведение сохраняется для объединений между Index объекты, которые ранее были запрещены. Тип данных пустого Index объекты теперь будут оцениваться перед выполнением операций объединения, а не просто возвращать другой Index объект. Index.union() теперь можно считать коммутативной, так что A.union(B) == B.union(A) (GH 23525).

Предыдущее поведение:

In [1]: pd.period_range('19910905', periods=2).union(pd.Int64Index([1, 2, 3]))
...
ValueError: can only call with other PeriodIndex-ed objects

In [2]: pd.Index([], dtype=object).union(pd.Index([1, 2, 3]))
Out[2]: Int64Index([1, 2, 3], dtype='int64')

Новое поведение:

In [3]: pd.period_range('19910905', periods=2).union(pd.Int64Index([1, 2, 3]))
Out[3]: Index([1991-09-05, 1991-09-06, 1, 2, 3], dtype='object')
In [4]: pd.Index([], dtype=object).union(pd.Index([1, 2, 3]))
Out[4]: Index([1, 2, 3], dtype='object')

Обратите внимание, что индексы целочисленного и плавающего типов считаются "совместимыми". Целочисленные значения приводятся к плавающей точке, что может привести к потере точности. См. Операции над множествами для объектов Index подробнее.

DataFrame GroupBy ffill/bfill больше не возвращают метки групп#

Методы ffill, bfill, pad и backfill of DataFrameGroupBy ранее включал метки групп в возвращаемое значение, что было несовместимо с другими преобразованиями groupby. Теперь возвращаются только заполненные значения. (GH 21521)

In [30]: df = pd.DataFrame({"a": ["x", "y"], "b": [1, 2]})

In [31]: df
Out[31]: 
   a  b
0  x  1
1  y  2

[2 rows x 2 columns]

Предыдущее поведение:

In [3]: df.groupby("a").ffill()
Out[3]:
   a  b
0  x  1
1  y  2

Новое поведение:

In [32]: df.groupby("a").ffill()
Out[32]: 
   b
0  1
1  2

[2 rows x 1 columns]

DataFrame describe для пустого категориального/объектного столбца вернет top и freq#

При вызове DataFrame.describe() При пустом категориальном/объектном столбце столбцы 'top' и 'freq' ранее опускались, что было несогласованно с выводом для непустых столбцов. Теперь столбцы 'top' и 'freq' будут всегда включаться, numpy.nan в случае пустого DataFrame (GH 26397)

In [33]: df = pd.DataFrame({"empty_col": pd.Categorical([])})

In [34]: df
Out[34]: 
Empty DataFrame
Columns: [empty_col]
Index: []

[0 rows x 1 columns]

Предыдущее поведение:

In [3]: df.describe()
Out[3]:
        empty_col
count           0
unique          0

Новое поведение:

In [35]: df.describe()
Out[35]: 
       empty_col
count          0
unique         0
top          NaN
freq         NaN

[4 rows x 1 columns]

__str__ методы теперь вызывают __repr__ а не наоборот#

pandas до сих пор в основном определял строковые представления в __str__/__unicode__/__bytes__ методы, и вызывается __str__ из __repr__ метод, если конкретный __repr__ метод не найден. Это не требуется для Python3. В pandas 0.25 строковые представления объектов pandas теперь обычно определяются в __repr__, и вызовы __str__ в целом теперь передают вызов в __repr__, если конкретный __str__ метод не существует, как это принято в Python. Это изменение обратно совместимо для прямого использования pandas, но если вы создаете подклассы объектов pandas и дайте вашим подклассам конкретные __str__/__repr__ методов, вам может потребоваться настроить свои __str__/__repr__ методы (GH 26495).

Индексирование IntervalIndex с Interval объекты#

Методы индексации для IntervalIndex были изменены, чтобы требовать только точных совпадений для Interval запросы. IntervalIndex методы ранее совпадали при любом перекрытии Interval. Поведение со скалярными точками, например, запрос с целым числом, не изменяется (GH 16316).

In [36]: ii = pd.IntervalIndex.from_tuples([(0, 4), (1, 5), (5, 8)])

In [37]: ii
Out[37]: IntervalIndex([(0, 4], (1, 5], (5, 8]], dtype='interval[int64, right]')

The in оператор (__contains__) теперь возвращает только True для точных совпадений с Intervals в IntervalIndex, тогда как ранее это возвращало True для любого Interval перекрывающий Interval в IntervalIndex.

Предыдущее поведение:

In [4]: pd.Interval(1, 2, closed='neither') in ii
Out[4]: True

In [5]: pd.Interval(-10, 10, closed='both') in ii
Out[5]: True

Новое поведение:

In [38]: pd.Interval(1, 2, closed='neither') in ii
Out[38]: False

In [39]: pd.Interval(-10, 10, closed='both') in ii
Out[39]: False

The get_loc() метод теперь возвращает только местоположения для точных совпадений с Interval запросы, в отличие от предыдущего поведения возврата местоположений для перекрывающихся совпадений. KeyError будет вызвано, если точное совпадение не найдено.

Предыдущее поведение:

In [6]: ii.get_loc(pd.Interval(1, 5))
Out[6]: array([0, 1])

In [7]: ii.get_loc(pd.Interval(2, 6))
Out[7]: array([0, 1, 2])

Новое поведение:

In [6]: ii.get_loc(pd.Interval(1, 5))
Out[6]: 1

In [7]: ii.get_loc(pd.Interval(2, 6))
---------------------------------------------------------------------------
KeyError: Interval(2, 6, closed='right')

Аналогично, get_indexer() и get_indexer_non_unique() также будет возвращать только местоположения для точных совпадений с Interval запросы, с -1 указывает, что точное совпадение не найдено.

Эти изменения индексации распространяются на запрос к Series или DataFrame с IntervalIndex index.

In [40]: s = pd.Series(list('abc'), index=ii)

In [41]: s
Out[41]: 
(0, 4]    a
(1, 5]    b
(5, 8]    c
Length: 3, dtype: object

Выбор из Series или DataFrame используя [] (__getitem__) или loc теперь возвращает только точные совпадения для Interval запросы.

Предыдущее поведение:

In [8]: s[pd.Interval(1, 5)]
Out[8]:
(0, 4]    a
(1, 5]    b
dtype: object

In [9]: s.loc[pd.Interval(1, 5)]
Out[9]:
(0, 4]    a
(1, 5]    b
dtype: object

Новое поведение:

In [42]: s[pd.Interval(1, 5)]
Out[42]: 'b'

In [43]: s.loc[pd.Interval(1, 5)]
Out[43]: 'b'

Аналогично, KeyError будет вызываться для неточных совпадений вместо возврата перекрывающихся совпадений.

Предыдущее поведение:

In [9]: s[pd.Interval(2, 3)]
Out[9]:
(0, 4]    a
(1, 5]    b
dtype: object

In [10]: s.loc[pd.Interval(2, 3)]
Out[10]:
(0, 4]    a
(1, 5]    b
dtype: object

Новое поведение:

In [6]: s[pd.Interval(2, 3)]
---------------------------------------------------------------------------
KeyError: Interval(2, 3, closed='right')

In [7]: s.loc[pd.Interval(2, 3)]
---------------------------------------------------------------------------
KeyError: Interval(2, 3, closed='right')

The overlaps() метод может быть использован для создания булева индексатора, который воспроизводит предыдущее поведение возврата перекрывающихся совпадений.

Новое поведение:

In [44]: idxr = s.index.overlaps(pd.Interval(2, 3))

In [45]: idxr
Out[45]: array([ True,  True, False])

In [46]: s[idxr]
Out[46]: 
(0, 4]    a
(1, 5]    b
Length: 2, dtype: object

In [47]: s.loc[idxr]
Out[47]: 
(0, 4]    a
(1, 5]    b
Length: 2, dtype: object

Бинарные ufuncs для Series теперь выравниваются#

Применение бинарной универсальной функции, такой как numpy.power() теперь выравнивает входные данные когда оба являются Series (GH 23293).

In [48]: s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])

In [49]: s2 = pd.Series([3, 4, 5], index=['d', 'c', 'b'])

In [50]: s1
Out[50]: 
a    1
b    2
c    3
Length: 3, dtype: int64

In [51]: s2
Out[51]: 
d    3
c    4
b    5
Length: 3, dtype: int64

Предыдущее поведение

In [5]: np.power(s1, s2)
Out[5]:
a      1
b     16
c    243
dtype: int64

Новое поведение

In [52]: np.power(s1, s2)
Out[52]: 
a     1.0
b    32.0
c    81.0
d     NaN
Length: 4, dtype: float64

Это соответствует поведению других бинарных операций в pandas, таких как Series.add(). Чтобы сохранить предыдущее поведение, преобразуйте другой Series в массив перед применением ufunc.

In [53]: np.power(s1, s2.array)
Out[53]: 
a      1
b     16
c    243
Length: 3, dtype: int64

Categorical.argsort теперь помещает пропущенные значения в конец#

Categorical.argsort() теперь помещает пропущенные значения в конец массива, делая его согласованным с NumPy и остальной частью pandas (GH 21801).

In [54]: cat = pd.Categorical(['b', None, 'a'], categories=['a', 'b'], ordered=True)

Предыдущее поведение

In [2]: cat = pd.Categorical(['b', None, 'a'], categories=['a', 'b'], ordered=True)

In [3]: cat.argsort()
Out[3]: array([1, 2, 0])

In [4]: cat[cat.argsort()]
Out[4]:
[NaN, a, b]
categories (2, object): [a < b]

Новое поведение

In [55]: cat.argsort()
Out[55]: array([2, 0, 1])

In [56]: cat[cat.argsort()]
Out[56]: 
['a', 'b', NaN]
Categories (2, object): ['a' < 'b']

Порядок столбцов сохраняется при передаче списка словарей в DataFrame#

Начиная с Python 3.7 порядок ключей в dict является гарантировано. На практике это верно с Python 3.6. DataFrame конструктор теперь обрабатывает список словарей так же, как он обрабатывает список OrderedDict, т.е. сохраняя порядок словарей. Это изменение применяется только когда pandas работает на Python>=3.6 (GH 27309).

In [57]: data = [
   ....:     {'name': 'Joe', 'state': 'NY', 'age': 18},
   ....:     {'name': 'Jane', 'state': 'KY', 'age': 19, 'hobby': 'Minecraft'},
   ....:     {'name': 'Jean', 'state': 'OK', 'age': 20, 'finances': 'good'}
   ....: ]
   ....: 

Предыдущее поведение:

Ранее столбцы сортировались лексикографически,

In [1]: pd.DataFrame(data)
Out[1]:
   age finances      hobby  name state
0   18      NaN        NaN   Joe    NY
1   19      NaN  Minecraft  Jane    KY
2   20     good        NaN  Jean    OK

Новое поведение:

Порядок столбцов теперь соответствует порядку вставки ключей в dict, учитывая все записи сверху вниз. В результате порядок столбцов в полученном DataFrame изменился по сравнению с предыдущими версиями pandas.

In [58]: pd.DataFrame(data)
Out[58]: 
   name state  age      hobby finances
0   Joe    NY   18        NaN      NaN
1  Jane    KY   19  Minecraft      NaN
2  Jean    OK   20        NaN     good

[3 rows x 5 columns]

Повышенные минимальные версии для зависимостей#

Из-за прекращения поддержки Python 2.7, ряд опциональных зависимостей обновил минимальные версии (GH 25725, GH 24942, GH 25752). Независимо, некоторые минимальные поддерживаемые версии зависимостей были обновлены (GH 23519, GH 25554). Если установлено, теперь требуется:

Пакет

Минимальная версия

Обязательно

numpy

1.13.3

X

pytz

2015.4

X

python-dateutil

2.6.1

X

bottleneck

1.2.1

numexpr

2.6.2

pytest (разработка)

4.0.2

Для дополнительные библиотеки общая рекомендация — использовать последнюю версию. Следующая таблица перечисляет минимальную версию для каждой библиотеки, которая в настоящее время тестируется в ходе разработки pandas. Опциональные библиотеки ниже минимальной тестируемой версии могут всё ещё работать, но не считаются поддерживаемыми.

Пакет

Минимальная версия

beautifulsoup4

4.6.0

fastparquet

0.2.1

gcsfs

0.2.2

lxml

3.8.0

matplotlib

2.2.2

openpyxl

2.4.8

pyarrow

0.9.0

pymysql

0.7.1

pytables

3.4.2

scipy

0.19.0

sqlalchemy

1.1.4

xarray

0.8.2

xlrd

1.1.0

xlsxwriter

0.9.8

xlwt

1.2.0

См. Зависимости и Необязательные зависимости подробнее.

Другие изменения API#

  • DatetimeTZDtype теперь будет стандартизировать часовые пояса pytz к общему экземпляру часового пояса (GH 24713)

  • Timestamp и Timedelta скаляры теперь реализуют to_numpy() метод как псевдонимы для Timestamp.to_datetime64() и Timedelta.to_timedelta64(), соответственно. (GH 24653)

  • Timestamp.strptime() теперь вызовет NotImplementedError (GH 25016)

  • Сравнение Timestamp с неподдерживаемыми объектами теперь возвращает NotImplemented вместо вызова исключения TypeError. Это означает, что неподдерживаемые расширенные сравнения делегируются другому объекту и теперь соответствуют поведению Python 3 для datetime объекты (GH 24011)

  • Ошибка в DatetimeIndex.snap() который не сохранял name входных данных Index (GH 25575)

  • The arg аргумент в DataFrameGroupBy.agg() был переименован в func (GH 26089)

  • The arg аргумент в Window.aggregate() был переименован в func (GH 26372)

  • У большинства классов pandas был __bytes__ метод, который использовался для получения представления объекта в стиле Python2 в виде байтовой строки. Этот метод был удален в рамках отказа от Python2 (GH 26447)

  • The .str-accessor был отключен для 1-уровневого MultiIndex, используйте MultiIndex.to_flat_index() при необходимости (GH 23679)

  • Удалена поддержка пакета gtk для буферов обмена (GH 26563)

  • Использование неподдерживаемой версии Beautiful Soup 4 теперь вызывает ImportError вместо ValueError (GH 27063)

  • Series.to_excel() и DataFrame.to_excel() теперь вызовет ValueError при сохранении данных с учётом часового пояса. (GH 27008, GH 7056)

  • ExtensionArray.argsort() помещает значения NA в конец отсортированного массива. (GH 21801)

  • DataFrame.to_hdf() и Series.to_hdf() теперь вызовет NotImplementedError при сохранении MultiIndex с типами данных расширений для fixed формат. (GH 7775)

  • Передача дублирующихся names в read_csv() теперь вызовет ValueError (GH 17346)

Устаревшие функции#

Разреженные подклассы#

The SparseSeries и SparseDataFrame подклассы устарели. Их функциональность лучше предоставляется через Series или DataFrame со значениями sparse.

Предыдущий способ

df = pd.SparseDataFrame({"A": [0, 0, 1, 2]})
df.dtypes

Новый способ

In [59]: df = pd.DataFrame({"A": pd.arrays.SparseArray([0, 0, 1, 2])})

In [60]: df.dtypes
Out[60]: 
A    Sparse[int64, 0]
Length: 1, dtype: object

Использование памяти двумя подходами идентично (GH 19239).

формат msgpack#

Формат msgpack устарел с версии 0.25 и будет удален в будущей версии. Рекомендуется использовать pyarrow для передачи объектов pandas по сети. (GH 27084)

Другие устаревшие функции#

  • Устаревший .ix[] индексатор теперь вызывает более заметное FutureWarning вместо DeprecationWarning (GH 26438).

  • Устарел units=M (месяцы) и units=Y (год) параметры для units of pandas.to_timedelta(), pandas.Timedelta() и pandas.TimedeltaIndex() (GH 16344)

  • pandas.concat() устарел join_axes-keyword. Вместо этого используйте DataFrame.reindex() или DataFrame.reindex_like() на результате или на входных данных (GH 21951)

  • The SparseArray.values атрибут устарел. Вы можете использовать np.asarray(...) или SparseArray.to_dense() метод вместо (GH 26421).

  • Функции pandas.to_datetime() и pandas.to_timedelta() устарели box ключевое слово. Вместо этого используйте to_numpy() или Timestamp.to_datetime64() или Timedelta.to_timedelta64(). (GH 24416)

  • The DataFrame.compound() и Series.compound() методы устарели и будут удалены в будущей версии (GH 26405).

  • Внутренние атрибуты _start, _stop и _step атрибуты RangeIndex были устаревшими. Используйте публичные атрибуты start, stop и step вместо (GH 26581).

  • The Series.ftype(), Series.ftypes() и DataFrame.ftypes() методы устарели и будут удалены в будущей версии. Вместо этого используйте Series.dtype() и DataFrame.dtypes() (GH 26705).

  • The Series.get_values(), DataFrame.get_values(), Index.get_values(), SparseArray.get_values() и Categorical.get_values() методы устарели. Один из np.asarray(..) или to_numpy() может использоваться вместо (GH 19617).

  • Метод 'outer' для NumPy ufuncs, например. np.subtract.outer был объявлен устаревшим в Series объектов. Преобразуйте входные данные в массив с помощью Series.array первый (GH 27186)

  • Timedelta.resolution() устарел и заменен на Timedelta.resolution_string(). В будущей версии, Timedelta.resolution() будет изменено для поведения, аналогичного стандартной библиотеке datetime.timedelta.resolution (GH 21344)

  • read_table() был восстановлен из устаревших. (GH 25220)

  • Index.dtype_str устарело. (GH 18262)

  • Series.imag и Series.real устарели. (GH 18262)

  • Series.put() устарело. (GH 18262)

  • Index.item() и Series.item() устарело. (GH 18262)

  • Значение по умолчанию ordered=None в CategoricalDtype был объявлен устаревшим в пользу ordered=False. При преобразовании между категориальными типами ordered=True должен быть явно передан, чтобы быть сохраненным. (GH 26336)

  • Index.contains() устарел. Используйте key in index (__contains__) вместо (GH 17753).

  • DataFrame.get_dtype_counts() устарело. (GH 18262)

  • Categorical.ravel() вернёт Categorical вместо np.ndarray (GH 27199)

Удаление устаревших функций/изменений предыдущих версий#

  • Удалено Panel (GH 25047, GH 25191, GH 25231)

  • Удалена ранее устаревшая sheetname ключевое слово в read_excel() (GH 16442, GH 20938)

  • Удалена ранее устаревшая TimeGrouper (GH 16942)

  • Удалена ранее устаревшая parse_cols ключевое слово в read_excel() (GH 16488)

  • Удалена ранее устаревшая pd.options.html.border (GH 16970)

  • Удалена ранее устаревшая convert_objects (GH 11221)

  • Удалена ранее устаревшая select метод DataFrame и Series (GH 17633)

  • Удалено ранее устаревшее поведение Series рассматривается как список в rename_categories() (GH 17982)

  • Удалена ранее устаревшая DataFrame.reindex_axis и Series.reindex_axis (GH 17842)

  • Удалено ранее устаревшее поведение изменения меток столбцов или индекса с помощью Series.rename_axis() или DataFrame.rename_axis() (GH 17842)

  • Удалена ранее устаревшая tupleize_cols именованный аргумент в read_html(), read_csv(), и DataFrame.to_csv() (GH 17877, GH 17820)

  • Удалена ранее устаревшая DataFrame.from.csv и Series.from_csv (GH 17812)

  • Удалена ранее устаревшая raise_on_error именованный аргумент в DataFrame.where() и DataFrame.mask() (GH 17744)

  • Удалена ранее устаревшая ordered и categories именованные аргументы в astype (GH 17742)

  • Удалена ранее устаревшая cdate_range (GH 17691)

  • Удалена ранее устаревшая True опция для dropna именованный аргумент в SeriesGroupBy.nth() (GH 17493)

  • Удалена ранее устаревшая convert именованный аргумент в Series.take() и DataFrame.take() (GH 17352)

  • Удалено ранее устаревшее поведение арифметических операций с datetime.date объекты (GH 21152)

Улучшения производительности#

  • Значительное ускорение в SparseArray инициализации, которая приносит пользу большинству операций, исправляя регрессию производительности, введённую в v0.20.0 (GH 24985)

  • DataFrame.to_stata() теперь работает быстрее при выводе данных с любыми строковыми или не-нативными колонками с порядком байт (GH 25045)

  • Улучшена производительность Series.searchsorted(). Ускорение особенно заметно, когда тип данных int8/int16/int32 и искомый ключ находится в пределах целочисленных границ для этого типа (GH 22034)

  • Улучшена производительность GroupBy.quantile() (GH 20405)

  • Улучшена производительность срезов и других выбранных операций над RangeIndex (GH 26565, GH 26617, GH 26722)

  • RangeIndex теперь выполняет стандартный поиск без создания фактической хэш-таблицы, экономя память (GH 16685)

  • Улучшена производительность read_csv() за счёт более быстрой токенизации и более быстрого разбора маленьких чисел с плавающей точкой (GH 25784)

  • Улучшена производительность read_csv() за счет более быстрого разбора значений N/A и булевых значений (GH 25804)

  • Улучшена производительность IntervalIndex.is_monotonic, IntervalIndex.is_monotonic_increasing и IntervalIndex.is_monotonic_decreasing путем удаления преобразования в MultiIndex (GH 24813)

  • Улучшена производительность DataFrame.to_csv() при записи типов данных datetime (GH 25708)

  • Улучшена производительность read_csv() значительно более быстрым парсингом MM/YYYY и DD/MM/YYYY форматы даты и времени (GH 25922)

  • Улучшена производительность nanops для типов данных, которые не могут хранить NaN. Ускорение особенно заметно для Series.all() и Series.any() (GH 25070)

  • Улучшена производительность Series.map() для словарных мапперов на категориальных сериях путём маппинга категорий вместо маппинга всех значений (GH 23785)

  • Улучшена производительность IntervalIndex.intersection() (GH 24813)

  • Улучшена производительность read_csv() за счёт более быстрого объединения столбцов дат без дополнительного преобразования в строку для целого/вещественного нуля и вещественного NaN; за счёт более быстрой проверки строки на возможность быть датой (GH 25754)

  • Улучшена производительность IntervalIndex.is_unique путем удаления преобразования в MultiIndex (GH 24813)

  • Восстановлена производительность DatetimeIndex.__iter__() путем повторного включения специализированного пути кода (GH 26702)

  • Улучшена производительность при построении MultiIndex с хотя бы одним CategoricalIndex уровень (GH 22044)

  • Улучшена производительность за счёт устранения необходимости сборки мусора при проверке SettingWithCopyWarning (GH 27031)

  • Для to_datetime() изменено значение по умолчанию параметра cache на True (GH 26043)

  • Улучшена производительность DatetimeIndex и PeriodIndex срез при задании неуникальных, монотонных данных (GH 27136).

  • Улучшена производительность pd.read_json() для данных, ориентированных на индекс. (GH 26773)

  • Улучшена производительность MultiIndex.shape() (GH 27384).

Исправления ошибок#

Категориальный#

Datetimelike#

  • Ошибка в to_datetime() что вызывало (неправильную) ValueError при вызове с датой далеко в будущем и format аргумент указан вместо вызова исключения OutOfBoundsDatetime (GH 23830)

  • Ошибка в to_datetime() что вызвало бы InvalidIndexError: Reindexing only valid with uniquely valued Index objects при вызове с cache=True, с arg включая как минимум два различных элемента из множества {None, numpy.nan, pandas.NaT} (GH 22305)

  • Ошибка в DataFrame и Series где данные с учётом часового пояса с dtype='datetime64[ns] не был преобразован в наивный (GH 25843)

  • Улучшено Timestamp проверка типа в различных функциях работы с датой и временем для предотвращения исключений при использовании подкласса datetime (GH 25851)

  • Ошибка в Series и DataFrame repr где np.datetime64('NaT') и np.timedelta64('NaT') с dtype=object будет представлен как NaN (GH 25445)

  • Ошибка в to_datetime() который не заменяет недопустимый аргумент на NaT когда error установлен в coerce (GH 26122)

  • Ошибка при добавлении DateOffset с ненулевым месяцем в DatetimeIndex вызовет ValueError (GH 26258)

  • Ошибка в to_datetime() который вызывает необработанное OverflowError при вызове со смесью недопустимых дат и NaN значения с format='%Y%m%d' и error='coerce' (GH 25512)

  • Ошибка в isin() для индексов типа datetime; DatetimeIndex, TimedeltaIndex и PeriodIndex где levels параметр игнорировался. (GH 26675)

  • Ошибка в to_datetime() который вызывает TypeError для format='%Y%m%d' при вызове для недопустимых целочисленных дат с длиной >= 6 цифр с errors='ignore'

  • Ошибка при сравнении PeriodIndex против нульмерного массива numpy (GH 26689)

  • Ошибка при построении Series или DataFrame из numpy datetime64 массив с не-ns единицей измерения и выходящими за границы временными метками, генерирующий некорректные данные, что теперь правильно вызывает исключение OutOfBoundsDatetime ошибка (GH 26206).

  • Ошибка в date_range() с ненужными OverflowError вызывается для очень больших или очень маленьких дат (GH 26651)

  • Ошибка, при которой добавление Timestamp в np.timedelta64 объект вызывал исключение вместо возврата Timestamp (GH 24775)

  • Ошибка, при сравнении нульмерного массива numpy, содержащего np.datetime64 объект в Timestamp некорректно вызывал TypeError (GH 26916)

  • Ошибка в to_datetime() что вызвало бы ValueError: Tz-aware datetime.datetime cannot be converted to datetime64 unless utc=True при вызове с cache=True, с arg включая строки даты и времени с различным смещением (GH 26097)

Timedelta#

  • Ошибка в TimedeltaIndex.intersection() где для немонотонных индексов в некоторых случаях пустой Index возвращалось, когда на самом деле существовало пересечение (GH 25913)

  • Ошибка при сравнениях между Timedelta и NaT вызов TypeError (GH 26039)

  • Ошибка при добавлении или вычитании BusinessHour в Timestamp с результирующим временем, попадающим в следующий или предыдущий день соответственно (GH 26381)

  • Ошибка при сравнении TimedeltaIndex против нульмерного массива numpy (GH 26689)

Часовые пояса#

  • Ошибка в DatetimeIndex.to_frame() где данные с учетом часового пояса преобразовывались бы в данные без учета часового пояса (GH 25809)

  • Ошибка в to_datetime() с utc=True и строки даты-времени, которые применяли ранее разобранные смещения UTC к последующим аргументам (GH 24992)

  • Ошибка в Timestamp.tz_localize() и Timestamp.tz_convert() не распространяется freq (GH 25241)

  • Ошибка в Series.at() где установка Timestamp с часовым поясом вызывает TypeError (GH 25506)

  • Ошибка в DataFrame.update() при обновлении с данными, учитывающими часовой пояс, возвращало данные без учёта часового пояса (GH 25807)

  • Ошибка в to_datetime() где неинформативный RuntimeError было вызвано при передаче наивного Timestamp с строками даты-времени со смещенными смещениями UTC (GH 25978)

  • Ошибка в to_datetime() с unit='ns' удалял бы информацию о часовом поясе из разобранного аргумента (GH 26168)

  • Ошибка в DataFrame.join() при объединении индекса с учетом часового пояса со столбцом с учетом часового пояса может получиться столбец NaN (GH 26335)

  • Ошибка в date_range() где неоднозначные или несуществующие начальные или конечные времена не обрабатывались ambiguous или nonexistent ключевые слова соответственно (GH 27088)

  • Ошибка в DatetimeIndex.union() при объединении timezone aware и timezone unaware DatetimeIndex (GH 21671)

  • Ошибка при применении функции редукции numpy (например, numpy.minimum()) в осведомленный о часовом поясе Series (GH 15552)

Числовой#

  • Ошибка в to_numeric() в котором большие отрицательные числа обрабатывались неправильно (GH 24910)

  • Ошибка в to_numeric() в котором числа приводились к типу float, хотя errors не был coerce (GH 24910)

  • Ошибка в to_numeric() в котором недопустимые значения для errors были разрешены (GH 26466)

  • Ошибка в format в котором числа с плавающей точкой комплексного типа не форматировались с правильной точностью отображения и обрезкой (GH 25514)

  • Ошибка в сообщениях об ошибках в DataFrame.corr() и Series.corr(). Добавлена возможность использования вызываемого объекта. (GH 25729)

  • Ошибка в Series.divmod() и Series.rdivmod() что вызывало (неправильную) ValueError вместо возврата пары Series объекты в качестве результата (GH 25557)

  • Вызывает полезное исключение, когда нечисловой индекс передается в interpolate() с методами, требующими числового индекса. (GH 21662)

  • Ошибка в eval() при сравнении чисел с плавающей точкой со скалярными операторами, например: x < -0.1 (GH 25928)

  • Исправлена ошибка, при которой приведение полностью булевого массива к целочисленному расширенному массиву завершалось неудачей (GH 25211)

  • Ошибка в divmod с Series объект, содержащий нули, неправильно вызывающий AttributeError (GH 26987)

  • Несогласованность в Series целочисленное деление (//) и divmod заполнение положительных//нулевых с NaN вместо Inf (GH 27321)

Преобразование#

  • Ошибка в DataFrame.astype() при передаче словаря столбцов и типов errors параметр игнорировался. (GH 25905)

Строки#

  • Ошибка в __name__ атрибут нескольких методов Series.str, которые были установлены некорректно (GH 23551)

  • Улучшено сообщение об ошибке при передаче Series неправильного типа данных для Series.str.cat() (GH 22722)

Interval#

Индексирование#

  • Улучшенное сообщение об исключении при вызове DataFrame.iloc() со списком нечисловых объектов (GH 25753).

  • Улучшенное сообщение об исключении при вызове .iloc или .loc с булевым индексатором другой длины (GH 26658).

  • Ошибка в KeyError сообщение об исключении при индексации MultiIndex с несуществующим ключом, не отображающим исходный ключ (GH 27250).

  • Ошибка в .iloc и .loc с булевым индексатором, не вызывающим IndexError когда передано слишком мало элементов (GH 26658).

  • Ошибка в DataFrame.loc() и Series.loc() где KeyError не было вызвано для MultiIndex когда ключ был меньше или равен количеству уровней в MultiIndex (GH 14885).

  • Ошибка, при которой DataFrame.append() выдавало ошибочное предупреждение, указывающее, что KeyError будет выброшено в будущем, когда добавляемые данные содержат новые столбцы (GH 22252).

  • Ошибка, при которой DataFrame.to_csv() вызывал ошибку сегментации для переиндексированного фрейма данных, когда индексы были одноуровневыми MultiIndex (GH 26303).

  • Исправлена ошибка, при которой присваивание arrays.PandasArray в DataFrame вызовет ошибку (GH 26390)

  • Разрешить ключевые аргументы для вызываемой локальной ссылки, используемой в DataFrame.query() строка (GH 26426)

  • Исправлена KeyError при индексации MultiIndex уровень со списком, содержащим ровно одну метку, которая отсутствует (GH 27148)

  • Ошибка, которая вызывала AttributeError о частичном совпадении Timestamp в MultiIndex (GH 26944)

  • Ошибка в Categorical и CategoricalIndex с Interval значения при использовании in оператор (__contains) с объектами, которые несопоставимы со значениями в Interval (GH 23705)

  • Ошибка в DataFrame.loc() и DataFrame.iloc() на DataFrame с одним столбцом datetime64[ns] с учетом часового пояса, ошибочно возвращающим скаляр вместо Series (GH 27110)

  • Ошибка в CategoricalIndex и Categorical некорректное возбуждение ValueError вместо TypeError когда список передается с использованием in оператор (__contains__) (GH 21729)

  • Ошибка при установке нового значения в Series с Timedelta объект некорректно преобразует значение в целое число (GH 22717)

  • Ошибка в Series установка нового ключа (__setitem__) с datetime с учетом часового пояса, некорректно вызывающий ValueError (GH 12862)

  • Ошибка в DataFrame.iloc() при индексировании с помощью доступного только для чтения индексатора (GH 17192)

  • Ошибка в Series установка существующего ключа-кортежа (__setitem__) с datetime значениями с часовым поясом ошибочно вызывает TypeError (GH 20441)

Отсутствует#

  • Исправлено вводящее в заблуждение сообщение об исключении в Series.interpolate() если аргумент order требуется, но опущен (GH 10633, GH 24014).

  • Исправлен тип класса, отображаемый в сообщении об исключении в DataFrame.dropna() если недействителен axis переданный параметр (GH 25555)

  • A ValueError теперь будет вызываться DataFrame.fillna() когда limit не является положительным целым числом (GH 27042)

MultiIndex#

  • Ошибка, при которой вызывается некорректное исключение Timedelta при проверке принадлежности MultiIndex (GH 24570)

Ввод-вывод#

  • Ошибка в DataFrame.to_html() где значения были усечены с использованием параметров отображения вместо вывода полного содержимого (GH 17004)

  • Исправлена ошибка с отсутствующим текстом при использовании to_clipboard() при копировании символов utf-16 в Python 3 на Windows (GH 25040)

  • Ошибка в read_json() для orient='table' когда он пытается определить типы данных по умолчанию, что неприменимо, так как типы данных уже определены в схеме JSON (GH 21345)

  • Ошибка в read_json() для orient='table' и индекс с плавающей точкой, так как он выводит тип данных индекса по умолчанию, что неприменимо, потому что тип данных индекса уже определен в схеме JSON (GH 25433)

  • Ошибка в read_json() для orient='table' и строку имен столбцов float, так как это преобразует тип имени столбца в Timestamp, что неприменимо, поскольку имена столбцов уже определены в схеме JSON (GH 25435)

  • Ошибка в json_normalize() для errors='ignore' где пропущенные значения во входных данных были заполнены в результате DataFrame со строкой "nan" вместо numpy.nan (GH 25468)

  • DataFrame.to_html() теперь вызывает TypeError при использовании недопустимого типа для classes параметр вместо AssertionError (GH 25608)

  • Ошибка в DataFrame.to_string() и DataFrame.to_latex() что привело бы к некорректному выводу, когда header используется ключевое слово (GH 16718)

  • Ошибка в read_csv() неправильная интерпретация имен файлов, закодированных в UTF8, в Windows на Python 3.6+ (GH 15086)

  • Улучшена производительность в pandas.read_stata() и pandas.io.stata.StataReader при преобразовании столбцов с пропущенными значениями (GH 25772)

  • Ошибка в DataFrame.to_html() где номера заголовков игнорировали параметры отображения при округлении (GH 17280)

  • Ошибка в read_hdf() где чтение таблицы из файла HDF5, записанного напрямую с помощью PyTables, завершается ошибкой ValueError при использовании частичного выбора через start или stop аргументы (GH 11188)

  • Ошибка в read_hdf() неправильное закрытие хранилища после KeyError возникает (GH 25766)

  • Улучшено объяснение ошибки при повторяющихся метках значений в файлах Stata dta и предложены обходные пути (GH 25772)

  • Улучшено pandas.read_stata() и pandas.io.stata.StataReader для чтения неправильно отформатированных файлов формата 118, сохраненных Stata (GH 25960)

  • Улучшен col_space параметр в DataFrame.to_html() принимать строку, чтобы значения длины CSS могли быть установлены корректно (GH 25941)

  • Исправлена ошибка при загрузке объектов из S3, содержащих # символы в URL (GH 25945)

  • Добавляет use_bqstorage_api параметр для read_gbq() для ускорения загрузки больших фреймов данных. Эта функция требует версии 0.10.0 pandas-gbq библиотека, а также google-cloud-bigquery-storage и fastavro библиотек. (GH 26104)

  • Исправлена утечка памяти в DataFrame.to_json() при работе с числовыми данными (GH 24889)

  • Ошибка в read_json() где строки дат с Z не были преобразованы в часовой пояс UTC (GH 26168)

  • Добавлен cache_dates=True параметр для read_csv(), что позволяет кэшировать уникальные даты при их разборе (GH 25990)

  • DataFrame.to_excel() теперь вызывает ValueError когда размеры вызывающего объекта превышают ограничения Excel (GH 26051)

  • Исправлена ошибка в pandas.read_csv() где BOM приводил к некорректному разбору при использовании engine='python' (GH 26545)

  • read_excel() теперь вызывает ValueError когда входные данные имеют тип pandas.io.excel.ExcelFile и engine параметр передаётся, так как pandas.io.excel.ExcelFile имеет определенный движок (GH 26566)

  • Ошибка при выборе из HDFStore с where='' указано (GH 26610).

  • Исправлена ошибка в DataFrame.to_excel() где пользовательские объекты (т.е. PeriodIndex) внутри объединенных ячеек не преобразовывались в типы, безопасные для записи в Excel (GH 27006)

  • Ошибка в read_hdf() где чтение данных с учетом часового пояса DatetimeIndex вызовет TypeError (GH 11926)

  • Ошибка в to_msgpack() и read_msgpack() что вызвало бы ValueError а не FileNotFoundError для недопустимого пути (GH 27160)

  • Исправлена ошибка в DataFrame.to_parquet() что вызвало бы ValueError когда фрейм данных не имел столбцов (GH 27339)

  • Разрешить парсинг PeriodDtype столбцов при использовании read_csv() (GH 26934)

Построение графиков#

  • Исправлена ошибка, где api.extensions.ExtensionArray не могли использоваться в построении графиков matplotlib (GH 25587)

  • Ошибка в сообщении об ошибке в DataFrame.plot(). Улучшено сообщение об ошибке, если в DataFrame.plot() (GH 25481)

  • Ошибка в неправильных позициях меток делений при построении индекса, который не является числовым/не является датой и временем (GH 7612, GH 15912, GH 22334)

  • Исправлена ошибка, вызывающая построение графиков PeriodIndex временных рядов ошибку, если частота кратна коду правила частоты (GH 14763)

  • Исправлена ошибка при построении графика DatetimeIndex с datetime.timezone.utc timezone (GH 17173)

GroupBy/resample/rolling#

  • Ошибка в Resampler.agg() с индексом, учитывающим часовой пояс, где OverflowError вызывало ошибку при передаче списка функций (GH 22660)

  • Ошибка в DataFrameGroupBy.nunique() в котором были потеряны имена уровней столбцов (GH 23222)

  • Ошибка в GroupBy.agg() при применении агрегирующей функции к данным с учетом часового пояса (GH 23683)

  • Ошибка в GroupBy.first() и GroupBy.last() где информация о часовом поясе будет удалена (GH 21603)

  • Ошибка в GroupBy.size() при группировке только значений NA (GH 23050)

  • Ошибка в Series.groupby() где observed kwarg ранее игнорировался (GH 24880)

  • Ошибка в Series.groupby() где использование groupby с MultiIndex Series со списком меток, равным длине серии, вызывал некорректную группировку (GH 25704)

  • Обеспечено, что порядок вывода в groupby функции агрегации согласованы во всех версиях Python (GH 25692)

  • Обеспечено, что порядок групп результата корректен при группировке по упорядоченному Categorical и указание observed=True (GH 25871, GH 25167)

  • Ошибка в Rolling.min() и Rolling.max() который вызывал утечку памяти (GH 25893)

  • Ошибка в Rolling.count() и .Expanding.count ранее игнорировал axis ключевое слово (GH 13503)

  • Ошибка в GroupBy.idxmax() и GroupBy.idxmin() с datetime столбцом возвращал неправильный тип данных (GH 25444, GH 15306)

  • Ошибка в GroupBy.cumsum(), GroupBy.cumprod(), GroupBy.cummin() и GroupBy.cummax() с категориальной колонкой, имеющей отсутствующие категории, возвращал неверный результат или вызывал segfault (GH 16771)

  • Ошибка в GroupBy.nth() где NA-значения в группировке возвращали бы некорректные результаты (GH 26011)

  • Ошибка в SeriesGroupBy.transform() где преобразование пустой группы вызвало бы ValueError (GH 26208)

  • Ошибка в DataFrame.groupby() где передача Grouper вернёт некорректные группы при использовании .groups аксессор (GH 26326)

  • Ошибка в GroupBy.agg() где возвращаются некорректные результаты для столбцов uint64. (GH 26310)

  • Ошибка в Rolling.median() и Rolling.quantile() где MemoryError возникает с пустым окном (GH 26005)

  • Ошибка в Rolling.median() и Rolling.quantile() где возвращаются некорректные результаты с closed='left' и closed='neither' (GH 26005)

  • Улучшено Rolling, Window и ExponentialMovingWindow функции для исключения нежелательных столбцов из результатов вместо вызова ошибок и вызывают DataError только если все столбцы являются несущественными (GH 12537)

  • Ошибка в Rolling.max() и Rolling.min() где возвращаются некорректные результаты с пустым переменным окном (GH 26005)

  • Выдать полезное исключение, когда неподдерживаемая взвешенная оконная функция используется в качестве аргумента Window.aggregate() (GH 26597)

Изменение формы#

  • Ошибка в pandas.merge() добавляет строку None, если None назначается в суффиксах вместо сохранения имени столбца как есть (GH 24782).

  • Ошибка в merge() при слиянии по имени индекса иногда приводило к некорректно пронумерованному индексу (пропущенные значения индекса теперь присваиваются NA) (GH 24212, GH 25009)

  • to_records() теперь принимает dtypes в свой column_dtypes параметр (GH 24895)

  • Ошибка в concat() где порядок OrderedDictdict в Python 3.6+) не соблюдается, когда передается как objs аргумент (GH 21510)

  • Ошибка в pivot_table() где столбцы с NaN значения удаляются, даже если dropna аргумент является False, когда aggfunc аргумент содержит list (GH 22159)

  • Ошибка в concat() где результирующий freq из двух DatetimeIndex с тем же freq будут удалены (GH 3232).

  • Ошибка в merge() где слияние с эквивалентными категориальными типами данных вызывало ошибку (GH 22501)

  • ошибка в DataFrame создание экземпляра со словарем итераторов или генераторов (например, pd.DataFrame({'A': reversed(range(3))})) вызывал ошибку (GH 26349).

  • Ошибка в DataFrame создание экземпляра с range (например, pd.DataFrame(range(3))) вызывал ошибку (GH 26342).

  • Ошибка в DataFrame конструкторе при передаче непустых кортежей, что вызывало ошибку сегментации (GH 25691)

  • Ошибка в Series.apply() не удалось, когда серия учитывает часовой пояс DatetimeIndex (GH 25959)

  • Ошибка в pandas.cut() где большие интервалы могли некорректно вызывать ошибку из-за переполнения целого числа (GH 26045)

  • Ошибка в DataFrame.sort_index() где возникает ошибка при работе с мультииндексированным DataFrame сортируется по всем уровням с начальным уровнем, отсортированным последним (GH 26053)

  • Ошибка в Series.nlargest() обрабатывает True как меньший, чем False (GH 26154)

  • Ошибка в DataFrame.pivot_table() с IntervalIndex как индекс сводной таблицы вызывал бы TypeError (GH 25814)

  • Ошибка, при которой DataFrame.from_dict() игнорировал порядок OrderedDict когда orient='index' (GH 8425).

  • Ошибка в DataFrame.transpose() где транспонирование DataFrame со столбцом datetime с учётом часового пояса некорректно вызывало ошибку ValueError (GH 26825)

  • Ошибка в pivot_table() при сводной таблице столбца с учетом часового пояса как values удалит информацию о часовом поясе (GH 14948)

  • Ошибка в merge_asof() при указании нескольких by столбцы, где один является datetime64[ns, tz] тип данных (GH 26649)

Разреженный#

  • Значительное ускорение в SparseArray инициализации, которая приносит пользу большинству операций, исправляя регрессию производительности, введённую в v0.20.0 (GH 24985)

  • Ошибка в SparseFrame конструктор, где передача None как данные вызвали бы default_fill_value игнорируется (GH 16807)

  • Ошибка в SparseDataFrame при добавлении столбца, в котором длина значений не соответствует длине индекса, AssertionError вызывается вместо вызова ValueError (GH 25484)

  • Ввести более понятное сообщение об ошибке в Series.sparse.from_coo() так что возвращает TypeError для входных данных, которые не являются матрицами coo (GH 26554)

  • Ошибка в numpy.modf() на SparseArray. Теперь кортеж из SparseArray возвращается (GH 26946).

Изменения сборки#

  • Исправлена ошибка установки с PyPy на macOS (GH 26536)

ExtensionArray#

  • Ошибка в factorize() при передаче ExtensionArray с пользовательским na_sentinel (GH 25696).

  • Series.count() неправильно подсчитывает значения NA в ExtensionArrays (GH 26835)

  • Добавлен Series.__array_ufunc__ для лучшей обработки NumPy ufuncs, применённых к Series, поддерживаемым массивами расширений (GH 23293).

  • Ключевой аргумент deep был удален из ExtensionArray.copy() (GH 27083)

Другие#

  • Удалены неиспользуемые C-функции из вендорной реализации UltraJSON (GH 26198)

  • Разрешить Index и RangeIndex для передачи в numpy min и max функции (GH 26125)

  • Используйте фактическое имя класса в repr пустых объектов Series подкласс (GH 27001).

  • Ошибка в DataFrame где передача массива объектов с учетом часового пояса datetime объекты некорректно вызывали ValueError (GH 13287)

Участники#

Всего 231 человек внесли патчи в этот релиз. Люди со знаком «+» рядом с именами внесли патч впервые.

  • 1_x7 +

  • Abdullah İhsan Seçer +

  • Adam Bull +

  • Adam Hooper

  • Albert Villanova del Moral

  • Alex Watt +

  • AlexTereshenkov +

  • Alexander Buchkovsky

  • Александр Хендорф +

  • Александр Нордин +

  • Alexander Ponomaroff

  • Александр Батисс +

  • Александр Декан +

  • Allen Downey +

  • Alyssa Fu Ward +

  • Эндрю Гаспари +

  • Andrew Wood +

  • Antoine Viscardi +

  • Antonio Gutierrez +

  • Arno Veenstra +

  • ArtinSarraf

  • Batalex +

  • Baurzhan Muftakhidinov

  • Benjamin Rowell

  • Бхарат Рагхунатан +

  • Бхавани Рави +

  • Big Head +

  • Brett Randall +

  • Bryan Cutler +

  • C John Klehm +

  • Caleb Braun +

  • Cecilia +

  • Chris Bertinato +

  • Chris Stadler +

  • Christian Haege +

  • Christian Hudon

  • Кристофер Уилан

  • Chuanzhu Xu +

  • Clemens Brunner

  • Damian Kula +

  • Daniel Hrisca +

  • Daniel Luis Costa +

  • Daniel Saxton

  • DanielFEvans +

  • David Liu +

  • Дипьяман Датта +

  • Denis Belavin +

  • Devin Petersohn +

  • Diane Trout +

  • EdAbati +

  • Enrico Rotundo +

  • EternalLearner42 +

  • Evan +

  • Evan Livelo +

  • Fabian Rost +

  • Flavien Lambert +

  • Florian Rathgeber +

  • Frank Hoang +

  • Gaibo Zhang +

  • Gioia Ballin

  • Giuseppe Romagnuolo +

  • Гордон Блэкэддер +

  • Gregory Rome +

  • Guillaume Gay

  • HHest +

  • Hielke Walinga +

  • Как Си Вэй +

  • Hubert

  • Huize Wang +

  • Hyukjin Kwon +

  • Ian Dunn +

  • Inevitable-Marzipan +

  • Ирв Ластиг

  • JElfner +

  • Jacob Bundgaard +

  • Джеймс Кобон-Керр +

  • Ян-Филипп Герке +

  • Jarrod Millman +

  • Jayanth Katuri +

  • Jeff Reback

  • Jeremy Schendel

  • Jiang Yue +

  • Joel Ostblom

  • Johan von Forstner +

  • Johnny Chiu +

  • Jonas +

  • Jonathon Vandezande +

  • Jop Vermeer +

  • Joris Van den Bossche

  • Josh

  • GH 15670

  • Джастин Чжэн

  • Kaiqi Dong

  • Кейн +

  • Kapil Patel +

  • Kara de la Marck +

  • Кэтрин Сурта +

  • Katrin Leinweber +

  • Kendall Masse

  • Кевин Шеппард

  • Kyle Kosic +

  • Lorenzo Stella +

  • Maarten Rietbergen +

  • Mak Sze Chun

  • Марк Гарсия

  • Mateusz Woś

  • Matias Heikkilä

  • Mats Maiwald +

  • Мэтью Рёшке

  • Max Bolingbroke +

  • Макс Ковалёвс +

  • Max van Deursen +

  • Майкл

  • Michael Davis +

  • Michael P. Moran +

  • Mike Cramblett +

  • Min ho Kim +

  • Misha Veldhoen +

  • Mukul Ashwath Ram +

  • MusTheDataGuy +

  • Nanda H Krishna +

  • Nicholas Musolino

  • Ноам Херштиг +

  • Noora Husseini +

  • Paul

  • Пол Риди

  • Pauli Virtanen

  • Pav A +

  • Peter Leimbigler +

  • Philippe Ombredanne +

  • Пьетро Баттистон

  • Richard Eames +

  • Roman Yurchak

  • Ruijing Li

  • Ryan

  • Ryan Joyce +

  • Ryan Nazareth

  • Ryan Rehman +

  • Sakar Panta +

  • Samuel Sinayoko

  • Сандип Патхак +

  • Sangwoong Yoon

  • Saurav Chakravorty

  • Scott Talbert +

  • Sergey Kopylov +

  • Shantanu Gontia +

  • Shivam Rana +

  • Shorokhov Sergey +

  • Simon Hawkins

  • Soyoun(Rose) Kim

  • Stephan Hoyer

  • Stephen Cowley +

  • Stephen Rauch

  • Sterling Paramore +

  • Steven +

  • Stijn Van Hoey

  • Sumanau Sareen +

  • Takuya N +

  • Тан Тран +

  • Tao He +

  • Tarbo Fukazawa

  • Terji Petersen +

  • Тейн У

  • ThibTrip +

  • Thijs Damsma +

  • Thiviyan Thanapalasingam

  • Thomas A Caswell

  • Thomas Kluiters +

  • Tilen Kusterle +

  • Tim Gates +

  • Tim Hoffmann

  • Tim Swast

  • Tom Augspurger

  • Tom Neep +

  • Tomáš Chvátal +

  • Tyler Reddy

  • Вайбхав Вишал +

  • Vasily Litvinov +

  • Vibhu Agarwal +

  • Викрамджит Дас +

  • Vladislav +

  • Víctor Moron Tejero +

  • Wenhuan

  • Will Ayd +

  • William Ayd

  • Wouter De Coster +

  • Yoann Goular +

  • Zach Angell +

  • alimcmaster1

  • anmyachev +

  • chris-b1

  • danielplawrence +

  • endenis +

  • enisnazif +

  • ezcitron +

  • fjetter

  • froessler

  • gfyoung

  • gwrome +

  • h-vetinari

  • haison +

  • hannah-c +

  • heckeop +

  • iamshwin +

  • jamesoliverh +

  • jbrockmendel

  • jkovacevic +

  • killerontherun1 +

  • knuu +

  • kpapdac +

  • kpflugshaupt +

  • krsnik93 +

  • leerssej +

  • lrjball +

  • mazayo +

  • nathalier +

  • nrebena +

  • nullptr +

  • pilkibun +

  • pmaxey83 +

  • rbenes +

  • robbuckley

  • shawnbrown +

  • sudhir mohanraj +

  • tadeja +

  • tamuhey +

  • thatneat

  • topper-123

  • willweil +

  • yehia67 +

  • yhaque1213 +