Версия 0.19.0 (2 октября 2016)#

Это основной выпуск с версии 0.18.1 и включает ряд изменений API, несколько новых функций, улучшений и оптимизаций производительности вместе с большим количеством исправлений ошибок. Мы рекомендуем всем пользователям обновиться до этой версии.

Основные моменты включают:

  • merge_asof() для соединения временных рядов в стиле asof, см. здесь

  • .rolling() теперь учитывает временные ряды, см. здесь

  • read_csv() теперь поддерживает парсинг Categorical данные, см. здесь

  • Функция union_categorical() был добавлен для объединения категориальных переменных, см. здесь

  • PeriodIndex теперь имеет свой собственный period тип данных и изменён для большей согласованности с другими Index классы. См. здесь

  • Разреженные структуры данных получили улучшенную поддержку int и bool типы данных, см. здесь

  • Операции сравнения с Series больше не игнорирует индекс, см. здесь для обзора изменений в API.

  • Введение API разработки pandas для служебных функций, см. здесь.

  • Устаревание Panel4D и PanelND. Мы рекомендуем представлять такие типы n-мерных данных с помощью пакет xarray.

  • Удаление ранее устаревших модулей pandas.io.data, pandas.io.wb, pandas.tools.rplot.

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

pandas >= 0.19.0 больше не будет подавлять предупреждения numpy ufunc при импорте, см. здесь.

Новые возможности#

Функция merge_asof для объединения временных рядов в стиле asof#

Долгожданная функция была добавлена через merge_asof() функция для поддержки соединения временных рядов в стиле asof (GH 1870, GH 13695, GH 13709, GH 13902). Полная документация здесь.

The merge_asof() выполняет слияние asof, которое похоже на левое соединение, за исключением того, что мы сопоставляем по ближайшему ключу, а не по равным ключам.

In [1]: left = pd.DataFrame({"a": [1, 5, 10], "left_val": ["a", "b", "c"]})

In [2]: right = pd.DataFrame({"a": [1, 2, 3, 6, 7], "right_val": [1, 2, 3, 6, 7]})

In [3]: left
Out[3]: 
    a left_val
0   1        a
1   5        b
2  10        c

[3 rows x 2 columns]

In [4]: right
Out[4]: 
   a  right_val
0  1          1
1  2          2
2  3          3
3  6          6
4  7          7

[5 rows x 2 columns]

Обычно мы хотим точно сопоставлять, когда это возможно, и использовать наиболее недавнее значение в противном случае.

In [5]: pd.merge_asof(left, right, on="a")
Out[5]: 
    a left_val  right_val
0   1        a          1
1   5        b          3
2  10        c          7

[3 rows x 3 columns]

Мы также можем сопоставлять строки ТОЛЬКО с предыдущими данными, а не точное совпадение.

In [6]: pd.merge_asof(left, right, on="a", allow_exact_matches=False)
Out[6]: 
    a left_val  right_val
0   1        a        NaN
1   5        b        3.0
2  10        c        7.0

[3 rows x 3 columns]

В типичном примере временного ряда у нас есть trades и quotes и мы хотим asof-join их. Это также иллюстрирует использование by параметр для группировки данных перед слиянием.

In [7]: trades = pd.DataFrame(
   ...:     {
   ...:         "time": pd.to_datetime(
   ...:             [
   ...:                 "20160525 13:30:00.023",
   ...:                 "20160525 13:30:00.038",
   ...:                 "20160525 13:30:00.048",
   ...:                 "20160525 13:30:00.048",
   ...:                 "20160525 13:30:00.048",
   ...:             ]
   ...:         ),
   ...:         "ticker": ["MSFT", "MSFT", "GOOG", "GOOG", "AAPL"],
   ...:         "price": [51.95, 51.95, 720.77, 720.92, 98.00],
   ...:         "quantity": [75, 155, 100, 100, 100],
   ...:     },
   ...:     columns=["time", "ticker", "price", "quantity"],
   ...: )
   ...: 

In [8]: quotes = pd.DataFrame(
   ...:     {
   ...:         "time": pd.to_datetime(
   ...:             [
   ...:                 "20160525 13:30:00.023",
   ...:                 "20160525 13:30:00.023",
   ...:                 "20160525 13:30:00.030",
   ...:                 "20160525 13:30:00.041",
   ...:                 "20160525 13:30:00.048",
   ...:                 "20160525 13:30:00.049",
   ...:                 "20160525 13:30:00.072",
   ...:                 "20160525 13:30:00.075",
   ...:             ]
   ...:         ),
   ...:         "ticker": ["GOOG", "MSFT", "MSFT", "MSFT", "GOOG", "AAPL", "GOOG", "MSFT"],
   ...:         "bid": [720.50, 51.95, 51.97, 51.99, 720.50, 97.99, 720.50, 52.01],
   ...:         "ask": [720.93, 51.96, 51.98, 52.00, 720.93, 98.01, 720.88, 52.03],
   ...:     },
   ...:     columns=["time", "ticker", "bid", "ask"],
   ...: )
   ...: 
In [9]: trades
Out[9]: 
                     time ticker   price  quantity
0 2016-05-25 13:30:00.023   MSFT   51.95        75
1 2016-05-25 13:30:00.038   MSFT   51.95       155
2 2016-05-25 13:30:00.048   GOOG  720.77       100
3 2016-05-25 13:30:00.048   GOOG  720.92       100
4 2016-05-25 13:30:00.048   AAPL   98.00       100

[5 rows x 4 columns]

In [10]: quotes
Out[10]: 
                     time ticker     bid     ask
0 2016-05-25 13:30:00.023   GOOG  720.50  720.93
1 2016-05-25 13:30:00.023   MSFT   51.95   51.96
2 2016-05-25 13:30:00.030   MSFT   51.97   51.98
3 2016-05-25 13:30:00.041   MSFT   51.99   52.00
4 2016-05-25 13:30:00.048   GOOG  720.50  720.93
5 2016-05-25 13:30:00.049   AAPL   97.99   98.01
6 2016-05-25 13:30:00.072   GOOG  720.50  720.88
7 2016-05-25 13:30:00.075   MSFT   52.01   52.03

[8 rows x 4 columns]

Объединение asof соединяет по on, обычно поле типа даты-времени, которое упорядочено, и в этом случае мы используем группировщик в by поля. Это похоже на левое внешнее соединение, за исключением того, что прямое заполнение происходит автоматически, беря самое последнее не-NaN значение.

In [11]: pd.merge_asof(trades, quotes, on="time", by="ticker")
Out[11]: 
                     time ticker   price  quantity     bid     ask
0 2016-05-25 13:30:00.023   MSFT   51.95        75   51.95   51.96
1 2016-05-25 13:30:00.038   MSFT   51.95       155   51.97   51.98
2 2016-05-25 13:30:00.048   GOOG  720.77       100  720.50  720.93
3 2016-05-25 13:30:00.048   GOOG  720.92       100  720.50  720.93
4 2016-05-25 13:30:00.048   AAPL   98.00       100     NaN     NaN

[5 rows x 6 columns]

Это возвращает объединенный DataFrame с записями в том же порядке, что и исходный переданный левый DataFrame (trades в этом случае), с полями quotes объединено.

Метод .rolling() теперь учитывает временные ряды#

.rolling() объекты теперь учитывают временные ряды и могут принимать смещение временного ряда (или конвертируемое) для window аргумент (GH 13327, GH 12995). См. полную документацию здесь.

In [12]: dft = pd.DataFrame(
   ....:     {"B": [0, 1, 2, np.nan, 4]},
   ....:     index=pd.date_range("20130101 09:00:00", periods=5, freq="s"),
   ....: )
   ....: 

In [13]: dft
Out[13]: 
                       B
2013-01-01 09:00:00  0.0
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  2.0
2013-01-01 09:00:03  NaN
2013-01-01 09:00:04  4.0

[5 rows x 1 columns]

Это обычный индекс частоты. Использование целочисленного параметра окна работает для скольжения по частоте окна.

In [14]: dft.rolling(2).sum()
Out[14]: 
                       B
2013-01-01 09:00:00  NaN
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  3.0
2013-01-01 09:00:03  NaN
2013-01-01 09:00:04  NaN

[5 rows x 1 columns]

In [15]: dft.rolling(2, min_periods=1).sum()
Out[15]: 
                       B
2013-01-01 09:00:00  0.0
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  3.0
2013-01-01 09:00:03  2.0
2013-01-01 09:00:04  4.0

[5 rows x 1 columns]

Указание смещения позволяет более интуитивно задавать частоту скользящего окна.

In [16]: dft.rolling("2s").sum()
Out[16]: 
                       B
2013-01-01 09:00:00  0.0
2013-01-01 09:00:01  1.0
2013-01-01 09:00:02  3.0
2013-01-01 09:00:03  2.0
2013-01-01 09:00:04  4.0

[5 rows x 1 columns]

Использование нерегулярного, но всё же монотонного индекса с целочисленным окном при скользящих операциях не даёт особых преимуществ в вычислениях.

In [17]: dft = pd.DataFrame(
   ....:     {"B": [0, 1, 2, np.nan, 4]},
   ....:     index=pd.Index(
   ....:         [
   ....:             pd.Timestamp("20130101 09:00:00"),
   ....:             pd.Timestamp("20130101 09:00:02"),
   ....:             pd.Timestamp("20130101 09:00:03"),
   ....:             pd.Timestamp("20130101 09:00:05"),
   ....:             pd.Timestamp("20130101 09:00:06"),
   ....:         ],
   ....:         name="foo",
   ....:     ),
   ....: )
   ....: 

In [18]: dft
Out[18]: 
                       B
foo                     
2013-01-01 09:00:00  0.0
2013-01-01 09:00:02  1.0
2013-01-01 09:00:03  2.0
2013-01-01 09:00:05  NaN
2013-01-01 09:00:06  4.0

[5 rows x 1 columns]

In [19]: dft.rolling(2).sum()
Out[19]: 
                       B
foo                     
2013-01-01 09:00:00  NaN
2013-01-01 09:00:02  1.0
2013-01-01 09:00:03  3.0
2013-01-01 09:00:05  NaN
2013-01-01 09:00:06  NaN

[5 rows x 1 columns]

Использование спецификации времени генерирует переменные окна для этих разреженных данных.

In [20]: dft.rolling("2s").sum()
Out[20]: 
                       B
foo                     
2013-01-01 09:00:00  0.0
2013-01-01 09:00:02  1.0
2013-01-01 09:00:03  3.0
2013-01-01 09:00:05  NaN
2013-01-01 09:00:06  4.0

[5 rows x 1 columns]

Кроме того, теперь мы разрешаем необязательный on параметр для указания столбца (вместо индекса по умолчанию) в DataFrame.

In [21]: dft = dft.reset_index()

In [22]: dft
Out[22]: 
                  foo    B
0 2013-01-01 09:00:00  0.0
1 2013-01-01 09:00:02  1.0
2 2013-01-01 09:00:03  2.0
3 2013-01-01 09:00:05  NaN
4 2013-01-01 09:00:06  4.0

[5 rows x 2 columns]

In [23]: dft.rolling("2s", on="foo").sum()
Out[23]: 
                  foo    B
0 2013-01-01 09:00:00  0.0
1 2013-01-01 09:00:02  1.0
2 2013-01-01 09:00:03  3.0
3 2013-01-01 09:00:05  NaN
4 2013-01-01 09:00:06  4.0

[5 rows x 2 columns]

Метод read_csv имеет улучшенную поддержку дублирующихся имён столбцов#

Дублирующиеся имена столбцов теперь поддерживаются в read_csv() находятся ли они в файле или переданы как names параметр (GH 7160, GH 9424)

In [24]: data = "0,1,2\n3,4,5"

In [25]: names = ["a", "b", "a"]

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

In [2]: pd.read_csv(StringIO(data), names=names)
Out[2]:
   a  b  a
0  2  1  2
1  5  4  5

Первый a столбец содержал те же данные, что и второй a столбец, когда он должен был содержать значения [0, 3].

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

In [26]: pd.read_csv(StringIO(data), names=names)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[26], line 1
----> 1 pd.read_csv(StringIO(data), names=names)

File ~/work/pandas/pandas/pandas/io/parsers/readers.py:1026, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)
   1013 kwds_defaults = _refine_defaults_read(
   1014     dialect,
   1015     delimiter,
   (...)
   1022     dtype_backend=dtype_backend,
   1023 )
   1024 kwds.update(kwds_defaults)
-> 1026 return _read(filepath_or_buffer, kwds)

File ~/work/pandas/pandas/pandas/io/parsers/readers.py:617, in _read(filepath_or_buffer, kwds)
    614 nrows = kwds.get("nrows", None)
    616 # Check for duplicates in names.
--> 617 _validate_names(kwds.get("names", None))
    619 # Create the parser.
    620 parser = TextFileReader(filepath_or_buffer, **kwds)

File ~/work/pandas/pandas/pandas/io/parsers/readers.py:576, in _validate_names(names)
    574 if names is not None:
    575     if len(names) != len(set(names)):
--> 576         raise ValueError("Duplicate names are not allowed.")
    577     if not (
    578         is_list_like(names, allow_sets=False) or isinstance(names, abc.KeysView)
    579     ):
    580         raise ValueError("Names should be an ordered collection.")

ValueError: Duplicate names are not allowed.

Метод read_csv поддерживает разбор Categorical напрямую#

The read_csv() функция теперь поддерживает парсинг Categorical столбец, когда указан как тип данных (GH 10153). В зависимости от структуры данных это может привести к более быстрому времени разбора и меньшему использованию памяти по сравнению с преобразованием в Categorical после парсинга. См. модуль io документация здесь.

In [27]: data = """
   ....: col1,col2,col3
   ....: a,b,1
   ....: a,b,2
   ....: c,d,3
   ....: """
   ....: 

In [28]: pd.read_csv(StringIO(data))
Out[28]: 
  col1 col2  col3
0    a    b     1
1    a    b     2
2    c    d     3

[3 rows x 3 columns]

In [29]: pd.read_csv(StringIO(data)).dtypes
Out[29]: 
col1    object
col2    object
col3     int64
Length: 3, dtype: object

In [30]: pd.read_csv(StringIO(data), dtype="category").dtypes
Out[30]: 
col1    category
col2    category
col3    category
Length: 3, dtype: object

Отдельные столбцы могут быть разобраны как Categorical используя спецификацию словаря

In [31]: pd.read_csv(StringIO(data), dtype={"col1": "category"}).dtypes
Out[31]: 
col1    category
col2      object
col3       int64
Length: 3, dtype: object

Примечание

Результирующие категории всегда будут парситься как строки (тип object). Если категории числовые, их можно преобразовать с помощью to_numeric() функция, или, если уместно, другой конвертер такой как to_datetime().

In [32]: df = pd.read_csv(StringIO(data), dtype="category")

In [33]: df.dtypes
Out[33]: 
col1    category
col2    category
col3    category
Length: 3, dtype: object

In [34]: df["col3"]
Out[34]: 
0    1
1    2
2    3
Name: col3, Length: 3, dtype: category
Categories (3, object): ['1', '2', '3']

In [35]: new_categories = pd.to_numeric(df["col3"].cat.categories)

In [36]: df["col3"] = df["col3"].cat.rename_categories(new_categories)

In [37]: df["col3"]
Out[37]: 
0    1
1    2
2    3
Name: col3, Length: 3, dtype: category
Categories (3, int64): [1, 2, 3]

Конкатенация категориальных переменных#

  • Функция union_categoricals() был добавлен для объединения категориальных переменных, см. Объединение категориальных переменных (GH 13361, GH 13763, GH 13846, GH 14173)

    In [38]: from pandas.api.types import union_categoricals
    
    In [39]: a = pd.Categorical(["b", "c"])
    
    In [40]: b = pd.Categorical(["a", "b"])
    
    In [41]: union_categoricals([a, b])
    Out[41]: 
    ['b', 'c', 'a', 'b']
    Categories (3, object): ['b', 'c', 'a']
    
  • concat и append теперь может объединять category типы данных с разными categories как object тип данных (GH 13524)

    In [42]: s1 = pd.Series(["a", "b"], dtype="category")
    
    In [43]: s2 = pd.Series(["b", "c"], dtype="category")
    

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

In [1]: pd.concat([s1, s2])
ValueError: incompatible categories in categorical concat

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

In [44]: pd.concat([s1, s2])
Out[44]: 
0    a
1    b
0    b
1    c
Length: 4, dtype: object

Полумесячные смещения#

pandas получил новые частотные смещения, SemiMonthEnd ('SM') и SemiMonthBegin (‘SMS’). Они предоставляют смещения дат, привязанные (по умолчанию) к 15-му и концу месяца, а также к 15-му и 1-му числу месяца соответственно. (GH 1543)

In [45]: from pandas.tseries.offsets import SemiMonthEnd, SemiMonthBegin

SemiMonthEnd:

In [46]: pd.Timestamp("2016-01-01") + SemiMonthEnd()
Out[46]: Timestamp('2016-01-15 00:00:00')

In [47]: pd.date_range("2015-01-01", freq="SM", periods=4)
Out[47]: DatetimeIndex(['2015-01-15', '2015-01-31', '2015-02-15', '2015-02-28'], dtype='datetime64[ns]', freq='SM-15')

SemiMonthBegin:

In [46]: pd.Timestamp("2016-01-01") + SemiMonthBegin()
Out[46]: Timestamp('2016-01-15 00:00:00')

In [47]: pd.date_range("2015-01-01", freq="SMS", periods=4)
Out[47]: DatetimeIndex(['2015-01-01', '2015-01-15', '2015-02-01', '2015-02-15'], dtype='datetime64[ns]', freq='SMS-15')

Используя суффикс привязки, вы также можете указать день месяца для использования вместо 15-го.

In [50]: pd.date_range("2015-01-01", freq="SMS-16", periods=4)
Out[50]: DatetimeIndex(['2015-01-01', '2015-01-16', '2015-02-01', '2015-02-16'], dtype='datetime64[ns]', freq='SMS-16')

In [51]: pd.date_range("2015-01-01", freq="SM-14", periods=4)
Out[51]: DatetimeIndex(['2015-01-14', '2015-01-31', '2015-02-14', '2015-02-28'], dtype='datetime64[ns]', freq='SM-14')

Новые методы Index#

Следующие методы и опции добавлены в Index, чтобы быть более согласованными с Series и DataFrame API.

Index теперь поддерживает .where() функция для индексации с одинаковой формой (GH 13170)

In [48]: idx = pd.Index(["a", "b", "c"])

In [49]: idx.where([True, False, True])
Out[49]: Index(['a', None, 'c'], dtype='object')

Index теперь поддерживает .dropna() чтобы исключить пропущенные значения (GH 6194)

In [50]: idx = pd.Index([1, 2, np.nan, 4])

In [51]: idx.dropna()
Out[51]: Index([1.0, 2.0, 4.0], dtype='float64')

Для MultiIndex, значения удаляются, если любой уровень отсутствует по умолчанию. Указание how='all' удаляет только значения, где отсутствуют все уровни.

In [52]: midx = pd.MultiIndex.from_arrays([[1, 2, np.nan, 4], [1, 2, np.nan, np.nan]])

In [53]: midx
Out[53]: 
MultiIndex([(1.0, 1.0),
            (2.0, 2.0),
            (nan, nan),
            (4.0, nan)],
           )

In [54]: midx.dropna()
Out[54]: 
MultiIndex([(1, 1),
            (2, 2)],
           )

In [55]: midx.dropna(how="all")
Out[55]: 
MultiIndex([(1, 1.0),
            (2, 2.0),
            (4, nan)],
           )

Index теперь поддерживает .str.extractall() который возвращает DataFrame, см. документация здесь (GH 10008, GH 13156)

In [56]: idx = pd.Index(["a1a2", "b1", "c1"])

In [57]: idx.str.extractall(r"[ab](?P\d)")
Out[57]: 
        digit
  match      
0 0         1
  1         2
1 0         1

[3 rows x 1 columns]

Index.astype() теперь принимает необязательный булев аргумент copy, что позволяет опциональное копирование, если требования к типу данных удовлетворены (GH 13209)

Улучшения Google BigQuery#

  • The read_gbq() метод получил dialect Mie~~~ + документация для дополнительных деталей (GH 13615).

  • The to_gbq() метод теперь позволяет порядку столбцов DataFrame отличаться от схемы таблицы назначения (GH 11359).

Детализированный NumPy errstate#

Предыдущие версии pandas постоянно отключали обработку ошибок ufunc numpy, когда pandas был импортирован. pandas делал это, чтобы заглушить предупреждения, возникающие при использовании numpy ufuncs на пропущенных данных, которые обычно представлены как NaN s. К сожалению, это заглушало законные предупреждения, возникающие в не-pandas коде приложения. Начиная с 0.19.0, pandas будет использовать numpy.errstate контекстный менеджер для подавления этих предупреждений более детальным образом, только вокруг тех мест, где эти операции фактически используются в кодовой базе pandas. (GH 13109, GH 13145)

После обновления pandas вы можете увидеть новый RuntimeWarnings выдаваемые из вашего кода. Вероятно, они законны, и основная причина, вероятно, существовала в коде при использовании предыдущих версий pandas, которые просто подавляли предупреждение. Используйте numpy.errstate вокруг источника RuntimeWarning для управления обработкой этих условий.

Метод get_dummies теперь возвращает целочисленные dtypes#

The pd.get_dummies функция теперь возвращает фиктивно-кодированные столбцы как маленькие целые числа, а не числа с плавающей точкой (GH 8725). Это должно обеспечить улучшенное использование памяти.

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

In [1]: pd.get_dummies(['a', 'b', 'a', 'c']).dtypes

Out[1]:
a    float64
b    float64
c    float64
dtype: object

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

In [58]: pd.get_dummies(["a", "b", "a", "c"]).dtypes
Out[58]: 
a    bool
b    bool
c    bool
Length: 3, dtype: object

Понизить значения до наименьшего возможного типа данных в to_numeric#

pd.to_numeric() теперь принимает downcast параметр, который понизит тип данных, если возможно, до наименьшего указанного числового типа данных (GH 13352)

In [59]: s = ["1", 2, 3]

In [60]: pd.to_numeric(s, downcast="unsigned")
Out[60]: array([1, 2, 3], dtype=uint8)

In [61]: pd.to_numeric(s, downcast="integer")
Out[61]: array([1, 2, 3], dtype=int8)

API разработки pandas#

В рамках будущей унификации и повышения доступности API pandas мы создали стандартный подпакет pandas, pandas.api для хранения публичных API. Мы начинаем с раскрытия функций интроспекции типов в pandas.api.types. Дополнительные подпакеты и официально утверждённые API будут опубликованы в будущих версиях pandas (GH 13147, GH 13634)

Следующие элементы теперь являются частью этого API:

In [62]: import pprint

In [63]: from pandas.api import types

In [64]: funcs = [f for f in dir(types) if not f.startswith("_")]

In [65]: pprint.pprint(funcs)
['CategoricalDtype',
 'DatetimeTZDtype',
 'IntervalDtype',
 'PeriodDtype',
 'infer_dtype',
 'is_any_real_numeric_dtype',
 'is_array_like',
 'is_bool',
 'is_bool_dtype',
 'is_categorical_dtype',
 'is_complex',
 'is_complex_dtype',
 'is_datetime64_any_dtype',
 'is_datetime64_dtype',
 'is_datetime64_ns_dtype',
 'is_datetime64tz_dtype',
 'is_dict_like',
 'is_dtype_equal',
 'is_extension_array_dtype',
 'is_file_like',
 'is_float',
 'is_float_dtype',
 'is_hashable',
 'is_int64_dtype',
 'is_integer',
 'is_integer_dtype',
 'is_interval',
 'is_interval_dtype',
 'is_iterator',
 'is_list_like',
 'is_named_tuple',
 'is_number',
 'is_numeric_dtype',
 'is_object_dtype',
 'is_period_dtype',
 'is_re',
 'is_re_compilable',
 'is_scalar',
 'is_signed_integer_dtype',
 'is_sparse',
 'is_string_dtype',
 'is_timedelta64_dtype',
 'is_timedelta64_ns_dtype',
 'is_unsigned_integer_dtype',
 'pandas_dtype',
 'union_categoricals']

Примечание

Вызов этих функций из внутреннего модуля pandas.core.common теперь будет показывать DeprecationWarning (GH 13990)

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

  • Timestamp теперь может принимать позиционные и ключевые параметры, аналогичные datetime.datetime() (GH 10758, GH 11630)

    In [66]: pd.Timestamp(2012, 1, 1)
    Out[66]: Timestamp('2012-01-01 00:00:00')
    
    In [67]: pd.Timestamp(year=2012, month=1, day=1, hour=8, minute=30)
    Out[67]: Timestamp('2012-01-01 08:30:00')
    
  • The .resample() функция теперь принимает on= или level= параметр для ресемплинга по столбцу типа datetime или MultiIndex уровень (GH 13500)

    In [68]: df = pd.DataFrame(
       ....:     {"date": pd.date_range("2015-01-01", freq="W", periods=5), "a": np.arange(5)},
       ....:     index=pd.MultiIndex.from_arrays(
       ....:         [[1, 2, 3, 4, 5], pd.date_range("2015-01-01", freq="W", periods=5)],
       ....:         names=["v", "d"],
       ....:     ),
       ....: )
       ....: 
    
    In [69]: df
    Out[69]: 
                       date  a
    v d                       
    1 2015-01-04 2015-01-04  0
    2 2015-01-11 2015-01-11  1
    3 2015-01-18 2015-01-18  2
    4 2015-01-25 2015-01-25  3
    5 2015-02-01 2015-02-01  4
    
    [5 rows x 2 columns]
    
    In [74]: df.resample("M", on="date")[["a"]].sum()
    Out[74]:
                a
    date
    2015-01-31  6
    2015-02-28  4
    
    [2 rows x 1 columns]
    
    In [75]: df.resample("M", level="d")[["a"]].sum()
    Out[75]:
                a
    d
    2015-01-31  6
    2015-02-28  4
    
    [2 rows x 1 columns]
    
  • The .get_credentials() метод GbqConnector теперь может сначала попытаться получить учётные данные приложения по умолчанию. Подробнее см. в документации (GH 13577).

  • The .tz_localize() метод DatetimeIndex и Timestamp получил errors ключевое слово, поэтому вы можете потенциально преобразовать несуществующие временные метки в NaT. Поведение по умолчанию остается вызовом исключения NonExistentTimeError (GH 13057)

  • .to_hdf/read_hdf() теперь принимают объекты пути (например, pathlib.Path, py.path.local) для пути к файлу (GH 11773)

  • The pd.read_csv() с engine='python' получил поддержку для decimal (GH 12933), na_filter (GH 13321) и memory_map опция (GH 13381).

  • В соответствии с Python API, pd.read_csv() теперь будет интерпретировать +inf как положительная бесконечность (GH 13274)

  • The pd.read_html() получил поддержку для na_values, converters, keep_default_na опции (GH 13461)

  • Categorical.astype() теперь принимает необязательный булев аргумент copy, действует, когда тип данных является категориальным (GH 13209)

  • DataFrame получил .asof() метод для возврата последних не-NaN значений в соответствии с выбранным подмножеством (GH 13358)

  • The DataFrame конструктор теперь будет учитывать порядок ключей, если передан список OrderedDict объекты передаются (GH 13304)

  • pd.read_html() получил поддержку для decimal опция (GH 12907)

  • Series получил свойства .is_monotonic, .is_monotonic_increasing, .is_monotonic_decreasing, аналогично Index (GH 13336)

  • DataFrame.to_sql() теперь позволяет использовать одно значение в качестве типа SQL для всех столбцов (GH 11886).

  • Series.append теперь поддерживает ignore_index опция (GH 13677)

  • .to_stata() и StataWriter теперь можно записывать метки переменных в файлы Stata dta, используя словарь для сопоставления имен столбцов с метками (GH 13535, GH 13536)

  • .to_stata() и StataWriter будет автоматически конвертировать datetime64[ns] столбцы в формат Stata %tc, а не вызов ValueError (GH 12259)

  • read_stata() и StataReader выдавать более явное сообщение об ошибке при чтении файлов Stata с повторяющимися метками значений, когда convert_categoricals=True (GH 13923)

  • DataFrame.style теперь будет отображать разреженные MultiIndexes (GH 11655)

  • DataFrame.style теперь будет показывать имена уровней столбцов (например, DataFrame.columns.names) (GH 13775)

  • DataFrame получил поддержку переупорядочивания столбцов на основе значений в строке с использованием df.sort_values(by='...', axis=1) (GH 10806)

    In [70]: df = pd.DataFrame({"A": [2, 7], "B": [3, 5], "C": [4, 8]}, index=["row1", "row2"])
    
    In [71]: df
    Out[71]: 
          A  B  C
    row1  2  3  4
    row2  7  5  8
    
    [2 rows x 3 columns]
    
    In [72]: df.sort_values(by="row2", axis=1)
    Out[72]: 
          B  A  C
    row1  3  2  4
    row2  5  7  8
    
    [2 rows x 3 columns]
    
  • Добавлена документация к I/O о рисках чтения столбцов со смешанными dtypes и как с этим справиться (GH 13746)

  • to_html() теперь имеет border аргумент для управления значением в открывающем тег. По умолчанию используется значение html.border опции, которая по умолчанию равна 1. Это также влияет на HTML-представление в блокноте, но поскольку CSS Jupyter включает атрибут border-width, визуальный эффект одинаков. (GH 11563).

  • Вызвать ImportError в функциях sql, когда sqlalchemy не установлен и используется строка подключения (GH 11920).

  • Совместимость с matplotlib 2.0. Более старые версии pandas также должны работать с matplotlib 2.0 (GH 13333)

  • Timestamp, Period, DatetimeIndex, PeriodIndex и .dt аксессор получил .is_leap_year свойство для проверки, принадлежит ли дата високосному году. (GH 13727)

  • astype() теперь принимает словарь отображения имени столбца на типы данных как dtype аргумент. (GH 12086)

  • The pd.read_json и DataFrame.to_json теперь поддерживает чтение и запись json lines с lines опцию см. JSON с разделителями строк (GH 9180)

  • read_excel() теперь поддерживает аргументы ключевых слов true_values и false_values (GH 13347)

  • groupby() теперь принимает скаляр и список из одного элемента для указания level на не-MultiIndex группировщик. (GH 13907)

  • Неконвертируемые даты в столбце дат Excel будут возвращены без преобразования, и столбец будет object тип данных, а не вызов исключения (GH 10001).

  • pd.Timedelta(None) теперь принимается и будет возвращать NaT, зеркально отражая pd.Timestamp (GH 13687)

  • pd.read_stata() теперь может обрабатывать некоторые файлы формата 111, которые создаются SAS при генерации файлов Stata dta (GH 11526)

  • Series и Index теперь поддерживает divmod который вернёт кортеж из серий или индексов. Это ведёт себя как стандартный бинарный оператор в отношении правил трансляции (GH 14208).

  • Изменения API#

    Series.tolist() теперь будет возвращать типы Python#

    Series.tolist() теперь будет возвращать типы Python в выводе, имитируя NumPy .tolist() поведение (GH 10904)

    In [73]: s = pd.Series([1, 2, 3])
    

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

    In [7]: type(s.tolist()[0])
    Out[7]:
     
    

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

    In [74]: type(s.tolist()[0])
    Out[74]: int
    

    Series операторы для различных индексов#

    Следуя Series операторы были изменены для обеспечения согласованности всех операторов, включая DataFrame (GH 1134, GH 4581, GH 13538)

    • Series операторы сравнения теперь вызывают ValueError когда index различаются.

    • Series логические операторы выравнивают оба index левой и правой стороны.

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

    До версии 0.18.1, сравнение Series с той же длиной, будет успешным, даже если .index различны (результат игнорирует .index). Начиная с версии 0.19.0, это вызовет ValueError быть более строгим. Этот раздел также описывает, как сохранить предыдущее поведение или выровнять разные индексы, используя гибкие методы сравнения, такие как .eq.

    В результате, Series и DataFrame операторы ведут себя следующим образом:

    Арифметические операторы#

    Арифметические операторы выравнивают оба index (без изменений).

    In [75]: s1 = pd.Series([1, 2, 3], index=list("ABC"))
    
    In [76]: s2 = pd.Series([2, 2, 2], index=list("ABD"))
    
    In [77]: s1 + s2
    Out[77]: 
    A    3.0
    B    4.0
    C    NaN
    D    NaN
    Length: 4, dtype: float64
    
    In [78]: df1 = pd.DataFrame([1, 2, 3], index=list("ABC"))
    
    In [79]: df2 = pd.DataFrame([2, 2, 2], index=list("ABD"))
    
    In [80]: df1 + df2
    Out[80]: 
         0
    A  3.0
    B  4.0
    C  NaN
    D  NaN
    
    [4 rows x 1 columns]
    

    Операторы сравнения#

    Операторы сравнения вызывают ValueError когда .index различаются.

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

    Series сравниваемые значения, игнорируя .index при условии, что оба имели одинаковую длину:

    In [1]: s1 == s2
    Out[1]:
    A    False
    B     True
    C    False
    dtype: bool
    

    Новое поведение (Series):

    In [2]: s1 == s2
    Out[2]:
    ValueError: Can only compare identically-labeled Series objects
    

    Примечание

    Чтобы достичь того же результата, что и в предыдущих версиях (сравнивать значения на основе местоположений, игнорируя .index), сравните оба .values.

    In [81]: s1.values == s2.values
    Out[81]: array([False,  True, False])
    

    Если вы хотите сравнить Series выравнивая его .index, см. раздел гибких методов сравнения ниже:

    In [82]: s1.eq(s2)
    Out[82]: 
    A    False
    B     True
    C    False
    D    False
    Length: 4, dtype: bool
    

    Текущее поведение (DataFrame, без изменений):

    In [3]: df1 == df2
    Out[3]:
    ValueError: Can only compare identically-labeled DataFrame objects
    

    Логические операторы#

    Логические операторы выравнивают оба .index левой и правой стороны.

    Предыдущее поведение (Series), только левая сторона index было сохранено:

    In [4]: s1 = pd.Series([True, False, True], index=list('ABC'))
    In [5]: s2 = pd.Series([True, True, True], index=list('ABD'))
    In [6]: s1 & s2
    Out[6]:
    A     True
    B    False
    C    False
    dtype: bool
    

    Новое поведение (Series):

    In [83]: s1 = pd.Series([True, False, True], index=list("ABC"))
    
    In [84]: s2 = pd.Series([True, True, True], index=list("ABD"))
    
    In [85]: s1 & s2
    Out[85]: 
    A     True
    B    False
    C    False
    D    False
    Length: 4, dtype: bool
    

    Примечание

    Series логические операторы заполняют NaN результат с False.

    Примечание

    Чтобы достичь того же результата, что и в предыдущих версиях (сравнивать значения только по левому индексу), можно использовать reindex_like:

    In [86]: s1 & s2.reindex_like(s1)
    Out[86]: 
    A     True
    B    False
    C    False
    Length: 3, dtype: bool
    

    Текущее поведение (DataFrame, без изменений):

    In [87]: df1 = pd.DataFrame([True, False, True], index=list("ABC"))
    
    In [88]: df2 = pd.DataFrame([True, True, True], index=list("ABD"))
    
    In [89]: df1 & df2
    Out[89]: 
           0
    A   True
    B  False
    C  False
    D  False
    
    [4 rows x 1 columns]
    

    Гибкие методы сравнения#

    Series гибкие методы сравнения, такие как eq, ne, le, lt, ge и gt теперь выравнивать оба index. Используйте эти операторы, если хотите сравнить два Series который имеет другой index.

    In [90]: s1 = pd.Series([1, 2, 3], index=["a", "b", "c"])
    
    In [91]: s2 = pd.Series([2, 2, 2], index=["b", "c", "d"])
    
    In [92]: s1.eq(s2)
    Out[92]: 
    a    False
    b     True
    c    False
    d    False
    Length: 4, dtype: bool
    
    In [93]: s1.ge(s2)
    Out[93]: 
    a    False
    b     True
    c     True
    d    False
    Length: 4, dtype: bool
    

    Ранее это работало так же, как операторы сравнения (см. выше).

    Series повышение типа при присваивании#

    A Series теперь будет правильно повышать свой dtype при присваивании несовместимых значений к текущему dtype (GH 13234)

    In [94]: s = pd.Series()
    

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

    In [2]: s["a"] = pd.Timestamp("2016-01-01")
    
    In [3]: s["b"] = 3.0
    TypeError: invalid type promotion
    

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

    In [95]: s["a"] = pd.Timestamp("2016-01-01")
    
    In [96]: s["b"] = 3.0
    
    In [97]: s
    Out[97]: 
    a    2016-01-01 00:00:00
    b                    3.0
    Length: 2, dtype: object
    
    In [98]: s.dtype
    Out[98]: dtype('O')
    

    Функция .to_datetime() изменения#

    Ранее если .to_datetime() встречались смешанные целые числа/дроби и строки, но без дат и времени с errors='coerce' это преобразует все в NaT.

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

    In [2]: pd.to_datetime([1, 'foo'], errors='coerce')
    Out[2]: DatetimeIndex(['NaT', 'NaT'], dtype='datetime64[ns]', freq=None)
    

    Текущее поведение:

    Теперь это будет преобразовывать целые числа/числа с плавающей точкой с единицей измерения по умолчанию ns.

    In [99]: pd.to_datetime([1, "foo"], errors="coerce")
    Out[99]: DatetimeIndex(['1970-01-01 00:00:00.000000001', 'NaT'], dtype='datetime64[ns]', freq=None)
    

    Исправления ошибок, связанные с .to_datetime():

    • Ошибка в pd.to_datetime() при передаче целых чисел или чисел с плавающей точкой, и нет unit и errors='coerce' (GH 13180).

    • Ошибка в pd.to_datetime() при передаче недопустимых типов данных (например, bool); теперь будет учитывать errors ключевое слово (GH 13176)

    • Ошибка в pd.to_datetime() который переполнялся на int8, и int16 типы данных (GH 13451)

    • Ошибка в pd.to_datetime() raise AttributeError с NaN и другая строка недействительна, когда errors='ignore' (GH 12424)

    • Ошибка в pd.to_datetime() не преобразовывал числа с плавающей точкой корректно, когда unit был указан, что привело к усечению даты и времени (GH 13834)

    Объединение изменений#

    Слияние теперь будет сохранять тип данных ключей соединения (GH 8596)

    In [100]: df1 = pd.DataFrame({"key": [1], "v1": [10]})
    
    In [101]: df1
    Out[101]: 
       key  v1
    0    1  10
    
    [1 rows x 2 columns]
    
    In [102]: df2 = pd.DataFrame({"key": [1, 2], "v1": [20, 30]})
    
    In [103]: df2
    Out[103]: 
       key  v1
    0    1  20
    1    2  30
    
    [2 rows x 2 columns]
    

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

    In [5]: pd.merge(df1, df2, how='outer')
    Out[5]:
       key    v1
    0  1.0  10.0
    1  1.0  20.0
    2  2.0  30.0
    
    In [6]: pd.merge(df1, df2, how='outer').dtypes
    Out[6]:
    key    float64
    v1     float64
    dtype: object
    

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

    Мы можем сохранить ключи соединения

    In [104]: pd.merge(df1, df2, how="outer")
    Out[104]: 
       key  v1
    0    1  10
    1    1  20
    2    2  30
    
    [3 rows x 2 columns]
    
    In [105]: pd.merge(df1, df2, how="outer").dtypes
    Out[105]: 
    key    int64
    v1     int64
    Length: 2, dtype: object
    

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

    In [106]: pd.merge(df1, df2, how="outer", on="key")
    Out[106]: 
       key  v1_x  v1_y
    0    1  10.0    20
    1    2   NaN    30
    
    [2 rows x 3 columns]
    
    In [107]: pd.merge(df1, df2, how="outer", on="key").dtypes
    Out[107]: 
    key       int64
    v1_x    float64
    v1_y      int64
    Length: 3, dtype: object
    

    Метод .describe() изменения#

    Идентификаторы процентилей в индексе .describe() вывод теперь будет округляться до наименьшей точности, сохраняющей их различия (GH 13104)

    In [108]: s = pd.Series([0, 1, 2, 3, 4])
    
    In [109]: df = pd.DataFrame([0, 1, 2, 3, 4])
    

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

    Процентили округлялись максимум до одного десятичного знака, что могло вызвать ValueError для data frame, если процентили были дублированы.

    In [3]: s.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
    Out[3]:
    count     5.000000
    mean      2.000000
    std       1.581139
    min       0.000000
    0.0%      0.000400
    0.1%      0.002000
    0.1%      0.004000
    50%       2.000000
    99.9%     3.996000
    100.0%    3.998000
    100.0%    3.999600
    max       4.000000
    dtype: float64
    
    In [4]: df.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
    Out[4]:
    ...
    ValueError: cannot reindex from a duplicate axis
    

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

    In [110]: s.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
    Out[110]: 
    count     5.000000
    mean      2.000000
    std       1.581139
    min       0.000000
    0.01%     0.000400
    0.05%     0.002000
    0.1%      0.004000
    50%       2.000000
    99.9%     3.996000
    99.95%    3.998000
    99.99%    3.999600
    max       4.000000
    Length: 12, dtype: float64
    
    In [111]: df.describe(percentiles=[0.0001, 0.0005, 0.001, 0.999, 0.9995, 0.9999])
    Out[111]: 
                   0
    count   5.000000
    mean    2.000000
    std     1.581139
    min     0.000000
    0.01%   0.000400
    0.05%   0.002000
    0.1%    0.004000
    50%     2.000000
    99.9%   3.996000
    99.95%  3.998000
    99.99%  3.999600
    max     4.000000
    
    [12 rows x 1 columns]
    

    Кроме того:

    • Передача дублированных percentiles теперь вызовет ValueError.

    • Ошибка в .describe() к DataFrame со смешанным индексом столбцов по типам данных, что ранее вызывало TypeError (GH 13288)

    Period изменения#

    The PeriodIndex теперь имеет period dtype#

    PeriodIndex теперь имеет свой собственный period dtype. The period dtype является pandas extension dtype, таким как category или тип данных с учетом часового пояса (datetime64[ns, tz]) (GH 13941). Как следствие этого изменения, PeriodIndex больше не имеет целочисленного типа данных:

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

    In [1]: pi = pd.PeriodIndex(['2016-08-01'], freq='D')
    
    In [2]: pi
    Out[2]: PeriodIndex(['2016-08-01'], dtype='int64', freq='D')
    
    In [3]: pd.api.types.is_integer_dtype(pi)
    Out[3]: True
    
    In [4]: pi.dtype
    Out[4]: dtype('int64')
    

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

    In [112]: pi = pd.PeriodIndex(["2016-08-01"], freq="D")
    
    In [113]: pi
    Out[113]: PeriodIndex(['2016-08-01'], dtype='period[D]')
    
    In [114]: pd.api.types.is_integer_dtype(pi)
    Out[114]: False
    
    In [115]: pd.api.types.is_period_dtype(pi)
    Out[115]: True
    
    In [116]: pi.dtype
    Out[116]: period[D]
    
    In [117]: type(pi.dtype)
    Out[117]: pandas.core.dtypes.dtypes.PeriodDtype
    

    Period('NaT') теперь возвращает pd.NaT#

    Ранее, Period имеет свой собственный Period('NaT') представление, отличное от pd.NaT. Теперь Period('NaT') было изменено для возврата pd.NaT. (GH 12759, GH 13582)

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

    In [5]: pd.Period('NaT', freq='D')
    Out[5]: Period('NaT', 'D')
    

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

    Это приводит к pd.NaT без предоставления freq опция.

    In [118]: pd.Period("NaT")
    Out[118]: NaT
    
    In [119]: pd.Period(None)
    Out[119]: NaT
    

    Для совместимости с Period сложение и вычитание, pd.NaT теперь поддерживает сложение и вычитание с int. Ранее вызывалось исключение ValueError.

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

    In [5]: pd.NaT + 1
    ...
    ValueError: Cannot add integral value to Timestamp without freq.
    

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

    In [120]: pd.NaT + 1
    Out[120]: NaT
    
    In [121]: pd.NaT - 1
    Out[121]: NaT
    

    PeriodIndex.values теперь возвращает массив Period object#

    .values изменён на возврат массива Period объектов, а не массив целых чисел (GH 13988).

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

    In [6]: pi = pd.PeriodIndex(['2011-01', '2011-02'], freq='M')
    In [7]: pi.values
    Out[7]: array([492, 493])
    

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

    In [122]: pi = pd.PeriodIndex(["2011-01", "2011-02"], freq="M")
    
    In [123]: pi.values
    Out[123]: array([Period('2011-01', 'M'), Period('2011-02', 'M')], dtype=object)
    

    Index + / - больше не используется для операций над множествами#

    Сложение и вычитание базового типа Index и DatetimeIndex (не числовых типов индексов) ранее выполняли операции над множествами (объединение и разность множеств). Это поведение уже было устаревшим с версии 0.15.0 (в пользу использования конкретных .union() и .difference() методы), и теперь отключен. Когда возможно, + и - теперь используются для поэлементных операций, например, для конкатенации строк или вычитания дат (GH 8227, GH 14127).

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

    In [1]: pd.Index(['a', 'b']) + pd.Index(['a', 'c'])
    FutureWarning: using '+' to provide set union with Indexes is deprecated, use '|' or .union()
    Out[1]: Index(['a', 'b', 'c'], dtype='object')
    

    Новое поведение: та же операция теперь будет выполнять поэлементное сложение:

    In [124]: pd.Index(["a", "b"]) + pd.Index(["a", "c"])
    Out[124]: Index(['aa', 'bc'], dtype='object')
    

    Обратите внимание, что числовые объекты Index уже выполняли поэлементные операции. Например, поведение сложения двух целочисленных Index осталось неизменным. Базовый Index теперь согласован с этим поведением.

    In [125]: pd.Index([1, 2, 3]) + pd.Index([2, 3, 4])
    Out[125]: Index([3, 5, 7], dtype='int64')
    

    Кроме того, из-за этого изменения теперь возможно вычитать два объекта DatetimeIndex, получая TimedeltaIndex:

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

    In [1]: (pd.DatetimeIndex(['2016-01-01', '2016-01-02'])
       ...:  - pd.DatetimeIndex(['2016-01-02', '2016-01-03']))
    FutureWarning: using '-' to provide set differences with datetimelike Indexes is deprecated, use .difference()
    Out[1]: DatetimeIndex(['2016-01-01'], dtype='datetime64[ns]', freq=None)
    

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

    In [126]: (
       .....:     pd.DatetimeIndex(["2016-01-01", "2016-01-02"])
       .....:     - pd.DatetimeIndex(["2016-01-02", "2016-01-03"])
       .....: )
       .....: 
    Out[126]: TimedeltaIndex(['-1 days', '-1 days'], dtype='timedelta64[ns]', freq=None)
    

    Index.difference и .symmetric_difference изменения#

    Index.difference и Index.symmetric_difference теперь будет более последовательно обрабатывать NaN значения как любые другие значения. (GH 13514)

    In [127]: idx1 = pd.Index([1, 2, 3, np.nan])
    
    In [128]: idx2 = pd.Index([0, 1, np.nan])
    

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

    In [3]: idx1.difference(idx2)
    Out[3]: Float64Index([nan, 2.0, 3.0], dtype='float64')
    
    In [4]: idx1.symmetric_difference(idx2)
    Out[4]: Float64Index([0.0, nan, 2.0, 3.0], dtype='float64')
    

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

    In [129]: idx1.difference(idx2)
    Out[129]: Index([2.0, 3.0], dtype='float64')
    
    In [130]: idx1.symmetric_difference(idx2)
    Out[130]: Index([0.0, 2.0, 3.0], dtype='float64')
    

    Index.unique последовательно возвращает Index#

    Index.unique() теперь возвращает уникальные значения как Index соответствующего dtype. (GH 13395). Ранее большинство Index классы, возвращённые np.ndarray, и DatetimeIndex, TimedeltaIndex и PeriodIndex возвращён Index для сохранения метаданных, таких как часовой пояс.

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

    In [1]: pd.Index([1, 2, 3]).unique()
    Out[1]: array([1, 2, 3])
    
    In [2]: pd.DatetimeIndex(['2011-01-01', '2011-01-02',
       ...:                   '2011-01-03'], tz='Asia/Tokyo').unique()
    Out[2]:
    DatetimeIndex(['2011-01-01 00:00:00+09:00', '2011-01-02 00:00:00+09:00',
                   '2011-01-03 00:00:00+09:00'],
                  dtype='datetime64[ns, Asia/Tokyo]', freq=None)
    

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

    In [131]: pd.Index([1, 2, 3]).unique()
    Out[131]: Index([1, 2, 3], dtype='int64')
    
    In [132]: pd.DatetimeIndex(
       .....:     ["2011-01-01", "2011-01-02", "2011-01-03"], tz="Asia/Tokyo"
       .....: ).unique()
       .....: 
    Out[132]: 
    DatetimeIndex(['2011-01-01 00:00:00+09:00', '2011-01-02 00:00:00+09:00',
                   '2011-01-03 00:00:00+09:00'],
                  dtype='datetime64[ns, Asia/Tokyo]', freq=None)
    

    MultiIndex конструкторы, groupby и set_index сохранять категориальные типы данных#

    MultiIndex.from_arrays и MultiIndex.from_product теперь будет сохранять категориальный тип данных в MultiIndex уровни (GH 13743, GH 13854).

    In [133]: cat = pd.Categorical(["a", "b"], categories=list("bac"))
    
    In [134]: lvl1 = ["foo", "bar"]
    
    In [135]: midx = pd.MultiIndex.from_arrays([cat, lvl1])
    
    In [136]: midx
    Out[136]: 
    MultiIndex([('a', 'foo'),
                ('b', 'bar')],
               )
    

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

    In [4]: midx.levels[0]
    Out[4]: Index(['b', 'a', 'c'], dtype='object')
    
    In [5]: midx.get_level_values[0]
    Out[5]: Index(['a', 'b'], dtype='object')
    

    Новое поведение: одиночный уровень теперь является CategoricalIndex:

    In [137]: midx.levels[0]
    Out[137]: CategoricalIndex(['b', 'a', 'c'], categories=['b', 'a', 'c'], ordered=False, dtype='category')
    
    In [138]: midx.get_level_values(0)
    Out[138]: CategoricalIndex(['a', 'b'], categories=['b', 'a', 'c'], ordered=False, dtype='category')
    

    Аналогичное изменение было сделано для MultiIndex.from_product. Как следствие, groupby и set_index также сохраняют категориальные типы данных в индексах

    In [139]: df = pd.DataFrame({"A": [0, 1], "B": [10, 11], "C": cat})
    
    In [140]: df_grouped = df.groupby(by=["A", "C"], observed=False).first()
    
    In [141]: df_set_idx = df.set_index(["A", "C"])
    

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

    In [11]: df_grouped.index.levels[1]
    Out[11]: Index(['b', 'a', 'c'], dtype='object', name='C')
    In [12]: df_grouped.reset_index().dtypes
    Out[12]:
    A      int64
    C     object
    B    float64
    dtype: object
    
    In [13]: df_set_idx.index.levels[1]
    Out[13]: Index(['b', 'a', 'c'], dtype='object', name='C')
    In [14]: df_set_idx.reset_index().dtypes
    Out[14]:
    A      int64
    C     object
    B      int64
    dtype: object
    

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

    In [142]: df_grouped.index.levels[1]
    Out[142]: CategoricalIndex(['b', 'a', 'c'], categories=['b', 'a', 'c'], ordered=False, dtype='category', name='C')
    
    In [143]: df_grouped.reset_index().dtypes
    Out[143]: 
    A       int64
    C    category
    B     float64
    Length: 3, dtype: object
    
    In [144]: df_set_idx.index.levels[1]
    Out[144]: CategoricalIndex(['b', 'a', 'c'], categories=['b', 'a', 'c'], ordered=False, dtype='category', name='C')
    
    In [145]: df_set_idx.reset_index().dtypes
    Out[145]: 
    A       int64
    C    category
    B       int64
    Length: 3, dtype: object
    

    Функция read_csv будет последовательно перечислять блоки#

    Когда read_csv() вызывается с chunksize=n и без указания индекса, каждый блок имел независимо сгенерированный индекс из 0 to n-1. Теперь им вместо этого присваивается прогрессивный индекс, начиная с 0 для первого фрагмента, от n для второго и так далее, так что при объединении они идентичны результату вызова read_csv() без chunksize= аргумент (GH 12185).

    In [146]: data = "A,B\n0,1\n2,3\n4,5\n6,7"
    

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

    In [2]: pd.concat(pd.read_csv(StringIO(data), chunksize=2))
    Out[2]:
       A  B
    0  0  1
    1  2  3
    0  4  5
    1  6  7
    

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

    In [147]: pd.concat(pd.read_csv(StringIO(data), chunksize=2))
    Out[147]: 
       A  B
    0  0  1
    1  2  3
    2  4  5
    3  6  7
    
    [4 rows x 2 columns]
    

    Изменения в Sparse#

    Эти изменения позволяют pandas работать с разреженными данными с большим количеством типов данных и способствуют более плавной работе с обработкой данных.

    Типы int64 и bool улучшения поддержки#

    Разреженные структуры данных теперь получили расширенную поддержку int64 и bool dtype (GH 667, GH 13849).

    Ранее разреженные данные были float64 dtype по умолчанию, даже если все входные данные были типа int или bool dtype. Вы должны были указать dtype явно для создания разреженных данных с int64 тип данных. Также, fill_value должно было быть указано явно, потому что значение по умолчанию было np.nan который не появляется в int64 или bool data.

    In [1]: pd.SparseArray([1, 2, 0, 0])
    Out[1]:
    [1.0, 2.0, 0.0, 0.0]
    Fill: nan
    IntIndex
    Indices: array([0, 1, 2, 3], dtype=int32)
    
    # specifying int64 dtype, but all values are stored in sp_values because
    # fill_value default is np.nan
    In [2]: pd.SparseArray([1, 2, 0, 0], dtype=np.int64)
    Out[2]:
    [1, 2, 0, 0]
    Fill: nan
    IntIndex
    Indices: array([0, 1, 2, 3], dtype=int32)
    
    In [3]: pd.SparseArray([1, 2, 0, 0], dtype=np.int64, fill_value=0)
    Out[3]:
    [1, 2, 0, 0]
    Fill: 0
    IntIndex
    Indices: array([0, 1], dtype=int32)
    

    Начиная с v0.19.0, разреженные данные сохраняют входной тип данных и используют более подходящие fill_value значения по умолчанию (0 для int64 dtype, False для bool dtype).

    In [148]: pd.arrays.SparseArray([1, 2, 0, 0], dtype=np.int64)
    Out[148]: 
    [1, 2, 0, 0]
    Fill: 0
    IntIndex
    Indices: array([0, 1], dtype=int32)
    
    In [149]: pd.arrays.SparseArray([True, False, False, False])
    Out[149]: 
    [True, False, False, False]
    Fill: False
    IntIndex
    Indices: array([0], dtype=int32)
    

    См. документация для получения дополнительной информации.

    Операторы теперь сохраняют типы данных#

    • Разреженная структура данных теперь может сохранять dtype после арифметических операций (GH 13848)

    s = pd.SparseSeries([0, 2, 0, 1], fill_value=0, dtype=np.int64)
    s.dtype
    
    s + 1
    
    • Разреженные структуры данных теперь поддерживают astype для преобразования внутренних dtype (GH 13900)

    s = pd.SparseSeries([1.0, 0.0, 2.0, 0.0], fill_value=0)
    s
    s.astype(np.int64)
    

    astype завершается ошибкой, если данные содержат значения, которые нельзя преобразовать в указанные dtype. Обратите внимание, что ограничение применяется к fill_value который по умолчанию np.nan.

    In [7]: pd.SparseSeries([1., np.nan, 2., np.nan], fill_value=np.nan).astype(np.int64)
    Out[7]:
    ValueError: unable to coerce current fill_value nan to int64 dtype
    

    Другие исправления для разреженных данных#

    • Подкласс SparseDataFrame и SparseSeries теперь сохраняет типы классов при срезе или транспонировании. (GH 13787)

    • SparseArray с bool dtype теперь поддерживает логические (bool) операторы (GH 14000)

    • Ошибка в SparseSeries с MultiIndex [] индексирование может вызвать IndexError (GH 13144)

    • Ошибка в SparseSeries с MultiIndex [] результат индексации может иметь нормальный Index (GH 13144)

    • Ошибка в SparseDataFrame в котором axis=None не использовал по умолчанию axis=0 (GH 13048)

    • Ошибка в SparseSeries и SparseDataFrame создание с object тип данных может вызывать TypeError (GH 11633)

    • Ошибка в SparseDataFrame не учитывает переданный SparseArray или SparseSeries тип данных и fill_value (GH 13866)

    • Ошибка в SparseArray и SparseSeries не применяйте ufunc к fill_value (GH 13853)

    • Ошибка в SparseSeries.abs неправильно сохраняет отрицательные fill_value (GH 13853)

    • Ошибка в срезе одной строки для мультитипа SparseDataFrame s, типы ранее принудительно преобразовывались в float (GH 13917)

    • Ошибка в SparseSeries срезы изменяют целочисленный тип данных на float (GH 8292)

    • Ошибка в SparseDataFarme операции сравнения могут вызывать TypeError (GH 13001)

    • Ошибка в SparseDataFarme.isnull вызывает ValueError (GH 8276)

    • Ошибка в SparseSeries представление с bool тип данных может вызывать IndexError (GH 13110)

    • Ошибка в SparseSeries и SparseDataFrame of bool или int64 dtype может отображать свои значения как float64 тип данных (GH 13110)

    • Ошибка в разреженном индексировании с использованием SparseArray с bool dtype может возвращать неверный результат (GH 13985)

    • Ошибка в SparseArray созданный из SparseSeries может потерять dtype (GH 13999)

    • Ошибка в SparseSeries сравнение с dense возвращает нормальный Series вместо SparseSeries (GH 13999)

    Изменения типа данных индексатора#

    Примечание

    Это изменение затрагивает только 64-битный Python, работающий на Windows, и только относительно сложные операции индексирования

    Методы, такие как Index.get_indexer которые возвращают массив индексатора, приводят этот массив к "платформенному целому числу", чтобы его можно было непосредственно использовать в операциях сторонних библиотек, таких как numpy.take. Ранее платформенный int определялся как np.int_ что соответствует целому числу C, но правильный тип, и тот, который используется сейчас, это np.intp, что соответствует размеру целого числа C, который может содержать указатель (GH 3033, GH 13972).

    Эти типы одинаковы на многих платформах, но для 64-битного Python на Windows, np.int_ составляет 32 бита, и np.intp составляет 64 бита. Изменение этого поведения улучшает производительность для многих операций на этой платформе.

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

    In [1]: i = pd.Index(['a', 'b', 'c'])
    
    In [2]: i.get_indexer(['b', 'b', 'c']).dtype
    Out[2]: dtype('int32')
    

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

    In [1]: i = pd.Index(['a', 'b', 'c'])
    
    In [2]: i.get_indexer(['b', 'b', 'c']).dtype
    Out[2]: dtype('int64')
    

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

    • Timestamp.to_pydatetime выдаст UserWarning когда warn=True, и экземпляр имеет ненулевое количество наносекунд, ранее это выводило сообщение в stdout (GH 14101).

    • Series.unique() с datetime и часовым поясом теперь возвращает массив Timestamp с часовым поясом (GH 13565).

    • Panel.to_sparse() вызовет NotImplementedError исключение при вызове (GH 13778).

    • Index.reshape() вызовет NotImplementedError исключение при вызове (GH 12882).

    • .filter() обеспечивает взаимное исключение аргументов ключевых слов (GH 12399).

    • evalправила повышения типа данных для float32 типы были обновлены для большей согласованности с правилами NumPy. Новое поведение не будет повышать тип до float64 если умножить pandas float32 объект на скаляр float64 (GH 12388).

    • An UnsupportedFunctionCall теперь вызывается ошибка, если функции NumPy, такие как np.mean вызываются на объектах groupby или resample (GH 12811).

    • __setitem__ больше не будет применять вызываемый rhs как функцию вместо его сохранения. Вызовите where напрямую для получения предыдущего поведения (GH 13299).

    • Вызовы .sample() будет учитывать случайное зерно, установленное через numpy.random.seed(n) (GH 13161)

    • Styler.apply теперь более строг к выводам, которые должна возвращать ваша функция. Для axis=0 или axis=1форма вывода должна быть идентичной. Для axis=None, вывод должен быть DataFrame с идентичными столбцами и метками индекса (GH 13222).

    • Float64Index.astype(int) теперь будет вызывать ValueError if Float64Index содержит NaN значения (GH 13149)

    • TimedeltaIndex.astype(int) и DatetimeIndex.astype(int) теперь вернет Int64Index вместо np.array (GH 13209)

    • Передача Period с несколькими частотами в обычный Index теперь возвращает Index с object тип данных (GH 13664)

    • PeriodIndex.fillna с Period имеет другую частоту, теперь приводится к object тип данных (GH 13664)

    • Фасетные boxplot из DataFrame.boxplot(by=col) теперь возвращает Series когда return_type не является None. Ранее они возвращали OrderedDict. Обратите внимание, что когда return_type=None, по умолчанию, они всё равно возвращают 2-D массив NumPy (GH 12216, GH 7096).

    • pd.read_hdf теперь вызовет ValueError вместо KeyError, если режим отличен от r, r+ и a предоставляется. (GH 13623)

    • pd.read_csv(), pd.read_table(), и pd.read_hdf() вызвать встроенное FileNotFoundError исключение для Python 3.x при вызове на несуществующем файле; это обратно портировано как IOError в Python 2.x (GH 14086)

    • Более информативные исключения передаются через csv-парсер. Тип исключения теперь будет исходным типом исключения вместо CParserError (GH 13652).

    • pd.read_csv() в движке C теперь будет выдавать ParserWarning или вызвать ValueError когда sep закодировано более чем одним символом (GH 14065)

    • DataFrame.values теперь вернет float64 с DataFrame смешанных int64 и uint64 типы данных, соответствующие np.find_common_type (GH 10364, GH 13917)

    • .groupby.groups теперь вернет словарь Index объектов, а не словарь np.ndarray или lists (GH 14293)

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

    • Series.reshape и Categorical.reshape были устаревшими и будут удалены в последующем выпуске (GH 12882, GH 12882)

    • PeriodIndex.to_datetime был объявлен устаревшим в пользу PeriodIndex.to_timestamp (GH 8254)

    • Timestamp.to_datetime был объявлен устаревшим в пользу Timestamp.to_pydatetime (GH 8254)

    • Index.to_datetime и DatetimeIndex.to_datetime устарели в пользу pd.to_datetime (GH 8254)

    • pandas.core.datetools модуль устарел и будет удален в последующем выпуске (GH 14094)

    • SparseList устарел и будет удален в будущей версии (GH 13784)

    • DataFrame.to_html() и DataFrame.to_latex() удалили colSpace параметр в пользу col_space (GH 13857)

    • DataFrame.to_sql() устарел flavor параметр, так как он избыточен, когда SQLAlchemy не установлен (GH 13611)

    • Устаревший read_csv ключевые слова:

      • compact_ints и use_unsigned были устаревшими и будут удалены в будущей версии (GH 13320)

      • buffer_lines устарел и будет удален в будущей версии (GH 13360)

      • as_recarray устарел и будет удален в будущей версии (GH 13373)

      • skip_footer был объявлен устаревшим в пользу skipfooter и будет удалена в будущей версии (GH 13349)

    • верхний уровень pd.ordered_merge() был переименован в pd.merge_ordered() и исходное имя будет удалено в будущей версии (GH 13358)

    • Timestamp.offset свойства (и именованного аргумента в конструкторе), устарели в пользу freq (GH 12160)

    • pd.tseries.util.pivot_annual устарел. Используйте pivot_table в качестве альтернативы, примером является здесь (GH 736)

    • pd.tseries.util.isleapyear был устаревшим и будет удален в последующем выпуске. Объекты, подобные дате и времени, теперь имеют .is_leap_year свойство (GH 13727)

    • Panel4D и PanelND Конструкторы устарели и будут удалены в будущей версии. Рекомендуемый способ представления этих типов n-мерных данных - с помощью пакет xarray. pandas предоставляет to_xarray() метод для автоматизации этого преобразования (GH 13564).

    • pandas.tseries.frequencies.get_standard_freq устарел. Используйте pandas.tseries.frequencies.to_offset(freq).rule_code вместо (GH 13874)

    • pandas.tseries.frequencies.to_offset’s freqstr ключевое слово устарело в пользу freq (GH 13874)

    • Categorical.from_array устарел и будет удален в будущей версии (GH 13854)

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

    • The SparsePanel класс был удален (GH 13778)

    • The pd.sandbox модуль был удалён в пользу внешней библиотеки pandas-qt (GH 13670)

    • The pandas.io.data и pandas.io.wb модули удалены в пользу пакет pandas-datareader (GH 13724).

    • The pandas.tools.rplot модуль был удален в пользу пакет seaborn (GH 13855)

    • DataFrame.to_csv() удалил engine параметра, который был объявлен устаревшим в версии 0.17.1 (GH 11274, GH 13419)

    • DataFrame.to_dict() удалил outtype параметр в пользу orient (GH 13627, 0.170972)

    • pd.Categorical прекратило установку ordered атрибут напрямую в пользу set_ordered метод (GH 13671)

    • pd.Categorical удалил levels атрибут в пользу categories (GH 8376)

    • DataFrame.to_sql() удалил mysql опция для flavor параметр (GH 13611)

    • Panel.shift() удалил lags параметр в пользу periods (GH 14041)

    • pd.Index удалил diff метод в пользу difference (GH 13669)

    • pd.DataFrame удалил to_wide метод в пользу to_panel (GH 14039)

    • Series.to_csv удалил nanRep параметр в пользу na_rep (GH 13804)

    • Series.xs, DataFrame.xs, Panel.xs, Panel.major_xs, и Panel.minor_xs удалили copy параметр (GH 13781)

    • str.split удалил return_type параметр в пользу expand (GH 13701)

    • Удаление устаревших временных правил (псевдонимов смещений), устаревших с версии 0.17.0 (это было псевдонимом с версии 0.8.0) (GH 13590, GH 13868). Теперь устаревшие правила времени вызывают ValueError. Для списка поддерживаемых смещений см. здесь.

    • Значение по умолчанию для return_type параметр для DataFrame.plot.box и DataFrame.boxplot изменено с None to "axes". Эти методы теперь по умолчанию возвращают объект matplotlib axes вместо словаря художников. См. здесь (GH 6581).

    • The tquery и uquery функции в pandas.io.sql модуль удалены (GH 5950).

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

    • Улучшена производительность разреженных IntIndex.intersect (GH 13082)

    • Улучшена производительность разреженной арифметики с BlockIndex когда количество блоков велико, хотя рекомендуется использовать IntIndex в таких случаях (GH 13082)

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

    • Улучшена производительность операций с хэш-таблицами float64, исправлены некоторые очень медленные операции индексирования и группировки в python 3 (GH 13166, GH 13334)

    • Улучшена производительность DataFrameGroupBy.transform (GH 12737)

    • Улучшена производительность Index и Series .duplicated (GH 10235)

    • Улучшена производительность Index.difference (GH 12044)

    • Улучшена производительность RangeIndex.is_monotonic_increasing и is_monotonic_decreasing (GH 13749)

    • Улучшена производительность разбора строк даты и времени в DatetimeIndex (GH 13692)

    • Улучшенная производительность хеширования Period (GH 12817)

    • Улучшена производительность factorize datetime с часовым поясом (GH 13750)

    • Улучшена производительность за счёт ленивого создания хэш-таблиц индексирования для больших индексов (GH 14266)

    • Улучшена производительность groupby.groups (GH 14293)

    • Ненужное материализование MultiIndex при интроспекции использования памяти (GH 14308)

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

    • Ошибка в groupby().shift(), что могло вызвать ошибку сегментации или повреждение в редких случаях при группировке по столбцам с пропущенными значениями (GH 13813)

    • Ошибка в groupby().cumsum() вычисление cumprod когда axis=1. (GH 13994)

    • Ошибка в pd.to_timedelta() в котором errors параметр не учитывался (GH 13613)

    • Ошибка в io.json.json_normalize(), где не-ASCII ключи вызывали исключение (GH 13213)

    • Ошибка при передаче временного ряда с нестандартным индексом Series как xerr или yerr в .plot() (GH 11858)

    • Ошибка в построении графика area: легенда рисуется некорректно, если включен подграфик или легенда перемещена после построения (требуется matplotlib 1.5.0 для правильного отображения легенды графика area) (GH 9161, GH 13544)

    • Ошибка в DataFrame присваивание с объектным типом данных Index где результирующий столбец изменяем для исходного объекта. (GH 13522)

    • Ошибка в matplotlib AutoDataFormatter; это восстанавливает второе масштабированное форматирование и повторно добавляет микросекундное масштабированное форматирование (GH 13131)

    • Ошибка при выборе из HDFStore с фиксированным форматом и start и/или stop указанный теперь вернет выбранный диапазон (GH 8287)

    • Ошибка в Categorical.from_codes() где возникала бесполезная ошибка при недопустимом ordered параметр был передан (GH 14058)

    • Ошибка в Series создание из кортежа целых чисел в Windows не возвращает тип данных по умолчанию (int64) (GH 13646)

    • Ошибка в TimedeltaIndex сложение с объектом типа Datetime, где переполнение при сложении не перехватывалось (GH 14068)

    • Ошибка в .groupby(..).resample(..) когда один и тот же объект вызывается несколько раз (GH 13174)

    • Ошибка в .to_records() когда имя индекса является строкой Unicode (GH 13172)

    • Ошибка при вызове .memory_usage() на объекте, который не реализует (GH 12924)

    • Регрессия в Series.quantile с nan (также появляется в .median() и .describe() ); кроме того, теперь называет Series с квантилем (GH 13098, GH 13146)

    • Ошибка в SeriesGroupBy.transform со значениями datetime и отсутствующими группами (GH 13191)

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

    • Ошибка в Categorical конструктору при передаче Categorical содержащие даты и время с часовыми поясами (GH 14190)

    • Ошибка в Series.str.extractall() с str индекс вызывает ValueError (GH 13156)

    • Ошибка в Series.str.extractall() с одной группой и квантификатором (GH 13382)

    • Ошибка в DatetimeIndex и Period вычитание вызывает ValueError или AttributeError вместо TypeError (GH 13078)

    • Ошибка в Index и Series создан с помощью NaN и NaT смешанные данные могут не иметь datetime64 dtype (GH 13324)

    • Ошибка в Index и Series может игнорировать np.datetime64('nat') и np.timdelta64('nat') для определения типа данных (GH 13324)

    • Ошибка в PeriodIndex и Period вычитание вызывает AttributeError (GH 13071)

    • Ошибка в PeriodIndex конструкция, возвращающая float64 индекс в некоторых обстоятельствах (GH 13067)

    • Ошибка в .resample(..) с PeriodIndex не изменяя его freq соответствующим образом, когда пусто (GH 13067)

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

    • Ошибка в groupby(..).apply(..) когда переданная функция возвращает скалярные значения для каждой группы (GH 13468).

    • Ошибка в groupby(..).resample(..) где передача некоторых ключевых слов вызовет исключение (GH 13235)

    • Ошибка в .tz_convert для объектов с информацией о часовом поясе DateTimeIndex который полагался на отсортированный индекс для корректных результатов (GH 13306)

    • Ошибка в .tz_localize с dateutil.tz.tzlocal может возвращать некорректный результат (GH 13583)

    • Ошибка в DatetimeTZDtype dtype с dateutil.tz.tzlocal не может считаться допустимым dtype (GH 13583)

    • Ошибка в pd.read_hdf() где попытка загрузить HDF-файл с одним набором данных, содержащим один или несколько категориальных столбцов, завершалась неудачей, если аргумент key не был установлен в имя набора данных. (GH 13231)

    • Ошибка в .rolling() который позволял использовать отрицательное целое окно при построении Rolling() объект, но позже завершится ошибкой при агрегации (GH 13383)

    • Ошибка в Series индексирование с данными в виде кортежей и числовым индексом (GH 13509)

    • Ошибка при печати pd.DataFrame где необычные элементы с object dtype вызывали ошибки сегментации (GH 13717)

    • Ошибка в ранжировании Series что могло привести к ошибкам сегментации (GH 13445)

    • Ошибка в различных типах индексов, которые не передавали имя переданного индекса (GH 12309)

    • Ошибка в DatetimeIndex, который не учитывал copy=True (GH 13205)

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

    • Ошибка в pd.concat и .append может приводить к преобразованию типов datetime64 и timedelta to object тип данных, содержащий встроенные объекты Python datetime или timedelta вместо Timestamp или Timedelta (GH 13626)

    • Ошибка в PeriodIndex.append может вызывать AttributeError когда результат object тип данных (GH 13221)

    • Ошибка в CategoricalIndex.append может принимать обычные list (GH 13626)

    • Ошибка в pd.concat и .append с тем же часовым поясом сбрасываются в UTC (GH 7795)

    • Ошибка в Series и DataFrame .append вызывает AmbiguousTimeError если данные содержат дату и время около границы перехода на летнее время (GH 13626)

    • Ошибка в DataFrame.to_csv() в котором значения с плавающей точкой заключались в кавычки, хотя кавычки были указаны только для нечисловых значений (GH 12922, GH 13259)

    • Ошибка в DataFrame.describe() вызов ValueError только с булевыми столбцами (GH 13898)

    • Ошибка в MultiIndex срезы, где возвращались лишние элементы, когда уровень не уникален (GH 12896)

    • Ошибка в .str.replace не вызывает TypeError для недопустимой замены (GH 13438)

    • Ошибка в MultiIndex.from_arrays который не проверял соответствие длин входных массивов (GH 13599)

    • Ошибка в cartesian_product и MultiIndex.from_product что может вызвать ошибку с пустыми входными массивами (GH 12258)

    • Ошибка в pd.read_csv() что может вызвать ошибку сегментации или повреждение при итерации большими блоками по потоку/файлу в редких обстоятельствах (GH 13703)

    • Ошибка в pd.read_csv() что вызывало ошибки при передаче словаря, содержащего скаляры, для na_values (GH 12224)

    • Ошибка в pd.read_csv() что приводило к некорректному парсингу файлов BOM из-за игнорирования BOM (GH 4793)

    • Ошибка в pd.read_csv() с engine='python' который вызывал ошибки, когда передавался массив numpy для usecols (GH 12546)

    • Ошибка в pd.read_csv() где столбцы индекса неправильно парсились при парсинге как даты с thousands параметр (GH 14066)

    • Ошибка в pd.read_csv() с engine='python' в котором NaN значения не обнаруживались после преобразования данных в числовые значения (GH 13314)

    • Ошибка в pd.read_csv() в котором nrows аргумент не был должным образом проверен для обоих движков (GH 10476)

    • Ошибка в pd.read_csv() с engine='python' в котором бесконечности смешанного регистра не интерпретировались правильно (GH 13274)

    • Ошибка в pd.read_csv() с engine='python' в котором завершающие NaN значения не парсились (GH 13320)

    • Ошибка в pd.read_csv() с engine='python' при чтении из tempfile.TemporaryFile в Windows с Python 3 (GH 13398)

    • Ошибка в pd.read_csv() что предотвращает usecols kwarg больше не принимает однобайтовые строки Unicode (GH 13219)

    • Ошибка в pd.read_csv() что предотвращает usecols от того, чтобы быть пустым множеством (GH 13402)

    • Ошибка в pd.read_csv() в движке C, где символ NULL не парсился как NULL (GH 14012)

    • Ошибка в pd.read_csv() с engine='c' в котором NULL quotechar не принимался, хотя quoting был указан как None (GH 13411)

    • Ошибка в pd.read_csv() с engine='c' в котором поля не были правильно приведены к float, когда кавычки указывались как нечисловые (GH 13411)

    • Ошибка в pd.read_csv() в Python 2.x с данными, закодированными не в UTF8, разделенными несколькими символами (GH 3404)

    • Ошибка в pd.read_csv(), где псевдонимы для utf-xx (например, UTF-xx, UTF_xx, utf_xx) вызывали UnicodeDecodeError (GH 13549)

    • Ошибка в pd.read_csv, pd.read_table, pd.read_fwf, pd.read_stata и pd.read_sas где файлы были открыты парсерами, но не закрыты, если оба chunksize и iterator были None. (GH 13940)

    • Ошибка в StataReader, StataWriter, XportReader и SAS7BDATReader где файл не был правильно закрыт при возникновении ошибки. (GH 13940)

    • Ошибка в pd.pivot_table() где margins_name игнорируется, когда aggfunc является списком (GH 13354)

    • Ошибка в pd.Series.str.zfill, center, ljust, rjust, и pad при передаче нецелых чисел не вызывал TypeError (GH 13598)

    • Ошибка при проверке наличия нулевых объектов в TimedeltaIndex, который всегда возвращал True (GH 13603)

    • Ошибка в Series арифметические операции вызывают TypeError если оно содержит дату-время как object тип данных (GH 13043)

    • Ошибка Series.isnull() и Series.notnull() ignore Period('NaT') (GH 13737)

    • Ошибка Series.fillna() и Series.dropna() не влияют на Period('NaT') (GH 13737

    • Ошибка в .fillna(value=np.nan) неправильно вызывает KeyError на category типизированный Series (GH 14021)

    • Ошибка при создании типа данных расширения, где созданные типы не были is/идентичными (GH 13285)

    • Ошибка в .resample(..) где некорректные предупреждения были вызваны интроспекцией IPython (GH 13618)

    • Ошибка в NaT - Period вызывает AttributeError (GH 13071)

    • Ошибка в Series сравнение может выдать некорректный результат, если правая часть содержит NaT (GH 9005)

    • Ошибка в Series и Index сравнение может выдать некорректный результат, если содержит NaT с object тип данных (GH 13592)

    • Ошибка в Period сложение вызывает TypeError if Period находится в правой части (GH 13069)

    • Ошибка в Period и Series или Index сравнение вызывает TypeError (GH 13200)

    • Ошибка в pd.set_eng_float_format() что предотвращало форматирование NaN и Inf (GH 11981)

    • Ошибка в .unstack с Categorical сброс dtype .ordered to True (GH 13249)

    • Очистка некоторых предупреждений времени компиляции при парсинге даты и времени (GH 13607)

    • Ошибка в factorize вызывает AmbiguousTimeError если данные содержат дату и время около границы перехода на летнее время (GH 13750)

    • Ошибка в .set_index вызывает AmbiguousTimeError если новый индекс содержит границу перехода на летнее время и несколько уровней (GH 12920)

    • Ошибка в .shift вызывает AmbiguousTimeError если данные содержат дату и время около границы перехода на летнее время (GH 13926)

    • Ошибка в pd.read_hdf() возвращает некорректный результат, когда DataFrame с categorical столбец и запрос, который не соответствует ни одному значению (GH 13792)

    • Ошибка в .iloc при индексации с не лексически отсортированным MultiIndex (GH 13797)

    • Ошибка в .loc при индексировании строк дат в обратно отсортированном DatetimeIndex (GH 14316)

    • Ошибка в Series операторы сравнения при работе с нульмерными массивами NumPy (GH 13006)

    • Ошибка в .combine_first может возвращать некорректный dtype (GH 7630, GH 10567)

    • Ошибка в groupby где apply возвращает разный результат в зависимости от того, является ли первый результат None или нет (GH 12824)

    • Ошибка в groupby(..).nth() где групповой ключ включается непоследовательно, если вызывается после .head()/.tail() (GH 12839)

    • Ошибка в .to_html, .to_latex и .to_string молча игнорирует пользовательский форматтер даты и времени, переданный через formatters ключевое слово (GH 10690)

    • Ошибка в DataFrame.iterrows(), не давая Series подкласс, если определен (GH 13977)

    • Ошибка в pd.to_numeric когда errors='coerce' и вход содержит нехешируемые объекты (GH 13324)

    • Ошибка в недопустимом Timedelta арифметические и сравнительные операции могут вызывать ValueError вместо TypeError (GH 13624)

    • Ошибка в некорректном парсинге даты и времени в to_datetime и DatetimeIndex может вызывать TypeError вместо ValueError (GH 11169, GH 11287)

    • Ошибка в Index создан с учетом часового пояса Timestamp и несоответствующие tz опция некорректно преобразует часовой пояс (GH 13692)

    • Ошибка в DatetimeIndex с наносекундной частотой не включает временную метку, указанную с end (GH 13672)

    • Ошибка в Series при установке среза с np.timedelta64 (GH 14155)

    • Ошибка в Index вызывает OutOfBoundsDatetime if datetime превышает datetime64[ns] границы, а не принудительное преобразование к object тип данных (GH 13663)

    • Ошибка в Index может игнорировать указанный datetime64 или timedelta64 передан как dtype (GH 13981)

    • Ошибка в RangeIndex может быть создан без аргументов, а не вызывает ошибку TypeError (GH 13793)

    • Ошибка в .value_counts() вызывает OutOfBoundsDatetime если данные превышают datetime64[ns] bounds (GH 13663)

    • Ошибка в DatetimeIndex может вызывать OutOfBoundsDatetime если входные данные np.datetime64 имеет другую единицу измерения, чем ns (GH 9114)

    • Ошибка в Series создание с np.datetime64 который имеет другую единицу измерения, чем ns как object dtype приводит к некорректным значениям (GH 13876)

    • Ошибка в resample с данными timedelta, где данные были приведены к типу float (GH 13119).

    • Ошибка в pd.isnull() pd.notnull() raise TypeError если входные данные datetime-like имеют другую единицу измерения, чем ns (GH 13389)

    • Ошибка в pd.merge() может вызывать TypeError если входные данные datetime-like имеют другую единицу измерения, чем ns (GH 13389)

    • Ошибка в HDFStore/read_hdf() отброшен DatetimeIndex.name if tz был установлен (GH 13884)

    • Ошибка в Categorical.remove_unused_categories() изменения .codes dtype в платформенный int (GH 13261)

    • Ошибка в groupby с as_index=False возвращает все NaN при группировке по нескольким столбцам, включая категориальный (GH 13204)

    • Ошибка в df.groupby(...)[...] где использование getitem с Int64Index вызывало ошибку (GH 13731)

    • Ошибка в CSS-классах, назначенных DataFrame.style для имен индексов. Ранее они назначались "col_heading level col" где n было количество уровней + 1. Теперь они назначаются "index_name level", где n является правильным уровнем для этого MultiIndex.

    • Ошибка, где pd.read_gbq() могло вызывать ImportError: No module named discovery в результате конфликта имен с другим пакетом Python под названием apiclient (GH 13454)

    • Ошибка в Index.union возвращает некорректный результат с именованным пустым индексом (GH 13432)

    • Ошибки в Index.difference и DataFrame.join вызов исключения в Python3 при использовании смешанных целочисленных индексов (GH 13432, GH 12814)

    • Ошибка в вычитании с учетом часового пояса datetime.datetime из данных с учетом часового пояса datetime64 серия (GH 14088)

    • Ошибка в .to_excel() когда DataFrame содержит MultiIndex, который содержит метку со значением NaN (GH 13511)

    • Ошибка в недопустимой строке смещения частоты, такой как "D1", "-2-3H", может не вызывать ValueError (GH 13930)

    • Ошибка в concat и groupby для иерархических фреймов с RangeIndex уровни (GH 13542).

    • Ошибка в Series.str.contains() для Series, содержащих только NaN значения object тип данных (GH 14171)

    • Ошибка в agg() функция на группированном датафрейме изменяет тип данных datetime64[ns] столбец в float64 (GH 12821)

    • Ошибка при использовании NumPy ufunc с PeriodIndex для добавления или вычитания целого числа вызывает IncompatibleFrequency. Обратите внимание, что использование стандартных операторов, таких как + или - рекомендуется, потому что стандартные операторы используют более эффективный путь (GH 13980)

    • Ошибка в операциях над NaT возвращая float вместо datetime64[ns] (GH 12941)

    • Ошибка в Series гибкие арифметические методы (например .add()) вызывает ValueError когда axis=None (GH 13894)

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

    • Ошибка в DatetimeIndex, TimedeltaIndex и PeriodIndex.equals() может возвращать True когда входные данные не Index но содержит те же значения (GH 13107)

    • Ошибка в присвоении для datetime с часовым поясом может не работать, если оно содержит datetime около границы перехода на летнее время (GH 14146)

    • Ошибка в pd.eval() и HDFStore запрос обрезает длинные литералы с плавающей точкой в python 2 (GH 14241)

    • Ошибка в Index вызывает KeyError отображение некорректного столбца, когда столбец не в df и столбцы содержат дублирующиеся значения (GH 13822)

    • Ошибка в Period и PeriodIndex создание неправильных дат, когда частота имеет комбинированные псевдонимы смещений (GH 13874)

    • Ошибка в .to_string() при вызове с целым числом line_width и index=False вызывает исключение UnboundLocalError, потому что idx ссылка до присваивания.

    • Ошибка в eval() где resolvers аргумент не принимал список (GH 14095)

    • Ошибки в stack, get_dummies, make_axis_dummies которые не сохраняют категориальные типы данных в (много)индексах (GH 13854)

    • PeriodIndex теперь может принимать list и array который содержит pd.NaT (GH 13430)

    • Ошибка в df.groupby где .median() возвращает произвольные значения, если сгруппированный датафрейм содержит пустые бины (GH 13629)

    • Ошибка в Index.copy() где name параметр игнорировался (GH 14302)

    Участники#

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

    • Adrien Emery +

    • Alex Alekseyev

    • Alex Vig +

    • Allen Riddell +

    • Amol +

    • Amol Agrawal +

    • Andy R. Terrel +

    • Anthonios Partheniou

    • Бен Кандел +

    • Боб Баксли +

    • Brett Rosen +

    • Camilo Cota +

    • Chris

    • Chris Grinolds

    • Chris Warth

    • Christian Hudon

    • Christopher C. Aycock

    • Daniel Siladji +

    • Дуглас МакНил

    • Дрюри Лутон +

    • Eduardo Blancas Reyes +

    • Elliot Marsden +

    • Evan Wright

    • Felix Marczinowski +

    • Фрэнсис Т. О’Донован

    • Geraint Duck +

    • Giacomo Ferroni +

    • Грант Роч +

    • Gábor Lipták

    • Haleemur Ali +

    • Hassan Shamim +

    • Iulius Curt +

    • Иван Назаров +

    • Jeff Reback

    • Jeffrey Gerard +

    • Jenn Olsen +

    • Jim Crist

    • Joe Jevnik

    • John Evans +

    • John Freeman

    • John Liekezer +

    • John W. O’Brien

    • John Zwinck +

    • Johnny Gill +

    • Jordan Erenrich +

    • Joris Van den Bossche

    • Josh Howes +

    • Jozef Brandys +

    • Ka Wo Chen

    • Камиль Синди +

    • Керби Шедден

    • Kernc +

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

    • Маттье Брюше +

    • Maximilian Roos

    • Michael Scherer +

    • Mike Graham +

    • Mortada Mehyar

    • Muhammad Haseeb Tariq +

    • Nate George +

    • Neil Parley +

    • Nicolas Bonnotte

    • OXPHOS

    • Pan Deng / Zora +

    • Paul +

    • Paul Mestemaker +

    • Pauli Virtanen

    • Pawel Kordek +

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

    • Пётр Юха +

    • Ravi Kumar Nimmi +

    • Robert Gieseke

    • Роберт Керн +

    • Roger Thomas

    • Roy Keyes +

    • Russell Smith +

    • Сахил Дуа +

    • Санджив Лобо +

    • Sašo Stanovnik +

    • Shawn Heide +

    • Sinhrks

    • Stephen Kappel +

    • Стив Чой +

    • Stewart Henderson +

    • Sudarshan Konge +

    • Thomas A Caswell

    • Tom Augspurger

    • Tom Bird +

    • Uwe Hoffmann +

    • WillAyd +

    • Xiang Zhang +

    • YG-Riku +

    • Yadunandan +

    • Yaroslav Halchenko

    • Юичиро Канэко +

    • adneu

    • agraboso +

    • babakkeyvani +

    • c123w +

    • chris-b1

    • cmazzullo +

    • conquistador1492 +

    • cr3 +

    • dsm054

    • gfyoung

    • harshul1610 +

    • iamsimha +

    • jackieleng +

    • mpuels +

    • pijucha +

    • priyankjain +

    • sinhrks

    • wcwagner +

    • yui-knk +

    • zhangjinjie +

    • znmean +

    • Янь Фацай (Yan Facai) +