Версия 0.18.0 (13 марта 2016)#

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

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

pandas >= 0.18.0 больше не поддерживает совместимость с версиями Python 2.6 и 3.3 (GH 7718, GH 11273)

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

numexpr версия 2.4.4 теперь будет показывать предупреждение и не будет использоваться в качестве вычислительного бэкенда для pandas из-за некоторого ошибочного поведения. Это не затрагивает другие версии (>= 2.1 и >= 2.4.6). (GH 12489)

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

  • Функции скользящего и расширяющегося окон теперь являются методами Series и DataFrame, аналогично .groupby, см. здесь.

  • Добавлена поддержка RangeIndex как специализированная форма Int64Index для экономии памяти, см. здесь.

  • Изменение API, нарушающее обратную совместимость, для .resample метод, чтобы сделать его более .groupby например, см. здесь.

  • Удаление поддержки позиционного индексирования с плавающими числами, которое было устаревшим с версии 0.14.0. Теперь это будет вызывать TypeError, см. здесь.

  • The .to_xarray() функция была добавлена для совместимости с пакет xarray, см. здесь.

  • The read_sas функция была улучшена для чтения sas7bdat файлы, см. здесь.

  • Добавление метод .str.extractall(), и изменения API в метод .str.extract() и метод .str.cat().

  • pd.test() доступен тестовый раннер верхнего уровня nose (GH 4327).

Проверьте Изменения API и устаревшие возможности перед обновлением.

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

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

Оконные функции были переработаны в методы на Series/DataFrame объектов, а не функций верхнего уровня, которые теперь устарели. Это позволяет этим функциям оконного типа иметь API, аналогичный API .groupby. См. полную документацию здесь (GH 11603, GH 12373)

In [1]: np.random.seed(1234)

In [2]: df = pd.DataFrame({'A': range(10), 'B': np.random.randn(10)})

In [3]: df
Out[3]: 
   A         B
0  0  0.471435
1  1 -1.190976
2  2  1.432707
3  3 -0.312652
4  4 -0.720589
5  5  0.887163
6  6  0.859588
7  7 -0.636524
8  8  0.015696
9  9 -2.242685

[10 rows x 2 columns]

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

In [8]: pd.rolling_mean(df, window=3)
        FutureWarning: pd.rolling_mean is deprecated for DataFrame and will be removed in a future version, replace with
                       DataFrame.rolling(window=3,center=False).mean()
Out[8]:
    A         B
0 NaN       NaN
1 NaN       NaN
2   1  0.237722
3   2 -0.023640
4   3  0.133155
5   4 -0.048693
6   5  0.342054
7   6  0.370076
8   7  0.079587
9   8 -0.954504

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

In [4]: r = df.rolling(window=3)

Они показывают описательное представление

In [5]: r
Out[5]: Rolling [window=3,center=False,axis=0,method=single]

с автодополнением доступных методов и свойств.

In [9]: r.<TAB>  # noqa E225, E999
r.A           r.agg         r.apply       r.count       r.exclusions  r.max         r.median      r.name        r.skew        r.sum
r.B           r.aggregate   r.corr        r.cov         r.kurt        r.mean        r.min         r.quantile    r.std         r.var

Методы работают с Rolling сам объект

In [6]: r.mean()
Out[6]: 
     A         B
0  NaN       NaN
1  NaN       NaN
2  1.0  0.237722
3  2.0 -0.023640
4  3.0  0.133155
5  4.0 -0.048693
6  5.0  0.342054
7  6.0  0.370076
8  7.0  0.079587
9  8.0 -0.954504

[10 rows x 2 columns]

Они предоставляют доступ через getitem

In [7]: r['A'].mean()
Out[7]: 
0    NaN
1    NaN
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    6.0
8    7.0
9    8.0
Name: A, Length: 10, dtype: float64

И множественные агрегации

In [8]: r.agg({'A': ['mean', 'std'],
   ...:        'B': ['mean', 'std']})
   ...: 
Out[8]: 
     A              B          
  mean  std      mean       std
0  NaN  NaN       NaN       NaN
1  NaN  NaN       NaN       NaN
2  1.0  1.0  0.237722  1.327364
3  2.0  1.0 -0.023640  1.335505
4  3.0  1.0  0.133155  1.143778
5  4.0  1.0 -0.048693  0.835747
6  5.0  1.0  0.342054  0.920379
7  6.0  1.0  0.370076  0.871850
8  7.0  1.0  0.079587  0.750099
9  8.0  1.0 -0.954504  1.162285

[10 rows x 4 columns]

Изменения для переименования#

Series.rename и NDFrame.rename_axis теперь может принимать скалярное или list-like значение для изменения Series или оси имя, в дополнение к их старому поведению изменения меток. (GH 9494, GH 11965)

In [9]: s = pd.Series(np.random.randn(5))

In [10]: s.rename('newname')
Out[10]: 
0    1.150036
1    0.991946
2    0.953324
3   -2.021255
4   -0.334077
Name: newname, Length: 5, dtype: float64
In [11]: df = pd.DataFrame(np.random.randn(5, 2))

In [12]: (df.rename_axis("indexname")
   ....:    .rename_axis("columns_name", axis="columns"))
   ....: 
Out[12]: 
columns_name         0         1
indexname                       
0             0.002118  0.405453
1             0.289092  1.321158
2            -1.546906 -0.202646
3            -0.655969  0.193421
4             0.553439  1.318152

[5 rows x 2 columns]

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

Range Index#

A RangeIndex был добавлен в Int64Index подклассы для поддержки альтернативы, экономящей память, для распространенных случаев использования. Это имеет аналогичную реализацию с python range объект (xrange в python 2), в том смысле, что он хранит только начальное, конечное и шаговое значения для индекса. Он будет прозрачно взаимодействовать с пользовательским API, преобразуясь в Int64Index при необходимости.

Теперь это будет индекс по умолчанию для NDFrame объекты, а не предыдущий Int64Index. (GH 939, GH 12070, GH 12071, GH 12109, GH 12888)

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

In [3]: s = pd.Series(range(1000))

In [4]: s.index
Out[4]:
Int64Index([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
            ...
            990, 991, 992, 993, 994, 995, 996, 997, 998, 999], dtype='int64', length=1000)

In [6]: s.index.nbytes
Out[6]: 8000

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

In [13]: s = pd.Series(range(1000))

In [14]: s.index
Out[14]: RangeIndex(start=0, stop=1000, step=1)

In [15]: s.index.nbytes
Out[15]: 128

Изменения в str.extract#

The .str.extract метод принимает регулярное выражение с группами захвата, находит первое совпадение в каждой строке-субъекте и возвращает содержимое групп захватаGH 11386).

В версии 0.18.0, expand аргумент был добавлен в extract.

  • expand=False: возвращает Series, Index, или DataFrame, в зависимости от объекта и шаблона регулярного выражения (то же поведение, что и до версии 0.18.0).

  • expand=True: всегда возвращает DataFrame, что более последовательно и менее запутанно с точки зрения пользователя.

В настоящее время по умолчанию используется expand=None который дает FutureWarning и использует expand=FalseЧтобы избежать этого предупреждения, явно укажите expand.

In [1]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'[ab](\d)', expand=None)
FutureWarning: currently extract(expand=None) means expand=False (return Index/Series/DataFrame)
but in a future version of pandas this will be changed to expand=True (return DataFrame)

Out[1]:
0      1
1      2
2    NaN
dtype: object

Извлечение регулярного выражения с одной группой возвращает Series, если expand=False.

In [16]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'[ab](\d)', expand=False)
Out[16]: 
0      1
1      2
2    NaN
Length: 3, dtype: object

Возвращает DataFrame с одним столбцом, если expand=True.

In [17]: pd.Series(['a1', 'b2', 'c3']).str.extract(r'[ab](\d)', expand=True)
Out[17]: 
     0
0    1
1    2
2  NaN

[3 rows x 1 columns]

Вызов на Index с регулярным выражением, содержащим ровно одну захватывающую группу, возвращает Index if expand=False.

In [18]: s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"])

In [19]: s.index
Out[19]: Index(['A11', 'B22', 'C33'], dtype='object')

In [20]: s.index.str.extract("(?P[a-zA-Z])", expand=False)
Out[20]: Index(['A', 'B', 'C'], dtype='object', name='letter')

Возвращает DataFrame с одним столбцом, если expand=True.

In [21]: s.index.str.extract("(?P[a-zA-Z])", expand=True)
Out[21]: 
  letter
0      A
1      B
2      C

[3 rows x 1 columns]

Вызов на Index с регулярным выражением, содержащим более одной группы захвата, вызывает ValueError if expand=False.

>>> s.index.str.extract("(?P[a-zA-Z])([0-9]+)", expand=False)
ValueError: only one regex group is supported with Index

Возвращает DataFrame if expand=True.

In [22]: s.index.str.extract("(?P[a-zA-Z])([0-9]+)", expand=True)
Out[22]: 
  letter   1
0      A  11
1      B  22
2      C  33

[3 rows x 2 columns]

В итоге, extract(expand=True) всегда возвращает DataFrame со строкой для каждой строки субъекта и столбцом для каждой группы захвата.

Добавление str.extractall#

The .str.extractall метод был добавлен (GH 11386). В отличие от extract, который возвращает только первое совпадение.

In [23]: s = pd.Series(["a1a2", "b1", "c1"], ["A", "B", "C"])

In [24]: s
Out[24]: 
A    a1a2
B      b1
C      c1
Length: 3, dtype: object

In [25]: s.str.extract(r"(?P[ab])(?P\d)", expand=False)
Out[25]: 
  letter digit
A      a     1
B      b     1
C    NaN   NaN

[3 rows x 2 columns]

The extractall метод возвращает все совпадения.

In [26]: s.str.extractall(r"(?P[ab])(?P\d)")
Out[26]: 
        letter digit
  match             
A 0          a     1
  1          a     2
B 0          b     1

[3 rows x 2 columns]

Изменения в str.cat#

Метод .str.cat() объединяет элементы Series. Ранее, если NaN значения присутствовали в Series, вызов .str.cat() на нем вернет NaN, в отличие от остальной части Series.str.* API. Это поведение было изменено, чтобы игнорировать NaN значения по умолчанию. (GH 11435).

Новый, более дружелюбный ValueError добавлена для защиты от ошибки предоставления sep в качестве аргумента, а не в качестве ключевого аргумента. (GH 11334).

In [27]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ')
Out[27]: 'a b c'

In [28]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(sep=' ', na_rep='?')
Out[28]: 'a b ? c'
In [2]: pd.Series(['a', 'b', np.nan, 'c']).str.cat(' ')
ValueError: Did you mean to supply a ``sep`` keyword?

Округление даты/времени#

DatetimeIndex, Timestamp, TimedeltaIndex, Timedelta получили .round(), .floor() и .ceil() метод для округления, округления вниз и вверх для дат и времени. (GH 4314, GH 11963)

Наивные даты и время

In [29]: dr = pd.date_range('20130101 09:12:56.1234', periods=3)

In [30]: dr
Out[30]: 
DatetimeIndex(['2013-01-01 09:12:56.123400', '2013-01-02 09:12:56.123400',
               '2013-01-03 09:12:56.123400'],
              dtype='datetime64[ns]', freq='D')

In [31]: dr.round('s')
Out[31]: 
DatetimeIndex(['2013-01-01 09:12:56', '2013-01-02 09:12:56',
               '2013-01-03 09:12:56'],
              dtype='datetime64[ns]', freq=None)

# Timestamp scalar
In [32]: dr[0]
Out[32]: Timestamp('2013-01-01 09:12:56.123400')

In [33]: dr[0].round('10s')
Out[33]: Timestamp('2013-01-01 09:13:00')

Временные метки с часовым поясом округляются, округляются вниз и вверх в местном времени

In [34]: dr = dr.tz_localize('US/Eastern')

In [35]: dr
Out[35]: 
DatetimeIndex(['2013-01-01 09:12:56.123400-05:00',
               '2013-01-02 09:12:56.123400-05:00',
               '2013-01-03 09:12:56.123400-05:00'],
              dtype='datetime64[ns, US/Eastern]', freq=None)

In [36]: dr.round('s')
Out[36]: 
DatetimeIndex(['2013-01-01 09:12:56-05:00', '2013-01-02 09:12:56-05:00',
               '2013-01-03 09:12:56-05:00'],
              dtype='datetime64[ns, US/Eastern]', freq=None)

Timedeltas

In [37]: t = pd.timedelta_range('1 days 2 hr 13 min 45 us', periods=3, freq='d')

In [38]: t
Out[38]: 
TimedeltaIndex(['1 days 02:13:00.000045', '2 days 02:13:00.000045',
                '3 days 02:13:00.000045'],
               dtype='timedelta64[ns]', freq='D')

In [39]: t.round('10min')
Out[39]: TimedeltaIndex(['1 days 02:10:00', '2 days 02:10:00', '3 days 02:10:00'], dtype='timedelta64[ns]', freq=None)

# Timedelta scalar
In [40]: t[0]
Out[40]: Timedelta('1 days 02:13:00.000045')

In [41]: t[0].round('2h')
Out[41]: Timedelta('1 days 02:00:00')

Кроме того, .round(), .floor() и .ceil() будет доступно через .dt аксессор Series.

In [42]: s = pd.Series(dr)

In [43]: s
Out[43]: 
0   2013-01-01 09:12:56.123400-05:00
1   2013-01-02 09:12:56.123400-05:00
2   2013-01-03 09:12:56.123400-05:00
Length: 3, dtype: datetime64[ns, US/Eastern]

In [44]: s.dt.round('D')
Out[44]: 
0   2013-01-01 00:00:00-05:00
1   2013-01-02 00:00:00-05:00
2   2013-01-03 00:00:00-05:00
Length: 3, dtype: datetime64[ns, US/Eastern]

Форматирование целых чисел в FloatIndex#

Целые числа в FloatIndex, например 1., теперь форматируются с десятичной точкой и 0 цифра, например. 1.0 (GH 11713) Это изменение влияет не только на отображение в консоли, но и на вывод методов ввода-вывода, таких как .to_csv или .to_html.

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

In [2]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [3]: s
Out[3]:
0    1
1    2
2    3
dtype: int64

In [4]: s.index
Out[4]: Float64Index([0.0, 1.0, 2.0], dtype='float64')

In [5]: print(s.to_csv(path=None))
0,1
1,2
2,3

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

In [45]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [46]: s
Out[46]: 
0.0    1
1.0    2
2.0    3
Length: 3, dtype: int64

In [47]: s.index
Out[47]: Index([0.0, 1.0, 2.0], dtype='float64')

In [48]: print(s.to_csv(path_or_buf=None, header=False))
0.0,1
1.0,2
2.0,3

Изменения в поведении назначения типов данных#

Когда срез DataFrame обновляется новым срезом того же типа данных, тип данных DataFrame теперь останется прежним. (GH 10503)

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

In [5]: df = pd.DataFrame({'a': [0, 1, 1],
                           'b': pd.Series([100, 200, 300], dtype='uint32')})

In [7]: df.dtypes
Out[7]:
a     int64
b    uint32
dtype: object

In [8]: ix = df['a'] == 1

In [9]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [11]: df.dtypes
Out[11]:
a    int64
b    int64
dtype: object

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

In [49]: df = pd.DataFrame({'a': [0, 1, 1],
   ....:                    'b': pd.Series([100, 200, 300], dtype='uint32')})
   ....: 

In [50]: df.dtypes
Out[50]: 
a     int64
b    uint32
Length: 2, dtype: object

In [51]: ix = df['a'] == 1

In [52]: df.loc[ix, 'b'] = df.loc[ix, 'b']

In [53]: df.dtypes
Out[53]: 
a     int64
b    uint32
Length: 2, dtype: object

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

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

In [4]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
                          columns=list('abc'),
                          index=[[4,4,8], [8,10,12]])

In [5]: df
Out[5]:
      a  b  c
4 8   1  2  3
  10  4  5  6
8 12  7  8  9

In [7]: df.ix[4, 'c'] = np.array([0., 1.])

In [8]: df
Out[8]:
      a  b  c
4 8   1  2  0
  10  4  5  1
8 12  7  8  9

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

In [54]: df = pd.DataFrame(np.array(range(1,10)).reshape(3,3),
   ....:                   columns=list('abc'),
   ....:                   index=[[4,4,8], [8,10,12]])
   ....: 

In [55]: df
Out[55]: 
      a  b  c
4 8   1  2  3
  10  4  5  6
8 12  7  8  9

[3 rows x 3 columns]

In [56]: df.loc[4, 'c'] = np.array([0., 1.])

In [57]: df
Out[57]: 
      a  b  c
4 8   1  2  0
  10  4  5  1
8 12  7  8  9

[3 rows x 3 columns]

Метод to_xarray#

В будущей версии pandas мы устареем Panel и другие объекты > 2 измерений. Для обеспечения непрерывности, все NDFrame объекты получили .to_xarray() метод для преобразования в xarray объекты, которые имеют интерфейс, подобный pandas, для > 2 измерений. (GH 11972)

См. полная документация xarray здесь.

In [1]: p = Panel(np.arange(2*3*4).reshape(2,3,4))

In [2]: p.to_xarray()
Out[2]:

array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
Coordinates:
  * items       (items) int64 0 1
  * major_axis  (major_axis) int64 0 1 2
  * minor_axis  (minor_axis) int64 0 1 2 3

Представление в Latex#

DataFrame получил ._repr_latex_() метод для обеспечения возможности преобразования в latex в блокноте ipython/jupyter с использованием nbconvert. (GH 11778)

Обратите внимание, что это необходимо активировать, установив опцию pd.display.latex.repr=True (GH 12182)

Например, если у вас есть блокнот jupyter, который вы планируете преобразовать в latex с помощью nbconvert, поместите оператор pd.display.latex.repr=True в первой ячейке, чтобы содержащийся DataFrame также выводился как latex.

Опции display.latex.escape и display.latex.longtable также добавлены в конфигурацию и автоматически используются to_latex метод. См. документация по доступным опциям для получения дополнительной информации.

pd.read_sas() изменения#

read_sas получил возможность читать файлы SAS7BDAT, включая сжатые файлы. Файлы можно читать полностью или по частям. Подробности см. в здесь. (GH 4052)

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

  • Обработка усеченных чисел с плавающей точкой в файлах SAS xport (GH 11713)

  • Добавлена опция скрытия индекса в Series.to_string (GH 11729)

  • read_excel теперь поддерживает s3-ссылки формата s3://bucketname/filename (GH 11447)

  • добавить поддержку для AWS_S3_HOST переменная окружения при чтении из s3 (GH 12198)

  • Простая версия Panel.round() теперь реализовано (GH 11763)

  • Для Python 3.x, round(DataFrame), round(Series), round(Panel) будет работать (GH 11763)

  • sys.getsizeof(obj) возвращает использование памяти объектом pandas, включая содержащиеся в нем значения (GH 11597)

  • Series получил is_unique атрибут (GH 11946)

  • DataFrame.quantile и Series.quantile теперь принимают interpolation ключевое слово (GH 10174).

  • Добавлен DataFrame.style.format для более гибкого форматирования значений ячеек (GH 11692)

  • DataFrame.select_dtypes теперь позволяет np.float16 код типа (GH 11990)

  • pivot_table() теперь принимает большинство итерируемых объектов для values параметр (GH 12017)

  • Добавлен Google BigQuery поддержка аутентификации через сервисный аккаунт, что позволяет аутентификацию на удалённых серверах. (GH 11881, GH 12572). Для получения дополнительных сведений см. здесь

  • HDFStore теперь является итерируемым: for k in store эквивалентно for k in store.keys() (GH 12221).

  • Добавить отсутствующие методы/поля в .dt для Period (GH 8848)

  • Вся кодовая база была PEP-ифицированный (GH 12096)

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

  • ведущие пробелы были удалены из вывода .to_string(index=False) метод (GH 11833)

  • the out параметр был удален из Series.round() метод. (GH 11763)

  • DataFrame.round() оставляет нечисловые столбцы неизменными в своем возвращаемом значении, а не вызывает ошибку. (GH 11885)

  • DataFrame.head(0) и DataFrame.tail(0) возвращать пустые фреймы, а не self. (GH 11937)

  • Series.head(0) и Series.tail(0) возвращать пустую серию, а не self. (GH 11937)

  • to_msgpack и read_msgpack кодировка теперь по умолчанию 'utf-8'. (GH 12170)

  • порядок аргументов ключевых слов для функций парсинга текстовых файлов (.read_csv(), .read_table(), .read_fwf()) изменено для группировки связанных аргументов. (GH 11555)

  • NaTType.isoformat теперь возвращает строку 'NaT чтобы позволить передать результат в конструктор Timestamp. (GH 12300)

Операции с NaT и Timedelta#

NaT и Timedelta расширили арифметические операции, которые расширены до Series арифметические операции, где применимо. Операции, определённые для datetime64[ns] или timedelta64[ns] теперь также определены для NaT (GH 11564).

NaT теперь поддерживает арифметические операции с целыми числами и числами с плавающей точкой.

In [58]: pd.NaT * 1
Out[58]: NaT

In [59]: pd.NaT * 1.5
Out[59]: NaT

In [60]: pd.NaT / 2
Out[60]: NaT

In [61]: pd.NaT * np.nan
Out[61]: NaT

NaT определяет дополнительные арифметические операции с datetime64[ns] и timedelta64[ns].

In [62]: pd.NaT / pd.NaT
Out[62]: nan

In [63]: pd.Timedelta('1s') / pd.NaT
Out[63]: nan

NaT может представлять либо datetime64[ns] null или a timedelta64[ns] null. Учитывая неоднозначность, это рассматривается как timedelta64[ns], что позволяет выполнять больше операций успешно.

In [64]: pd.NaT + pd.NaT
Out[64]: NaT

# same as
In [65]: pd.Timedelta('1s') + pd.Timedelta('1s')
Out[65]: Timedelta('0 days 00:00:02')

в отличие от

In [3]: pd.Timestamp('19900315') + pd.Timestamp('19900315')
TypeError: unsupported operand type(s) for +: 'Timestamp' and 'Timestamp'

Однако, когда обернуто в Series чей dtype является datetime64[ns] или timedelta64[ns], dtype информация учитывается.

In [1]: pd.Series([pd.NaT], dtype=') + pd.Series([pd.NaT], dtype=')
TypeError: can only operate on a datetimes for subtraction,
           but the operator [__add__] was passed
In [66]: pd.Series([pd.NaT], dtype=') + pd.Series([pd.NaT], dtype=')
Out[66]: 
0   NaT
Length: 1, dtype: timedelta64[ns]

Timedelta деление на floats теперь работает.

In [67]: pd.Timedelta('1s') / 2.0
Out[67]: Timedelta('0 days 00:00:00.500000')

Вычитание на Timedelta в Series с помощью Timestamp работает (GH 11925)

In [68]: ser = pd.Series(pd.timedelta_range('1 day', periods=3))

In [69]: ser
Out[69]: 
0   1 days
1   2 days
2   3 days
Length: 3, dtype: timedelta64[ns]

In [70]: pd.Timestamp('2012-01-01') - ser
Out[70]: 
0   2011-12-31
1   2011-12-30
2   2011-12-29
Length: 3, dtype: datetime64[ns]

NaT.isoformat() теперь возвращает 'NaT'. Это изменение позволяет pd.Timestamp для восстановления любого объекта временной метки из его isoформата (GH 12300).

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

Несовместимые изменения в будущих версиях в msgpack формат записи был изменен в версиях 0.17.0 и 0.18.0; старые версии pandas не могут читать файлы, созданные новыми версиями (GH 12129, GH 10527)

Ошибки в to_msgpack и read_msgpack введено в 0.17.0 и исправлено в 0.18.0, из-за чего файлы, упакованные в Python 2, не читались в Python 3 (GH 12142). Следующая таблица описывает обратную и прямую совместимость msgpacks.

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

Упаковано с

Может быть распаковано с помощью

до версии 0.17 / Python 2

любой

pre-0.17 / Python 3

любой

0.17 / Python 2

  • ==0.17 / Python 2

  • >=0.18 / любой Python

0.17 / Python 3

>=0.18 / любой Python

0.18

>= 0.18

0.18.0 обратно совместима для чтения файлов, упакованных старыми версиями, за исключением файлов, упакованных с 0.17 в Python 2, в этом случае их можно распаковать только в Python 2.

Изменение сигнатуры для .rank#

Series.rank и DataFrame.rank теперь имеют одинаковую сигнатуру (GH 11759)

Предыдущая сигнатура

In [3]: pd.Series([0,1]).rank(method='average', na_option='keep',
                              ascending=True, pct=False)
Out[3]:
0    1
1    2
dtype: float64

In [4]: pd.DataFrame([0,1]).rank(axis=0, numeric_only=None,
                                 method='average', na_option='keep',
                                 ascending=True, pct=False)
Out[4]:
   0
0  1
1  2

Новая сигнатура

In [71]: pd.Series([0,1]).rank(axis=0, method='average', numeric_only=False,
   ....:                       na_option='keep', ascending=True, pct=False)
   ....: 
Out[71]: 
0    1.0
1    2.0
Length: 2, dtype: float64

In [72]: pd.DataFrame([0,1]).rank(axis=0, method='average', numeric_only=False,
   ....:                          na_option='keep', ascending=True, pct=False)
   ....: 
Out[72]: 
     0
0  1.0
1  2.0

[2 rows x 1 columns]

Ошибка в QuarterBegin с n=0#

В предыдущих версиях поведение смещения QuarterBegin было непоследовательным в зависимости от даты, когда n параметр был 0. (GH 11406)

Общая семантика закрепленных смещений для n=0 состоит в том, чтобы не перемещать дату когда это точка привязки (например, начало квартала), а в противном случае сдвигать вперед к следующей точке привязки.

In [73]: d = pd.Timestamp('2014-02-01')

In [74]: d
Out[74]: Timestamp('2014-02-01 00:00:00')

In [75]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[75]: Timestamp('2014-02-01 00:00:00')

In [76]: d + pd.offsets.QuarterBegin(n=0, startingMonth=1)
Out[76]: Timestamp('2014-04-01 00:00:00')

Для QuarterBegin смещение в предыдущих версиях, дата была бы перенесена обратной совместимостью если дата была в том же месяце, что и дата начала квартала.

In [3]: d = pd.Timestamp('2014-02-15')

In [4]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[4]: Timestamp('2014-02-01 00:00:00')

Это поведение было исправлено в версии 0.18.0, что согласуется с другими закреплёнными смещениями, такими как MonthBegin и YearBegin.

In [77]: d = pd.Timestamp('2014-02-15')

In [78]: d + pd.offsets.QuarterBegin(n=0, startingMonth=2)
Out[78]: Timestamp('2014-05-01 00:00:00')

API Resample#

Как изменение в API оконных функций выше, .resample(...) изменяется для более похожего на groupby API. (GH 11732, GH 12702, GH 12202, GH 12332, GH 12334, GH 12348, GH 12448).

In [79]: np.random.seed(1234)

In [80]: df = pd.DataFrame(np.random.rand(10,4),
   ....:                   columns=list('ABCD'),
   ....:                   index=pd.date_range('2010-01-01 09:00:00',
   ....:                                       periods=10, freq='s'))
   ....: 

In [81]: df
Out[81]: 
                            A         B         C         D
2010-01-01 09:00:00  0.191519  0.622109  0.437728  0.785359
2010-01-01 09:00:01  0.779976  0.272593  0.276464  0.801872
2010-01-01 09:00:02  0.958139  0.875933  0.357817  0.500995
2010-01-01 09:00:03  0.683463  0.712702  0.370251  0.561196
2010-01-01 09:00:04  0.503083  0.013768  0.772827  0.882641
2010-01-01 09:00:05  0.364886  0.615396  0.075381  0.368824
2010-01-01 09:00:06  0.933140  0.651378  0.397203  0.788730
2010-01-01 09:00:07  0.316836  0.568099  0.869127  0.436173
2010-01-01 09:00:08  0.802148  0.143767  0.704261  0.704581
2010-01-01 09:00:09  0.218792  0.924868  0.442141  0.909316

[10 rows x 4 columns]

Предыдущий API:

Вы бы написали операцию передискретизации, которая немедленно вычисляется. Если how параметр не был предоставлен, он по умолчанию будет равен how='mean'.

In [6]: df.resample('2s')
Out[6]:
                         A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949

Вы также можете указать how напрямую

In [7]: df.resample('2s', how='sum')
Out[7]:
                         A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897

Новый API:

Теперь вы можете писать .resample(..) как двухэтапная операция, например .groupby(...), что дает Resampler.

In [82]: r = df.resample('2s')

In [83]: r
Out[83]: 

Понижающая дискретизация#

Затем вы можете использовать этот объект для выполнения операций. Это операции понижающей дискретизации (переход от более высокой частоты к более низкой).

In [84]: r.mean()
Out[84]: 
                            A         B         C         D
2010-01-01 09:00:00  0.485748  0.447351  0.357096  0.793615
2010-01-01 09:00:02  0.820801  0.794317  0.364034  0.531096
2010-01-01 09:00:04  0.433985  0.314582  0.424104  0.625733
2010-01-01 09:00:06  0.624988  0.609738  0.633165  0.612452
2010-01-01 09:00:08  0.510470  0.534317  0.573201  0.806949

[5 rows x 4 columns]
In [85]: r.sum()
Out[85]: 
                            A         B         C         D
2010-01-01 09:00:00  0.971495  0.894701  0.714192  1.587231
2010-01-01 09:00:02  1.641602  1.588635  0.728068  1.062191
2010-01-01 09:00:04  0.867969  0.629165  0.848208  1.251465
2010-01-01 09:00:06  1.249976  1.219477  1.266330  1.224904
2010-01-01 09:00:08  1.020940  1.068634  1.146402  1.613897

[5 rows x 4 columns]

Кроме того, resample теперь поддерживает getitem операции для выполнения передискретизации по определенным столбцам.

In [86]: r[['A','C']].mean()
Out[86]: 
                            A         C
2010-01-01 09:00:00  0.485748  0.357096
2010-01-01 09:00:02  0.820801  0.364034
2010-01-01 09:00:04  0.433985  0.424104
2010-01-01 09:00:06  0.624988  0.633165
2010-01-01 09:00:08  0.510470  0.573201

[5 rows x 2 columns]

и .aggregate операции с типами.

In [87]: r.agg({'A' : 'mean', 'B' : 'sum'})
Out[87]: 
                            A         B
2010-01-01 09:00:00  0.485748  0.894701
2010-01-01 09:00:02  0.820801  1.588635
2010-01-01 09:00:04  0.433985  0.629165
2010-01-01 09:00:06  0.624988  1.219477
2010-01-01 09:00:08  0.510470  1.068634

[5 rows x 2 columns]

Эти аксессоры, конечно, могут быть объединены

In [88]: r[['A','B']].agg(['mean','sum'])
Out[88]: 
                            A                   B          
                         mean       sum      mean       sum
2010-01-01 09:00:00  0.485748  0.971495  0.447351  0.894701
2010-01-01 09:00:02  0.820801  1.641602  0.794317  1.588635
2010-01-01 09:00:04  0.433985  0.867969  0.314582  0.629165
2010-01-01 09:00:06  0.624988  1.249976  0.609738  1.219477
2010-01-01 09:00:08  0.510470  1.020940  0.534317  1.068634

[5 rows x 4 columns]

Повышение частоты дискретизации#

Операции повышающей дискретизации переводят вас с более низкой частоты на более высокую. Теперь они выполняются с помощью Resampler объекты с backfill(), ffill(), fillna() и asfreq() методы.

In [89]: s = pd.Series(np.arange(5, dtype='int64'),
              index=pd.date_range('2010-01-01', periods=5, freq='Q'))

In [90]: s
Out[90]:
2010-03-31    0
2010-06-30    1
2010-09-30    2
2010-12-31    3
2011-03-31    4
Freq: Q-DEC, Length: 5, dtype: int64

Ранее

In [6]: s.resample('M', fill_method='ffill')
Out[6]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, dtype: int64

Новый API

In [91]: s.resample('M').ffill()
Out[91]:
2010-03-31    0
2010-04-30    0
2010-05-31    0
2010-06-30    1
2010-07-31    1
2010-08-31    1
2010-09-30    2
2010-10-31    2
2010-11-30    2
2010-12-31    3
2011-01-31    3
2011-02-28    3
2011-03-31    4
Freq: M, Length: 13, dtype: int64

Примечание

В новом API вы можете либо понизить, либо повысить частоту дискретизации. Предыдущая реализация позволяла передавать агрегирующую функцию (например, mean) даже при апсемплинге, что вызывало некоторую путаницу.

Предыдущий API будет работать, но с устареваниями#

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

funnycrab +

In [4]: r = df.resample('2s')

In [6]: r*10
pandas/tseries/resample.py:80: FutureWarning: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...)

Out[6]:
                      A         B         C         D
2010-01-01 09:00:00  4.857476  4.473507  3.570960  7.936154
2010-01-01 09:00:02  8.208011  7.943173  3.640340  5.310957
2010-01-01 09:00:04  4.339846  3.145823  4.241039  6.257326
2010-01-01 09:00:06  6.249881  6.097384  6.331650  6.124518
2010-01-01 09:00:08  5.104699  5.343172  5.732009  8.069486

Однако операции получения и присваивания непосредственно на Resampler вызовет ValueError:

In [7]: r.iloc[0] = 5
ValueError: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...)

Существует ситуация, когда новый API не может выполнить все операции при использовании исходного кода. Этот код предназначен для ресемплинга каждые 2 секунды, взятия mean И затем взять min из этих результатов.

In [4]: df.resample('2s').min()
Out[4]:
A    0.433985
B    0.314582
C    0.357096
D    0.531096
dtype: float64

Новый API будет:

In [89]: df.resample('2s').min()
Out[89]: 
                            A         B         C         D
2010-01-01 09:00:00  0.191519  0.272593  0.276464  0.785359
2010-01-01 09:00:02  0.683463  0.712702  0.357817  0.500995
2010-01-01 09:00:04  0.364886  0.013768  0.075381  0.368824
2010-01-01 09:00:06  0.316836  0.568099  0.397203  0.436173
2010-01-01 09:00:08  0.218792  0.143767  0.442141  0.704581

[5 rows x 4 columns]

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

Для воспроизведения исходной операции

In [90]: df.resample('2s').mean().min()
Out[90]: 
A    0.433985
B    0.314582
C    0.357096
D    0.531096
Length: 4, dtype: float64

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

В предыдущих версиях присвоение новых столбцов в eval выражение привело к изменению на месте в DataFrame. (GH 9297, GH 8664, GH 10486)

In [91]: df = pd.DataFrame({'a': np.linspace(0, 10, 5), 'b': range(5)})

In [92]: df
Out[92]: 
      a  b
0   0.0  0
1   2.5  1
2   5.0  2
3   7.5  3
4  10.0  4

[5 rows x 2 columns]
In [12]: df.eval('c = a + b')
FutureWarning: eval expressions containing an assignment currentlydefault to operating inplace.
This will change in a future version of pandas, use inplace=True to avoid this warning.

In [13]: df
Out[13]:
      a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

В версии 0.18.0 новый inplace Ключевое слово было добавлено для выбора, должно ли назначение выполняться на месте или возвращать копию.

In [93]: df
Out[93]: 
      a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [94]: df.eval('d = c - b', inplace=False)
Out[94]: 
      a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns]

In [95]: df
Out[95]: 
      a  b     c
0   0.0  0   0.0
1   2.5  1   3.5
2   5.0  2   7.0
3   7.5  3  10.5
4  10.0  4  14.0

[5 rows x 3 columns]

In [96]: df.eval('d = c - b', inplace=True)

In [97]: df
Out[97]: 
      a  b     c     d
0   0.0  0   0.0   0.0
1   2.5  1   3.5   2.5
2   5.0  2   7.0   5.0
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[5 rows x 4 columns]

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

Для обратной совместимости, inplace по умолчанию True если не указано. Это изменится в будущей версии pandas. Если ваш код зависит от присваивания на месте, вам следует обновить его, чтобы явно установить inplace=True

The inplace параметр ключевого слова также был добавлен query метод.

In [98]: df.query('a > 5')
Out[98]: 
      a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [99]: df.query('a > 5', inplace=True)

In [100]: df
Out[100]: 
      a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

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

Обратите внимание, что значение по умолчанию для inplace в query является False, что соответствует предыдущим версиям.

eval также было обновлено для поддержки многострочных выражений при множественных присваиваниях. Эти выражения будут вычисляться по одному в порядке следования. Только присваивания допустимы для многострочных выражений.

In [101]: df
Out[101]: 
      a  b     c     d
3   7.5  3  10.5   7.5
4  10.0  4  14.0  10.0

[2 rows x 4 columns]

In [102]: df.eval("""
   .....: e = d + a
   .....: f = e - 22
   .....: g = f / 2.0""", inplace=True)
   .....: 

In [103]: df
Out[103]: 
      a  b     c     d     e    f    g
3   7.5  3  10.5   7.5  15.0 -7.0 -3.5
4  10.0  4  14.0  10.0  20.0 -2.0 -1.0

[2 rows x 7 columns]

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

  • DataFrame.between_time и Series.between_time теперь разбирает только фиксированный набор строк времени. Разбор строк даты больше не поддерживается и вызывает ValueError. (GH 11818)

    In [107]: s = pd.Series(range(10), pd.date_range('2015-01-01', freq='H', periods=10))
    
    In [108]: s.between_time("7:00am", "9:00am")
    Out[108]:
    2015-01-01 07:00:00    7
    2015-01-01 08:00:00    8
    2015-01-01 09:00:00    9
    Freq: H, Length: 3, dtype: int64
    

    Теперь это будет вызывать ошибку.

    In [2]: s.between_time('20150101 07:00:00','20150101 09:00:00')
    ValueError: Cannot convert arg ['20150101 07:00:00'] to a time.
    
  • .memory_usage() теперь включает значения в индексе, как и memory_usage в .info() (GH 11597)

  • DataFrame.to_latex() теперь поддерживает не-ASCII кодировки (например, utf-8) в Python 2 с параметром encoding (GH 7061)

  • pandas.merge() и DataFrame.merge() будет показывать конкретное сообщение об ошибке при попытке слияния с объектом, не являющимся типом DataFrame или подкласс (GH 12081)

  • DataFrame.unstack и Series.unstack теперь принимают fill_value ключевое слово для прямой замены пропущенных значений, когда unstack приводит к пропущенным значениям в результате DataFrame. В качестве дополнительного преимущества, указание fill_value сохранит тип данных исходных уложенных данных. (GH 9746)

  • В рамках нового API для оконные функции и ресемплинг, функции агрегации были уточнены, выводя более информативные сообщения об ошибках при недопустимых агрегациях. (GH 9052). Полный набор примеров представлен в groupby.

  • Статистические функции для NDFrame объектов (таких как sum(), mean(), min()) теперь будет вызывать ошибку, если переданы аргументы, несовместимые с numpy, для **kwargs (GH 12301)

  • .to_latex и .to_html получить decimal параметра, такого как .to_csv; по умолчанию '.' (GH 12031)

  • Более полезное сообщение об ошибке при создании DataFrame с пустыми данными, но с индексами (GH 8020)

  • .describe() теперь будет правильно обрабатывать bool dtype как категориальный (GH 6625)

  • Более информативное сообщение об ошибке при недопустимом .transform с пользовательским вводом (GH 10165)

  • Экспоненциально взвешенные функции теперь позволяют напрямую указывать альфа (GH 10789) и вызывает ValueError если параметры нарушают 0 < alpha <= 1 (GH 12492)

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

  • Функции pd.rolling_*, pd.expanding_*, и pd.ewm* устарели и заменены соответствующими вызовами методов. Обратите внимание, что новый предлагаемый синтаксис включает все аргументы (даже по умолчанию) (GH 11603)

    In [1]: s = pd.Series(range(3))
    
    In [2]: pd.rolling_mean(s,window=2,min_periods=1)
            FutureWarning: pd.rolling_mean is deprecated for Series and
                 will be removed in a future version, replace with
                 Series.rolling(min_periods=1,window=2,center=False).mean()
    Out[2]:
            0    0.0
            1    0.5
            2    1.5
            dtype: float64
    
    In [3]: pd.rolling_cov(s, s, window=2)
            FutureWarning: pd.rolling_cov is deprecated for Series and
                 will be removed in a future version, replace with
                 Series.rolling(window=2).cov(other=)
    Out[3]:
            0    NaN
            1    0.5
            2    0.5
            dtype: float64
    
  • The freq и how аргументы для .rolling, .expanding, и .ewm (новые) функции устарели и будут удалены в будущей версии. Вы можете просто передискретизировать входные данные перед созданием оконной функции. (GH 11603).

    Например, вместо s.rolling(window=5,freq='D').max() чтобы получить максимальное значение в скользящем окне 5 дней, можно использовать s.resample('D').mean().rolling(window=5).max(), который сначала передискретизирует данные до ежедневных, затем предоставляет скользящее окно в 5 дней.

  • pd.tseries.frequencies.get_offset_name функция устарела. Используйте offset’s .freqstr свойство как альтернатива (GH 11192)

  • pandas.stats.fama_macbeth подпрограммы устарели и будут удалены в будущей версии (GH 6077)

  • pandas.stats.ols, pandas.stats.plm и pandas.stats.var подпрограммы устарели и будут удалены в будущей версии (GH 6077)

  • показать FutureWarning а не DeprecationWarning при использовании давно устаревшего синтаксиса в HDFStore.select, где where условие не является строкоподобным (GH 12027)

  • The pandas.options.display.mpl_style конфигурация устарела и будет удалена в будущей версии pandas. Эта функциональность лучше обрабатывается таблицы стилей (GH 11783).

Удаление устаревших индексаторов с плавающей точкой#

В GH 4892 индексирование с числами с плавающей точкой на не-Float64Index было устаревшим (в версии 0.14.0). В 0.18.0 это предупреждение об устаревании удалено, и теперь они будут вызывать TypeError. (GH 12165, GH 12333)

In [104]: s = pd.Series([1, 2, 3], index=[4, 5, 6])

In [105]: s
Out[105]: 
4    1
5    2
6    3
Length: 3, dtype: int64

In [106]: s2 = pd.Series([1, 2, 3], index=list('abc'))

In [107]: s2
Out[107]: 
a    1
b    2
c    3
Length: 3, dtype: int64

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

# this is label indexing
In [2]: s[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[2]: 2

# this is positional indexing
In [3]: s.iloc[1.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[3]: 2

# this is label indexing
In [4]: s.loc[5.0]
FutureWarning: scalar indexers for index type Int64Index should be integers and not floating point
Out[4]: 2

# .ix would coerce 1.0 to the positional 1, and index
In [5]: s2.ix[1.0] = 10
FutureWarning: scalar indexers for index type Index should be integers and not floating point

In [6]: s2
Out[6]:
a     1
b    10
c     3
dtype: int64

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

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

In [3]: s.iloc[2.0]
TypeError: cannot do label indexing on  with these indexers [2.0] of 

Другие индексаторы будут преобразованы в аналогичный целочисленный тип как для получения, так и для установки значений. FutureWarning был удален для .loc, .ix и [].

In [108]: s[5.0]
Out[108]: 2

In [109]: s.loc[5.0]
Out[109]: 2

и установка

In [110]: s_copy = s.copy()

In [111]: s_copy[5.0] = 10

In [112]: s_copy
Out[112]: 
4     1
5    10
6     3
Length: 3, dtype: int64

In [113]: s_copy = s.copy()

In [114]: s_copy.loc[5.0] = 10

In [115]: s_copy
Out[115]: 
4     1
5    10
6     3
Length: 3, dtype: int64

Позиционная установка с .ix и индексатор с плавающей точкой ДОБАВИТ это значение к индексу, а не установит значение по позиции, как ранее.

In [3]: s2.ix[1.0] = 10
In [4]: s2
Out[4]:
a       1
b       2
c       3
1.0    10
dtype: int64

Срезы также будут преобразовывать целочисленные подобные числа с плавающей точкой в целые числа для не-Float64Index.

In [116]: s.loc[5.0:6]
Out[116]: 
5    2
6    3
Length: 2, dtype: int64

Обратите внимание, что для чисел с плавающей точкой, которые НЕ преобразуются в целые числа, границы на основе меток будут исключены

In [117]: s.loc[5.1:6]
Out[117]: 
6    3
Length: 1, dtype: int64

Индексирование с плавающей точкой на Float64Index не изменяется.

In [118]: s = pd.Series([1, 2, 3], index=np.arange(3.))

In [119]: s[1.0]
Out[119]: 2

In [120]: s[1.0:2.5]
Out[120]: 
1.0    2
2.0    3
Length: 2, dtype: int64

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

  • Удаление rolling_corr_pairwise в пользу .rolling().corr(pairwise=True) (GH 4950)

  • Удаление expanding_corr_pairwise в пользу .expanding().corr(pairwise=True) (GH 4950)

  • Удаление DataMatrix модуля. Это не было импортировано в пространство имен pandas в любом случае (GH 12111)

  • Удаление cols ключевое слово в пользу subset в DataFrame.duplicated() и DataFrame.drop_duplicates() (GH 6680)

  • Удаление read_frame и frame_query (оба псевдонима для pd.read_sql) и write_frame (псевдоним to_sql) функции в pd.io.sql пространство имен, устарело с версии 0.14.0 (GH 6292).

  • Удаление order ключевое слово из .factorize() (GH 6930)

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

  • Улучшена производительность andrews_curves (GH 11534)

  • Улучшена обработка огромных DatetimeIndex, PeriodIndex и TimedeltaIndexпроизводительность операций, включая NaT (GH 10277)

  • Улучшена производительность pandas.concat (GH 11958)

  • Улучшена производительность StataReader (GH 11591)

  • Улучшена производительность при построении Categoricals с Series дат, содержащих NaT (GH 12077)

  • Улучшена производительность парсинга дат ISO 8601 для дат без разделителей (GH 11899), ведущие нули (GH 11871) и с пробелом перед часовым поясом (GH 9714)

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

  • Ошибка в GroupBy.size когда фрейм данных пуст. (GH 11699)

  • Ошибка в Period.end_time когда запрашивается кратное временному периоду (GH 11738)

  • Регрессия в .clip с датами с учетом часового пояса (GH 11838)

  • Ошибка в date_range когда границы попадали на частоту (GH 11804, GH 12409)

  • Ошибка в согласованности передачи вложенных словарей в .groupby(...).agg(...) (GH 9052)

  • Принимать unicode в Timedelta конструктор (GH 11995)

  • Ошибка при чтении метки значения для StataReader при инкрементальном чтении (GH 12014)

  • Ошибка в векторизованном DateOffset когда n параметр 0 (GH 11370)

  • Совместимость с numpy 1.11 относительно NaT изменения сравнения (GH 12049)

  • Ошибка в read_csv при чтении из StringIO в потоках (GH 11790)

  • Ошибка в неправильной обработке NaT как пропущенное значение в datetime при факторизации и с Categoricals (GH 12077)

  • Ошибка в getitem, когда значения Series были с учетом часового пояса (GH 12089)

  • Ошибка в Series.str.get_dummies когда одной из переменных было 'name' (GH 12180)

  • Ошибка в pd.concat при объединении серий NaT с учетом часового пояса. (GH 11693, GH 11755, GH 12217)

  • Ошибка в pd.read_stata с файлами версии <= 108 (GH 12232)

  • Ошибка в Series.resample используя частоту Nano когда индекс является DatetimeIndex и содержит ненулевые наносекундные части (GH 12037)

  • Ошибка при передискретизации с .nunique и разреженный индекс (GH 12352)

  • Убраны некоторые предупреждения компилятора (GH 12471)

  • Обход проблем совместимости с boto в python 3.5 (GH 11915)

  • Ошибка в NaT вычитание из Timestamp или DatetimeIndex с часовыми поясами (GH 11718)

  • Ошибка при вычитании Series одного tz-aware Timestamp (GH 12290)

  • Использовать совместимые итераторы в PY2 для поддержки .next() (GH 12299)

  • Ошибка в Timedelta.round с отрицательными значениями (GH 11690)

  • Ошибка в .loc против CategoricalIndex может привести к нормальному Index (GH 11586)

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

  • Ошибка в .copy datetime объектов с информацией о часовом поясе (GH 11794)

  • Ошибка в Series.apply и Series.map где timedelta64 не был упакован (GH 11349)

  • Ошибка в DataFrame.set_index() с учетом часового пояса Series (GH 12358)

  • Ошибка в подклассах DataFrame где AttributeError не распространялось (GH 11808)

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

  • Ошибка в pd.read_clipboard и pd.to_clipboard функции, не поддерживающие Unicode; обновление включено pyperclip до v1.5.15 (GH 9263)

  • Ошибка в DataFrame.query содержащий присваивание (GH 8664)

  • Ошибка в from_msgpack где __contains__() не работает для столбцов распакованного DataFrame, если DataFrame имеет столбцы типа object. (GH 11880)

  • Ошибка в .resample на категориальных данных с TimedeltaIndex (GH 12169)

  • Ошибка: информация о часовом поясе теряется при трансляции скалярного datetime в DataFrame (GH 11682)

  • Ошибка в Index создание из Timestamp со смешанными часовыми поясами преобразуется в UTC (GH 11488)

  • Ошибка в to_numeric где не вызывает ошибку, если входные данные имеют более одного измерения (GH 11776)

  • Ошибка в разборе строк смещения часового пояса с ненулевыми минутами (GH 11708)

  • Ошибка в df.plot использование некорректных цветов для столбчатых диаграмм в matplotlib 1.5+ (GH 11614)

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

  • Ошибка в DataFrame.duplicated и drop_duplicates вызывая ложные совпадения при установке keep=False (GH 11864)

  • Ошибка в .loc результат с дублированным ключом может иметь Index с некорректным dtype (GH 11497)

  • Ошибка в pd.rolling_median где выделение памяти завершилось неудачей даже при достаточном объеме памяти (GH 11696)

  • Ошибка в DataFrame.style со случайными нулями (GH 12134)

  • Ошибка в DataFrame.style с целочисленными столбцами, не начинающимися с 0 (GH 12125)

  • Ошибка в .style.bar может отображаться некорректно в определённых браузерах (GH 11678)

  • Ошибка в богатом сравнении Timedelta с numpy.array of Timedelta что вызвало бесконечную рекурсию (GH 11835)

  • Ошибка в DataFrame.round удаление имени индекса столбца (GH 11986)

  • Ошибка в df.replace при замене значения в смешанном типе данных Dataframe (GH 11698)

  • Ошибка в Index предотвращает копирование имени переданного Index, когда новое имя не предоставлено (GH 11193)

  • Ошибка в read_excel не удается прочитать непустые листы при наличии пустых листов и sheetname=None (GH 11711)

  • Ошибка в read_excel не удалось вызвать NotImplemented ошибка при использовании ключевых слов parse_dates и date_parser предоставлены (GH 11544)

  • Ошибка в read_sql с pymysql соединения, не возвращающие фрагментированные данные (GH 11522)

  • Ошибка в .to_csv игнорируя параметры форматирования decimal, na_rep, float_format для индексов с плавающей запятой (GH 11553)

  • Ошибка в Int64Index и Float64Index предотвращая использование оператора модуля (GH 9244)

  • Ошибка в MultiIndex.drop для не лексически отсортированных MultiIndexes (GH 12078)

  • Ошибка в DataFrame при маскировании пустого DataFrame (GH 11859)

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

  • Ошибка в Series.plot ошибка при наличии индекса с CustomBusinessDay частота (GH 7222).

  • Ошибка в .to_sql для datetime.time значения с резервным вариантом sqlite (GH 8341)

  • Ошибка в read_excel не удается прочитать данные с одним столбцом, когда squeeze=True (GH 12157)

  • Ошибка в read_excel не удалось прочитать один пустой столбец (GH 12292, GH 9002)

  • Ошибка в .groupby где KeyError не вызывалось для неправильного столбца, если в dataframe была только одна строка (GH 11741)

  • Ошибка в .read_csv с указанием dtype на пустых данных, вызывающих ошибку (GH 12048)

  • Ошибка в .read_csv где строки, такие как '2E' рассматриваются как допустимые числа с плавающей точкой (GH 12237)

  • Ошибка в сборке pandas с символами отладки (GH 12123)

  • Удалено millisecond свойство DatetimeIndex. Это всегда вызывало бы ValueError (GH 12019).

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

  • Удалено pandas._testing.choice(). Следует использовать np.random.choice(), вместо этого. (GH 12386)

  • Ошибка в .loc индексатор setitem, предотвращающий использование DatetimeIndex с учетом часового пояса (GH 12050)

  • Ошибка в .style индексы и MultiIndexes не отображаются (GH 11655)

  • Ошибка в to_msgpack и from_msgpack который некорректно сериализовал или десериализовал NaT (GH 12307).

  • Ошибка в .skew и .kurt из-за ошибки округления для очень похожих значений (GH 11974)

  • Ошибка в Timestamp конструктор, где разрешение микросекунд терялось, если HHMMSS не были разделены ':' (GH 10041)

  • Ошибка в buffer_rd_bytes src->buffer мог быть освобожден более одного раза при неудачном чтении, вызывая ошибку сегментации (GH 12098)

  • Ошибка в crosstab где аргументы с непересекающимися индексами возвращают KeyError (GH 10291)

  • Ошибка в DataFrame.apply в котором предотвращение редукции не выполнялось для случаев, когда dtype не был numpy dtype (GH 12244)

  • Ошибка при инициализации категориальной серии скалярным значением. (GH 12336)

  • Ошибка при указании UTC DatetimeIndex установкой utc=True в .to_datetime (GH 11934)

  • Ошибка при увеличении размера буфера CSV-ридера в read_csv (GH 12494)

  • Ошибка при установке столбцов DataFrame с повторяющимися именами столбцов (GH 12344)

Участники#

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

  • ARF +

  • Alex Alekseyev +

  • Andrew McPherson +

  • Andrew Rosenfeld

  • Andy Hayden

  • Anthonios Partheniou

  • Anton I. Sipos

  • Ben +

  • Ben North +

  • Bran Yang +

  • Chris

  • Chris Carroux +

  • Christopher C. Aycock +

  • Christopher Scanlin +

  • Cody +

  • Da Wang +

  • Daniel Grady +

  • Dorozhko Anton +

  • Dr-Irv +

  • Эрик М. Брей +

  • Evan Wright

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

  • Frank Cleary +

  • Джанлука Росси

  • Грэм Джеффрис +

  • Guillaume Horel

  • Henry Hammond +

  • Isaac Schwabacher +

  • Jean-Mathieu Deschenes

  • Jeff Reback

  • Joe Jevnik +

  • Джон Фримен +

  • John Fremlin +

  • Jonas Hoersch +

  • Joris Van den Bossche

  • Joris Vankerschaver

  • Justin Lecher

  • Justin Lin +

  • Ka Wo Chen

  • Кеминг Чжан +

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

  • Kyle +

  • Marco Farrugia +

  • MasonGallo +

  • MattRijk +

  • Matthew Lurie +

  • Maximilian Roos

  • Mayank Asthana +

  • Mortada Mehyar

  • Moussa Taifi +

  • Navreet Gill +

  • Nicolas Bonnotte

  • Paul Reiners +

  • Филип Гура +

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

  • RahulHP +

  • Randy Carnevale

  • Rinoc Johnson

  • Rishipuri +

  • Sangmin Park +

  • Скотт Э. Ласли

  • Sereger13 +

  • Shannon Wang +

  • Skipper Seabold

  • Thierry Moisan

  • Thomas A Caswell

  • Toby Dylan Hocking +

  • Tom Augspurger

  • Travis +

  • Trent Hauck

  • Tux1

  • Varun

  • Wes McKinney

  • Will Thompson +

  • register_dataframe_accessor

  • Yoong Kang Lim +

  • Yoshiki Vázquez Baeza

  • Young Joong Kim +

  • Younggun Kim

  • Yuval Langer +

  • alex argunov +

  • behzad nouri

  • boombard +

  • brian-pantano +

  • chromy +

  • daniel +

  • dgram0 +

  • gfyoung +

  • hack-c +

  • hcontrast +

  • jfoo +

  • kaustuv deolal +

  • llllllllll

  • ranarag +

  • rockg

  • scls19fr

  • seales +

  • sinhrks

  • srib +

  • surveymedia.ca +

  • tworec +