Версия 0.15.0 (18 октября 2014)#

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

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

pandas >= 0.15.0 больше не будет поддерживать совместимость с версиями NumPy < 1.7.0. Если вы хотите использовать последние версии pandas, пожалуйста, обновитесь до NumPy >= 1.7.0 (GH 7711)

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

В версии 0.15.0 Index был внутренне переработан, чтобы больше не наследовать от ndarray но вместо этого подкласс PandasObject, аналогично остальным объектам pandas. Это изменение позволяет очень просто создавать подклассы и новые типы индексов. Это должно быть прозрачным изменением с очень ограниченными последствиями для API (см. Внутренний рефакторинг)

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

Рефакторинг в Categorical изменил конструктор с двумя аргументами с "коды/метки и уровни" на "значения и уровни (теперь называемые 'категориями')". Это может привести к тонким ошибкам. Если вы используете Categorical напрямую, пожалуйста, проверьте свой код перед обновлением до этой версии pandas и измените его, чтобы использовать from_codes() конструктор. Подробнее см. Categorical здесь

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

Категориальные данные в Series/DataFrame#

Categorical теперь может быть включён в Series и DataFrames и получил новые методы для манипуляции. Спасибо Jan Schulz за большую часть этого API/реализации. (GH 3943, GH 5313, GH 5314, GH 7444, GH 7839, GH 7848, GH 7864, GH 7914, GH 7768, GH 8006, GH 3678, GH 8075, GH 8076, GH 8143, GH 8453, GH 8518).

Полную документацию см. в введение в категориальные данные и документация API.

In [1]: df = pd.DataFrame({"id": [1, 2, 3, 4, 5, 6],
   ...:                    "raw_grade": ['a', 'b', 'b', 'a', 'a', 'e']})
   ...: 

In [2]: df["grade"] = df["raw_grade"].astype("category")

In [3]: df["grade"]
Out[3]: 
0    a
1    b
2    b
3    a
4    a
5    e
Name: grade, Length: 6, dtype: category
Categories (3, object): ['a', 'b', 'e']

# Rename the categories
In [4]: df["grade"] = df["grade"].cat.rename_categories(["very good", "good", "very bad"])

# Reorder the categories and simultaneously add the missing categories
In [5]: df["grade"] = df["grade"].cat.set_categories(["very bad", "bad",
   ...:                                               "medium", "good", "very good"])
   ...: 

In [6]: df["grade"]
Out[6]: 
0    very good
1         good
2         good
3    very good
4    very good
5     very bad
Name: grade, Length: 6, dtype: category
Categories (5, object): ['very bad', 'bad', 'medium', 'good', 'very good']

In [7]: df.sort_values("grade")
Out[7]: 
   id raw_grade      grade
5   6         e   very bad
1   2         b       good
2   3         b       good
0   1         a  very good
3   4         a  very good
4   5         a  very good

[6 rows x 3 columns]

In [8]: df.groupby("grade", observed=False).size()
Out[8]: 
grade
very bad     1
bad          0
medium       0
good         2
very good    3
Length: 5, dtype: int64
  • pandas.core.group_agg и pandas.core.factor_agg были удалены. В качестве альтернативы создайте датафрейм и используйте df.groupby().agg().

  • Предоставление "кодов/меток и уровней" в Categorical конструктор больше не поддерживается. Передача двух аргументов в конструктор теперь интерпретируется как "значения и уровни (теперь называемые 'категориями')". Пожалуйста, измените свой код, чтобы использовать from_codes() конструктор.

  • The Categorical.labels атрибут был переименован в Categorical.codes и доступен только для чтения. Если вы хотите манипулировать кодами, используйте один из API методы на Categoricals.

  • The Categorical.levels атрибут переименован в Categorical.categories.

TimedeltaIndex/скаляр#

Мы вводим новый скалярный тип Timedelta, который является подклассом datetime.timedelta, и ведет себя аналогичным образом, но обеспечивает совместимость с np.timedelta64 типов, а также множество пользовательских представлений, парсинга и атрибутов. Этот тип очень похож на то, как Timestamp работает для datetimes. Это удобный API-контейнер для типа. См. документация. (GH 3009, GH 4533, GH 8209, GH 8187, GH 8190, GH 7869, GH 7661, GH 8345, GH 8471)

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

Timedelta скаляры (и TimedeltaIndex) компонентные поля являются не тот же как компонентные поля на datetime.timedelta объект. Например, .seconds на datetime.timedelta объект возвращает общее количество секунд, объединенных между hours, minutes и seconds. В отличие от этого, pandas Timedelta разделяет часы, минуты, микросекунды и наносекунды отдельно.

# Timedelta accessor
In [9]: tds = pd.Timedelta('31 days 5 min 3 sec')

In [10]: tds.minutes
Out[10]: 5L

In [11]: tds.seconds
Out[11]: 3L

# datetime.timedelta accessor
# this is 5 minutes * 60 + 3 seconds
In [12]: tds.to_pytimedelta().seconds
Out[12]: 303

Примечание: это больше не верно, начиная с v0.16.0, где полная совместимость с datetime.timedelta вводится. См. запись whatsnew для версии 0.16.0

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

До версии 0.15.0 pd.to_timedelta вернет Series для ввода, похожего на список/Series, и np.timedelta64 для скалярного ввода. Теперь будет возвращаться TimedeltaIndex для ввода в виде списка, Series для ввода Series, и Timedelta для скалярного ввода.

Аргументы для pd.to_timedelta теперь (arg,unit='ns',box=True,coerce=False), ранее были (arg,box=True,unit='ns') так как они более логичны.

Создать скаляр

In [9]: pd.Timedelta('1 days 06:05:01.00003')
Out[9]: Timedelta('1 days 06:05:01.000030')

In [10]: pd.Timedelta('15.5us')
Out[10]: Timedelta('0 days 00:00:00.000015500')

In [11]: pd.Timedelta('1 hour 15.5us')
Out[11]: Timedelta('0 days 01:00:00.000015500')

# negative Timedeltas have this string repr
# to be more consistent with datetime.timedelta conventions
In [12]: pd.Timedelta('-1us')
Out[12]: Timedelta('-1 days +23:59:59.999999')

# a NaT
In [13]: pd.Timedelta('nan')
Out[13]: NaT

Доступ к полям для Timedelta

In [14]: td = pd.Timedelta('1 hour 3m 15.5us')

In [15]: td.seconds
Out[15]: 3780

In [16]: td.microseconds
Out[16]: 15

In [17]: td.nanoseconds
Out[17]: 500

Создать TimedeltaIndex

In [18]: pd.TimedeltaIndex(['1 days', '1 days, 00:00:05',
   ....:                    np.timedelta64(2, 'D'),
   ....:                    datetime.timedelta(days=2, seconds=2)])
   ....: 
Out[18]: 
TimedeltaIndex(['1 days 00:00:00', '1 days 00:00:05', '2 days 00:00:00',
                '2 days 00:00:02'],
               dtype='timedelta64[ns]', freq=None)

Создание TimedeltaIndex с обычным диапазоном

In [19]: pd.timedelta_range('1 days', periods=5, freq='D')
Out[19]: TimedeltaIndex(['1 days', '2 days', '3 days', '4 days', '5 days'], dtype='timedelta64[ns]', freq='D')
In [20]: pd.timedelta_range(start='1 days', end='2 days', freq='30T')
Out[20]:
TimedeltaIndex(['1 days 00:00:00', '1 days 00:30:00', '1 days 01:00:00',
                '1 days 01:30:00', '1 days 02:00:00', '1 days 02:30:00',
                '1 days 03:00:00', '1 days 03:30:00', '1 days 04:00:00',
                '1 days 04:30:00', '1 days 05:00:00', '1 days 05:30:00',
                '1 days 06:00:00', '1 days 06:30:00', '1 days 07:00:00',
                '1 days 07:30:00', '1 days 08:00:00', '1 days 08:30:00',
                '1 days 09:00:00', '1 days 09:30:00', '1 days 10:00:00',
                '1 days 10:30:00', '1 days 11:00:00', '1 days 11:30:00',
                '1 days 12:00:00', '1 days 12:30:00', '1 days 13:00:00',
                '1 days 13:30:00', '1 days 14:00:00', '1 days 14:30:00',
                '1 days 15:00:00', '1 days 15:30:00', '1 days 16:00:00',
                '1 days 16:30:00', '1 days 17:00:00', '1 days 17:30:00',
                '1 days 18:00:00', '1 days 18:30:00', '1 days 19:00:00',
                '1 days 19:30:00', '1 days 20:00:00', '1 days 20:30:00',
                '1 days 21:00:00', '1 days 21:30:00', '1 days 22:00:00',
                '1 days 22:30:00', '1 days 23:00:00', '1 days 23:30:00',
                '2 days 00:00:00'],
               dtype='timedelta64[ns]', freq='30T')

Теперь вы можете использовать TimedeltaIndex в качестве индекса объекта pandas

In [20]: s = pd.Series(np.arange(5),
   ....:               index=pd.timedelta_range('1 days', periods=5, freq='s'))
   ....: 

In [21]: s
Out[21]: 
1 days 00:00:00    0
1 days 00:00:01    1
1 days 00:00:02    2
1 days 00:00:03    3
1 days 00:00:04    4
Freq: s, Length: 5, dtype: int64

Вы можете выбирать с частичными строковыми выборками

In [22]: s['1 day 00:00:02']
Out[22]: 2

In [23]: s['1 day':'1 day 00:00:02']
Out[23]: 
1 days 00:00:00    0
1 days 00:00:01    1
1 days 00:00:02    2
Freq: s, Length: 3, dtype: int64

Наконец, комбинация TimedeltaIndex с DatetimeIndex позволяют определенные комбинационные операции, которые NaT сохраняя:

In [24]: tdi = pd.TimedeltaIndex(['1 days', pd.NaT, '2 days'])

In [25]: tdi.tolist()
Out[25]: [Timedelta('1 days 00:00:00'), NaT, Timedelta('2 days 00:00:00')]

In [26]: dti = pd.date_range('20130101', periods=3)

In [27]: dti.tolist()
Out[27]: 
[Timestamp('2013-01-01 00:00:00'),
 Timestamp('2013-01-02 00:00:00'),
 Timestamp('2013-01-03 00:00:00')]

In [28]: (dti + tdi).tolist()
Out[28]: [Timestamp('2013-01-02 00:00:00'), NaT, Timestamp('2013-01-05 00:00:00')]

In [29]: (dti - tdi).tolist()
Out[29]: [Timestamp('2012-12-31 00:00:00'), NaT, Timestamp('2013-01-01 00:00:00')]
  • итерация Series например, list(Series(...)) of timedelta64[ns] до версии 0.15.0 возвращал np.timedelta64 для каждого элемента. Теперь они будут обёрнуты в Timedelta.

Использование памяти#

Реализованы методы для определения использования памяти DataFrame. См. Часто задаваемые вопросы для получения дополнительной информации. (GH 6852).

Новая опция отображения display.memory_usage (см. Опции и настройки) устанавливает поведение по умолчанию для memory_usage аргумент в df.info() метод. По умолчанию display.memory_usage является True.

In [30]: dtypes = ['int64', 'float64', 'datetime64[ns]', 'timedelta64[ns]',
   ....:           'complex128', 'object', 'bool']
   ....: 

In [31]: n = 5000

In [32]: data = {t: np.random.randint(100, size=n).astype(t) for t in dtypes}

In [33]: df = pd.DataFrame(data)

In [34]: df['categorical'] = df['object'].astype('category')

In [35]: df.info()

RangeIndex: 5000 entries, 0 to 4999
Data columns (total 8 columns):
 #   Column           Non-Null Count  Dtype          
---  ------           --------------  -----          
 0   int64            5000 non-null   int64          
 1   float64          5000 non-null   float64        
 2   datetime64[ns]   5000 non-null   datetime64[ns] 
 3   timedelta64[ns]  5000 non-null   timedelta64[ns]
 4   complex128       5000 non-null   complex128     
 5   object           5000 non-null   object         
 6   bool             5000 non-null   bool           
 7   categorical      5000 non-null   category       
dtypes: bool(1), category(1), complex128(1), datetime64[ns](1), float64(1), int64(1), object(1), timedelta64[ns](1)
memory usage: 288.2+ KB

Кроме того memory_usage() является доступным методом для объекта dataframe, который возвращает использование памяти каждого столбца.

In [36]: df.memory_usage(index=True)
Out[36]: 
Index                128
int64              40000
float64            40000
datetime64[ns]     40000
timedelta64[ns]    40000
complex128         80000
object             40000
bool                5000
categorical         9968
Length: 9, dtype: int64

аксессор Series.dt#

Series получил аксессор для краткого возврата свойств, подобных datetime, для values Series, если это Series типа datetime/period. (GH 7207) Это вернет Series, индексированный как существующий Series. См. документация

# datetime
In [37]: s = pd.Series(pd.date_range('20130101 09:10:12', periods=4))

In [38]: s
Out[38]: 
0   2013-01-01 09:10:12
1   2013-01-02 09:10:12
2   2013-01-03 09:10:12
3   2013-01-04 09:10:12
Length: 4, dtype: datetime64[ns]

In [39]: s.dt.hour
Out[39]: 
0    9
1    9
2    9
3    9
Length: 4, dtype: int32

In [40]: s.dt.second
Out[40]: 
0    12
1    12
2    12
3    12
Length: 4, dtype: int32

In [41]: s.dt.day
Out[41]: 
0    1
1    2
2    3
3    4
Length: 4, dtype: int32

In [42]: s.dt.freq
Out[42]: 'D'

Это позволяет использовать удобные выражения, такие как:

In [43]: s[s.dt.day == 2]
Out[43]: 
1   2013-01-02 09:10:12
Length: 1, dtype: datetime64[ns]

Вы можете легко создавать преобразования с учетом часового пояса:

In [44]: stz = s.dt.tz_localize('US/Eastern')

In [45]: stz
Out[45]: 
0   2013-01-01 09:10:12-05:00
1   2013-01-02 09:10:12-05:00
2   2013-01-03 09:10:12-05:00
3   2013-01-04 09:10:12-05:00
Length: 4, dtype: datetime64[ns, US/Eastern]

In [46]: stz.dt.tz
Out[46]: 

Вы также можете объединять такие операции в цепочку:

In [47]: s.dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
Out[47]: 
0   2013-01-01 04:10:12-05:00
1   2013-01-02 04:10:12-05:00
2   2013-01-03 04:10:12-05:00
3   2013-01-04 04:10:12-05:00
Length: 4, dtype: datetime64[ns, US/Eastern]

The .dt аксессор работает для типов period и timedelta.

# period
In [48]: s = pd.Series(pd.period_range('20130101', periods=4, freq='D'))

In [49]: s
Out[49]: 
0    2013-01-01
1    2013-01-02
2    2013-01-03
3    2013-01-04
Length: 4, dtype: period[D]

In [50]: s.dt.year
Out[50]: 
0    2013
1    2013
2    2013
3    2013
Length: 4, dtype: int64

In [51]: s.dt.day
Out[51]: 
0    1
1    2
2    3
3    4
Length: 4, dtype: int64
# timedelta
In [52]: s = pd.Series(pd.timedelta_range('1 day 00:00:05', periods=4, freq='s'))

In [53]: s
Out[53]: 
0   1 days 00:00:05
1   1 days 00:00:06
2   1 days 00:00:07
3   1 days 00:00:08
Length: 4, dtype: timedelta64[ns]

In [54]: s.dt.days
Out[54]: 
0    1
1    1
2    1
3    1
Length: 4, dtype: int64

In [55]: s.dt.seconds
Out[55]: 
0    5
1    6
2    7
3    8
Length: 4, dtype: int32

In [56]: s.dt.components
Out[56]: 
   days  hours  minutes  seconds  milliseconds  microseconds  nanoseconds
0     1      0        0        5             0             0            0
1     1      0        0        6             0             0            0
2     1      0        0        7             0             0            0
3     1      0        0        8             0             0            0

[4 rows x 7 columns]

Улучшения обработки часовых поясов#

  • tz_localize(None) для учитывающих часовой пояс Timestamp и DatetimeIndex теперь удаляет часовой пояс, содержащий местное время, ранее это приводило к Exception или TypeError (GH 7812)

    In [58]: ts = pd.Timestamp('2014-08-01 09:00', tz='US/Eastern')
    
    In[59]: ts
    Out[59]: Timestamp('2014-08-01 09:00:00-0400', tz='US/Eastern')
    
    In [60]: ts.tz_localize(None)
    Out[60]: Timestamp('2014-08-01 09:00:00')
    
    In [61]: didx = pd.date_range(start='2014-08-01 09:00', freq='H',
       ....:                      periods=10, tz='US/Eastern')
       ....:
    
    In [62]: didx
    Out[62]:
    DatetimeIndex(['2014-08-01 09:00:00-04:00', '2014-08-01 10:00:00-04:00',
                   '2014-08-01 11:00:00-04:00', '2014-08-01 12:00:00-04:00',
                   '2014-08-01 13:00:00-04:00', '2014-08-01 14:00:00-04:00',
                   '2014-08-01 15:00:00-04:00', '2014-08-01 16:00:00-04:00',
                   '2014-08-01 17:00:00-04:00', '2014-08-01 18:00:00-04:00'],
                  dtype='datetime64[ns, US/Eastern]', freq='H')
    
    In [63]: didx.tz_localize(None)
    Out[63]:
    DatetimeIndex(['2014-08-01 09:00:00', '2014-08-01 10:00:00',
                   '2014-08-01 11:00:00', '2014-08-01 12:00:00',
                   '2014-08-01 13:00:00', '2014-08-01 14:00:00',
                   '2014-08-01 15:00:00', '2014-08-01 16:00:00',
                   '2014-08-01 17:00:00', '2014-08-01 18:00:00'],
                  dtype='datetime64[ns]', freq=None)
    
  • tz_localize теперь принимает ambiguous ключевое слово, которое позволяет передавать массив булевых значений, указывающих, относится ли дата к летнему времени или нет, 'NaT' для установки времени перехода в NaT, 'infer' для определения летнего/нелетнего времени и 'raise' (по умолчанию) для AmbiguousTimeError будет вызвано. См. документация для дополнительных деталей (GH 7943)

  • DataFrame.tz_localize и DataFrame.tz_convert теперь принимает необязательный level аргумент для локализации конкретного уровня MultiIndex (GH 7846)

  • Timestamp.tz_localize и Timestamp.tz_convert теперь вызывают TypeError в случаях ошибок, а не Exception (GH 8025)

  • временной ряд/индекс, локализованный в UTC, при вставке в Series/DataFrame сохранит часовой пояс UTC (а не будет наивным) datetime64[ns]) как object тип данных (GH 8411)

  • Timestamp.__repr__ отображает dateutil.tz.tzoffset info (GH 7907)

Улучшения моментов скользящих/расширяющихся окон#

  • rolling_min(), rolling_max(), rolling_cov(), и rolling_corr() теперь возвращают объекты со всеми NaN когда len(arg) < min_periods <= window вместо вызова исключения. (Это делает все скользящие функции согласованными в этом поведении). (GH 7766)

    До версии 0.15.0

    In [57]: s = pd.Series([10, 11, 12, 13])
    
    In [15]: pd.rolling_min(s, window=10, min_periods=5)
    ValueError: min_periods (5) must be <= window (4)
    

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

    In [4]: pd.rolling_min(s, window=10, min_periods=5)
    Out[4]:
    0   NaN
    1   NaN
    2   NaN
    3   NaN
    dtype: float64
    
  • rolling_max(), rolling_min(), rolling_sum(), rolling_mean(), rolling_median(), rolling_std(), rolling_var(), rolling_skew(), rolling_kurt(), rolling_quantile(), rolling_cov(), rolling_corr(), rolling_corr_pairwise(), rolling_window(), и rolling_apply() с center=True ранее возвращал результат той же структуры, что и входные данные arg с NaN в конечном (window-1)/2 записей.

    Теперь окончательный (window-1)/2 элементы результата вычисляются так, как если бы входные данные arg следовали за (window-1)/2 NaN значения (или с уменьшающимися окнами, в случае rolling_apply()). (GH 7925, GH 8269)

    Предыдущее поведение (обратите внимание, что конечное значение NaN):

    In [7]: pd.rolling_sum(Series(range(4)), window=3, min_periods=0, center=True)
    Out[7]:
    0     1
    1     3
    2     6
    3   NaN
    dtype: float64
    

    Новое поведение (обратите внимание, что конечное значение 5 = sum([2, 3, NaN])):

    In [7]: pd.rolling_sum(pd.Series(range(4)), window=3,
      ....:                min_periods=0, center=True)
    Out[7]:
    0    1
    1    3
    2    6
    3    5
    dtype: float64
    
  • rolling_window() теперь правильно нормализует веса в режиме скользящего среднего (mean=True) так, чтобы вычисленные взвешенные средние (например, 'triang', 'gaussian') распределялись вокруг тех же средних, что и вычисленные без взвешивания (т.е. 'boxcar'). См. примечание о нормализации для получения дополнительных сведений. (GH 7618)

    In [58]: s = pd.Series([10.5, 8.8, 11.4, 9.7, 9.3])
    

    Поведение до версии 0.15.0:

    In [39]: pd.rolling_window(s, window=3, win_type='triang', center=True)
    Out[39]:
    0         NaN
    1    6.583333
    2    6.883333
    3    6.683333
    4         NaN
    dtype: float64
    

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

    In [10]: pd.rolling_window(s, window=3, win_type='triang', center=True)
    Out[10]:
    0       NaN
    1     9.875
    2    10.325
    3    10.025
    4       NaN
    dtype: float64
    
  • Удалено center аргумент из всех expanding_ функции (см. list), как результаты, полученные при center=True не имело особого смысла. (GH 7925)

  • Добавлен опциональный ddof аргумент для expanding_cov() и rolling_cov(). Значение по умолчанию для 1 обратно совместим. (GH 8279)

  • Документировано ddof аргумент для expanding_var(), expanding_std(), rolling_var(), и rolling_std(). Поддержка этих функций для ddof аргумент (со значением по умолчанию 1) ранее не был задокументирован. (GH 8064)

  • ewma(), ewmstd(), ewmvol(), ewmvar(), ewmcov(), и ewmcorr() теперь интерпретируют min_periods таким же образом, как rolling_*() и expanding_*() функции делают: данная запись результата будет NaN если (расширяющееся, в данном случае) окно не содержит по крайней мере min_periods значения. Предыдущее поведение было установлено в NaN the min_periods записи, начиная с первой не- NaN значение. (GH 7977)

    Предыдущее поведение (обратите внимание, что значения начинаются с индекса 2, что является min_periods после индекса 0 (индекс первого непустого значения):

    In [59]: s  = pd.Series([1, None, None, None, 2, 3])
    
    In [51]: pd.ewma(s, com=3., min_periods=2)
    Out[51]:
    0         NaN
    1         NaN
    2    1.000000
    3    1.000000
    4    1.571429
    5    2.189189
    dtype: float64
    

    Новое поведение (обратите внимание, что значения начинаются с индекса 4, расположение 2-го (поскольку min_periods=2) непустое значение):

    In [2]: pd.ewma(s, com=3., min_periods=2)
    Out[2]:
    0         NaN
    1         NaN
    2         NaN
    3         NaN
    4    1.759644
    5    2.383784
    dtype: float64
    
  • ewmstd(), ewmvol(), ewmvar(), ewmcov(), и ewmcorr() теперь имеют необязательный adjust аргумент, так же как ewma() делает, влияя на то, как рассчитываются веса. Значение по умолчанию для adjust является True, что обратно совместимо. См. Функции экспоненциально взвешенных моментов для подробностей. (GH 7911)

  • ewma(), ewmstd(), ewmvol(), ewmvar(), ewmcov(), и ewmcorr() теперь имеют необязательный ignore_na аргумент. Когда ignore_na=False (по умолчанию), пропущенные значения учитываются в расчёте весов. Когда ignore_na=True (что воспроизводит поведение до версии 0.15.0), пропущенные значения игнорируются в расчёте весов. (GH 7543)

    In [7]: pd.ewma(pd.Series([None, 1., 8.]), com=2.)
    Out[7]:
    0    NaN
    1    1.0
    2    5.2
    dtype: float64
    
    In [8]: pd.ewma(pd.Series([1., None, 8.]), com=2.,
      ....:         ignore_na=True)  # pre-0.15.0 behavior
    Out[8]:
    0    1.0
    1    1.0
    2    5.2
    dtype: float64
    
    In [9]: pd.ewma(pd.Series([1., None, 8.]), com=2.,
      ....:         ignore_na=False)  # new default
    Out[9]:
    0    1.000000
    1    1.000000
    2    5.846154
    dtype: float64
    

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

    По умолчанию (ignore_na=False) ewm*() расчёт весов функций при наличии пропущенных значений отличается от версий до 0.15.0. Для воспроизведения расчёта весов до версии 0.15.0 при наличии пропущенных значений необходимо явно указать ignore_na=True.

  • Ошибка в expanding_cov(), expanding_corr(), rolling_cov(), rolling_cor(), ewmcov(), и ewmcorr() возвращение результатов с колонками, отсортированными по имени, и выдача ошибки для неуникальных колонок; теперь обрабатывает неуникальные колонки и возвращает колонки в исходном порядке (за исключением случая двух DataFrame с pairwise=False, где поведение не изменилось) (GH 7542)

  • Ошибка в rolling_count() и expanding_*() функции, ненужно выдающие сообщение об ошибке для данных нулевой длины (GH 8056)

  • Ошибка в rolling_apply() и expanding_apply() интерпретация min_periods=0 как min_periods=1 (GH 8080)

  • Ошибка в expanding_std() и expanding_var() для одного значения, вызывая запутанное сообщение об ошибке (GH 7900)

  • Ошибка в rolling_std() и rolling_var() для одного значения, производя 0 вместо NaN (GH 7900)

  • Ошибка в ewmstd(), ewmvol(), ewmvar(), и ewmcov() расчет факторов устранения смещения при bias=False (по умолчанию). Ранее использовался неправильный постоянный множитель, основанный на adjust=True, ignore_na=Trueи бесконечного числа наблюдений. Теперь используется другой коэффициент для каждой записи, основанный на фактических весах (аналогично обычному N/(N-1) фактор). В частности, для одной точки значение NaN возвращается, когда bias=False, тогда как ранее значение (приблизительно) 0 был возвращен.

    Например, рассмотрим следующие результаты до версии 0.15.0 для ewmvar(..., bias=False), и соответствующие корректирующие коэффициенты:

    In [60]: s = pd.Series([1., 2., 0., 4.])
    
    In [89]: pd.ewmvar(s, com=2., bias=False)
    Out[89]:
    0   -2.775558e-16
    1    3.000000e-01
    2    9.556787e-01
    3    3.585799e+00
    dtype: float64
    
    In [90]: pd.ewmvar(s, com=2., bias=False) / pd.ewmvar(s, com=2., bias=True)
    Out[90]:
    0    1.25
    1    1.25
    2    1.25
    3    1.25
    dtype: float64
    

    Обратите внимание, что запись 0 приблизительно равно 0, а коэффициенты устранения смещения являются константой 1.25. Для сравнения, следующие результаты 0.15.0 имеют NaN для записи 0, и коэффициенты устранения смещения уменьшаются (к 1.25):

    In [14]: pd.ewmvar(s, com=2., bias=False)
    Out[14]:
    0         NaN
    1    0.500000
    2    1.210526
    3    4.089069
    dtype: float64
    
    In [15]: pd.ewmvar(s, com=2., bias=False) / pd.ewmvar(s, com=2., bias=True)
    Out[15]:
    0         NaN
    1    2.083333
    2    1.583333
    3    1.425439
    dtype: float64
    

    См. Функции экспоненциально взвешенных моментов для подробностей. (GH 7912)

Улучшения в модуле SQL IO#

  • Добавлена поддержка для chunksize параметр для to_sql функция. Это позволяет записывать DataFrame частями и избегать ошибок переполнения размера пакета (GH 8062).

  • Добавлена поддержка для chunksize параметр для read_sql функция. Указание этого аргумента вернет итератор по частям результата запроса (GH 2908).

  • Добавлена поддержка записи datetime.date и datetime.time столбцы типа object с to_sql (GH 6932).

  • Добавлена поддержка указания schema для чтения/записи с read_sql_table и to_sql (GH 7441, GH 7952). Например:

    df.to_sql('table', engine, schema='other_schema')  # noqa F821
    pd.read_sql_table('table', engine, schema='other_schema')  # noqa F821
    
  • Добавлена поддержка записи NaN значения с to_sql (GH 2754).

  • Добавлена поддержка записи столбцов datetime64 с to_sql для всех типов баз данных (GH 7103).

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

Критические изменения#

Изменения API, связанные с Categorical (см. здесь подробнее):

  • The Categorical конструктор с двумя аргументами изменился с «коды/метки и уровни» на «значения и уровни (теперь называемые 'категориями')». Это может привести к скрытым ошибкам. Если вы используете Categorical напрямую, пожалуйста, проверьте свой код, изменив его на использование from_codes() конструктор.

    Старый вызов функции (до 0.15.0):

    pd.Categorical([0,1,0,2,1], levels=['a', 'b', 'c'])
    

    придётся адаптировать к следующему, чтобы сохранить то же поведение:

    In [2]: pd.Categorical.from_codes([0,1,0,2,1], categories=['a', 'b', 'c'])
    Out[2]:
    [a, b, a, c, b]
    Categories (3, object): [a, b, c]
    

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

  • До версии 0.15.0 to_timedelta() вернет Series для ввода в виде списка/Series, и np.timedelta64 для скалярного ввода. Теперь он будет возвращать TimedeltaIndex для ввода в виде списка, Series для ввода Series, и Timedelta для скалярного ввода.

Об изменениях API, связанных с функциями rolling и expanding, см. подробный обзор выше.

Другие заметные изменения API:

  • Согласованность при индексировании с .loc и списокоподобный индексатор, когда значения не найдены.

    In [61]: df = pd.DataFrame([['a'], ['b']], index=[1, 2])
    
    In [62]: df
    Out[62]: 
       0
    1  a
    2  b
    
    [2 rows x 1 columns]
    

    В предыдущих версиях была разница между этими двумя конструкциями:

    • df.loc[[3]] вернет фрейм, переиндексированный на 3 (со всеми np.nan значения)

    • df.loc[[3],:] вызовет KeyError.

    Оба теперь будут вызывать KeyError. Правило заключается в том, что как минимум 1 индексатор должен быть найден при использовании данных, подобных списку, и .loc (GH 7999)

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

    • df.loc[[1,3]] вернет фрейм, переиндексированный по [1,3]

    • df.loc[[1,3],:] вызовет KeyError.

    Оба теперь вернут фрейм, переиндексированный по [1,3]. Например,

    In [3]: df.loc[[1, 3]]
    Out[3]:
         0
    1    a
    3  NaN
    
    In [4]: df.loc[[1, 3], :]
    Out[4]:
         0
    1    a
    3  NaN
    

    Это также можно увидеть при индексации по нескольким осям с Panel.

    >>> p = pd.Panel(np.arange(2 * 3 * 4).reshape(2, 3, 4),
    ...              items=['ItemA', 'ItemB'],
    ...              major_axis=[1, 2, 3],
    ...              minor_axis=['A', 'B', 'C', 'D'])
    >>> p
    
    Dimensions: 2 (items) x 3 (major_axis) x 4 (minor_axis)
    Items axis: ItemA to ItemB
    Major_axis axis: 1 to 3
    Minor_axis axis: A to D
    

    Следующее вызовет ошибку KeyError до версии 0.15.0:

    In [5]:
    Out[5]:
       ItemA  ItemD
    1      3    NaN
    2      7    NaN
    3     11    NaN
    

    Кроме того, .loc вызовет исключение Если в MultiIndex с индексом в виде списка не найдены значения:

    In [63]: s = pd.Series(np.arange(3, dtype='int64'),
       ....:               index=pd.MultiIndex.from_product([['A'],
       ....:                                                ['foo', 'bar', 'baz']],
       ....:                                                names=['one', 'two'])
       ....:               ).sort_index()
       ....: 
    
    In [64]: s
    Out[64]: 
    one  two
    A    bar    1
         baz    2
         foo    0
    Length: 3, dtype: int64
    
    In [65]: try:
       ....:     s.loc[['D']]
       ....: except KeyError as e:
       ....:     print("KeyError: " + str(e))
       ....: 
    KeyError: "['D'] not in index"
    
  • Присвоение значений None теперь учитывает тип данных при выборе 'пустого' значения (GH 7941).

    Ранее присваивание None в числовых контейнерах изменял dtype на object (или вызывал ошибку, в зависимости от вызова). Теперь используется NaN:

    In [66]: s = pd.Series([1., 2., 3.])
    
    In [67]: s.loc[0] = None
    
    In [68]: s
    Out[68]: 
    0    NaN
    1    2.0
    2    3.0
    Length: 3, dtype: float64
    

    NaT теперь используется аналогично для контейнеров datetime.

    Для объектных контейнеров мы теперь сохраняем None значения (ранее они преобразовывались в NaN значений).

    In [69]: s = pd.Series(["a", "b", "c"])
    
    In [70]: s.loc[0] = None
    
    In [71]: s
    Out[71]: 
    0    None
    1       b
    2       c
    Length: 3, dtype: object
    

    Чтобы вставить NaN, вы должны явно использовать np.nan. См. документация.

  • В предыдущих версиях обновление объекта pandas на месте не отражалось в других ссылках Python на этот объект. (GH 8511, GH 5104)

    In [72]: s = pd.Series([1, 2, 3])
    
    In [73]: s2 = s
    
    In [74]: s += 1.5
    

    Поведение до версии v0.15.0

    # the original object
    In [5]: s
    Out[5]:
    0    2.5
    1    3.5
    2    4.5
    dtype: float64
    
    
    # a reference to the original object
    In [7]: s2
    Out[7]:
    0    1
    1    2
    2    3
    dtype: int64
    

    Теперь это правильное поведение

    # the original object
    In [75]: s
    Out[75]: 
    0    2.5
    1    3.5
    2    4.5
    Length: 3, dtype: float64
    
    # a reference to the original object
    In [76]: s2
    Out[76]: 
    0    2.5
    1    3.5
    2    4.5
    Length: 3, dtype: float64
    
  • Сделаны как C-основанные, так и Python-движки для read_csv и read_table игнорировать пустые строки во входных данных, а также строки, заполненные пробелами, при условии, что sep не является пробелом. Это изменение API, которое можно контролировать с помощью параметра ключевого слова skip_blank_lines. См. документация (GH 4466)

  • Временной ряд/индекс, локализованный в UTC при вставке в Series/DataFrame, сохранит часовой пояс UTC и будет вставлен как object dtype, а не преобразуется в наивный datetime64[ns] (GH 8411).

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

    В предыдущих версиях это удаляло часовой пояс, теперь он сохраняет часовой пояс, но дает столбец object dtype:

    In [77]: i = pd.date_range('1/1/2011', periods=3, freq='10s', tz='US/Eastern')
    
    In [78]: i
    Out[78]: 
    DatetimeIndex(['2011-01-01 00:00:00-05:00', '2011-01-01 00:00:10-05:00',
                   '2011-01-01 00:00:20-05:00'],
                  dtype='datetime64[ns, US/Eastern]', freq='10s')
    
    In [79]: df = pd.DataFrame({'a': i})
    
    In [80]: df
    Out[80]: 
                              a
    0 2011-01-01 00:00:00-05:00
    1 2011-01-01 00:00:10-05:00
    2 2011-01-01 00:00:20-05:00
    
    [3 rows x 1 columns]
    
    In [81]: df.dtypes
    Out[81]: 
    a    datetime64[ns, US/Eastern]
    Length: 1, dtype: object
    

    Ранее это приводило бы к столбцу datetime64 dtype, но без информации о часовом поясе.

    Поведение присвоения столбца существующему датафрейму как df['a'] = i остается неизменным (это уже возвращало object столбец с часовым поясом).

  • При передаче нескольких уровней в stack(), теперь будет вызывать ValueError когда уровни не являются всеми именами уровней или всеми номерами уровней (GH 7660). См. Изменение формы путем укладки и разложения.

  • Вызвать ValueError в df.to_hdf с 'фиксированным' форматом, если df имеет неуникальные колонки, так как результирующий файл будет поврежден (GH 7761)

  • SettingWithCopy вызывать/предупреждения (в соответствии с опцией mode.chained_assignment) теперь будет выдаваться при установке значения на срезанном DataFrame со смешанными типами данных с использованием цепочечного присваивания. (GH 7845, GH 7950)

    In [1]: df = pd.DataFrame(np.arange(0, 9), columns=['count'])
    
    In [2]: df['group'] = 'b'
    
    In [3]: df.iloc[0:5]['group'] = 'a'
    /usr/local/bin/ipython:1: SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead
    
    See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
    
  • merge, DataFrame.merge, и ordered_merge теперь возвращают тот же тип как left аргумент (GH 7737).

  • Ранее расширение фрейма смешанных типов данных вело себя иначе .append что сохранит типы данных (связано GH 2578, GH 8176):

    In [82]: df = pd.DataFrame([[True, 1], [False, 2]],
       ....:                   columns=["female", "fitness"])
       ....: 
    
    In [83]: df
    Out[83]: 
       female  fitness
    0    True        1
    1   False        2
    
    [2 rows x 2 columns]
    
    In [84]: df.dtypes
    Out[84]: 
    female      bool
    fitness    int64
    Length: 2, dtype: object
    
    # dtypes are now preserved
    In [85]: df.loc[2] = df.loc[1]
    
    In [86]: df
    Out[86]: 
       female  fitness
    0    True        1
    1   False        2
    2   False        2
    
    [3 rows x 2 columns]
    
    In [87]: df.dtypes
    Out[87]: 
    female      bool
    fitness    int64
    Length: 2, dtype: object
    
  • Series.to_csv() теперь возвращает строку, когда path=None, соответствуя поведению DataFrame.to_csv() (GH 8215).

  • read_hdf теперь вызывает IOError когда передается файл, который не существует. Ранее создавался новый пустой файл, и KeyError вызвано (GH 7715).

  • DataFrame.info() теперь завершает вывод символом новой строки (GH 8114)

  • Конкатенация без объектов теперь вызовет ValueError вместо простого Exception.

  • Ошибки слияния теперь будут подклассами ValueError вместо сырых Exception (GH 8501)

  • DataFrame.plot и Series.plot ключевые слова теперь имеют согласованный порядок (GH 8037)

Внутренний рефакторинг#

В версии 0.15.0 Index был внутренне переработан, чтобы больше не наследовать от ndarray но вместо этого подкласс PandasObject, аналогично остальным объектам pandas. Это изменение позволяет очень простое наследование и создание новых типов индексов. Это должно быть прозрачным изменением с очень ограниченными последствиями для API (GH 5080, GH 7439, GH 7796, GH 8024, GH 8367, GH 7997, GH 8522):

  • вам может потребоваться распаковать pickle-файлы pandas версии < 0.15.0 с помощью pd.read_pickle вместо pickle.load. См. документация по pickle

  • при построении графика с PeriodIndex, внутренние оси matplotlib теперь будут массивами Period а не PeriodIndex (это похоже на то, как DatetimeIndex передает массивы datetimes теперь)

  • MultiIndex теперь будет вызывать исключения аналогично другим объектам pandas в отношении проверки истинности, см. здесь (GH 7897).

  • При построении графика DatetimeIndex напрямую с помощью plot функции, метки осей больше не будут форматироваться как даты, а как целые числа (внутреннее представление datetime64). UPDATE Это исправлено в версии 0.15.1, см. здесь.

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

  • Атрибуты Categorical labels и levels атрибуты устарели и переименованы в codes и categories.

  • The outtype аргумент для pd.DataFrame.to_dict был объявлен устаревшим в пользу orient. (GH 7840)

  • The convert_dummies метод устарел в пользу get_dummies (GH 8140)

  • The infer_dst аргумент в tz_localize будет устаревшим в пользу ambiguous для большей гибкости при работе с переходами на летнее время. Заменить infer_dst=True с ambiguous='infer' для того же поведения (GH 7943). См. документация для получения дополнительной информации.

  • Верхнеуровневый pd.value_range был устаревшим и может быть заменен на .describe() (GH 8481)

  • The Index операции над множествами + и - были устаревшими, чтобы предоставить их для операций с числовыми типами на определенных типах индексов. + может быть заменен на .union() или |, и - by .difference(). Кроме того, имя метода Index.diff() устарел и может быть заменён на Index.difference() (GH 8226)

    # +
    pd.Index(['a', 'b', 'c']) + pd.Index(['b', 'c', 'd'])
    
    # should be replaced by
    pd.Index(['a', 'b', 'c']).union(pd.Index(['b', 'c', 'd']))
    
    # -
    pd.Index(['a', 'b', 'c']) - pd.Index(['b', 'c', 'd'])
    
    # should be replaced by
    pd.Index(['a', 'b', 'c']).difference(pd.Index(['b', 'c', 'd']))
    
  • The infer_types аргумент для read_html() теперь не имеет эффекта и объявлен устаревшим (GH 7762, GH 7032).

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

  • Удалить DataFrame.delevel метод в пользу DataFrame.reset_index

Улучшения#

Улучшения в импорте/экспорте файлов Stata:

  • Добавлена поддержка типов данных bool, uint8, uint16 и uint32 в to_stata (GH 7097, GH 7365)

  • Добавлена опция преобразования при импорте файлов Stata (GH 8527)

  • DataFrame.to_stata и StataWriter проверять длину строки на совместимость с ограничениями, накладываемыми в файлах dta, где строки фиксированной длины должны содержать 244 или меньше символов. Попытка записи файлов Stata dta со строками длиннее 244 символов вызывает ValueError. (GH 7858)

  • read_stata и StataReader может импортировать информацию о пропущенных данных в DataFrame установив аргумент convert_missing to True. При использовании этой опции пропущенные значения возвращаются как StataMissingValue объекты и столбцы, содержащие пропущенные значения, имеют object тип данных. (GH 8045)

Улучшения в функциях построения графиков:

  • Добавлен layout ключевое слово для DataFrame.plot. Вы можете передать кортеж из (rows, columns), один из которых может быть -1 для автоматического вывода (GH 6667, GH 8071).

  • Разрешить передачу нескольких осей в DataFrame.plot, hist и boxplot (GH 5353, GH 6970, GH 7069)

  • Добавлена поддержка для c, colormap и colorbar аргументы для DataFrame.plot с kind='scatter' (GH 7780)

  • Гистограмма из DataFrame.plot с kind='hist' (GH 7809), См. документация.

  • Boxplot из DataFrame.plot с kind='box' (GH 7998), См. документация.

Другие:

  • read_csv теперь имеет параметр ключевого слова float_precision который указывает, какой преобразователь чисел с плавающей запятой должен использовать C-движок при разборе, см. здесь (GH 8002, GH 8044)

  • Добавлен searchsorted метод для Series объекты (GH 7447)

  • describe() на DataFrame со смешанными типами более гибкий. Фильтрация столбцов по типу теперь возможна через include/exclude аргументы. См. документация (GH 8164).

    In [88]: df = pd.DataFrame({'catA': ['foo', 'foo', 'bar'] * 8,
       ....:                    'catB': ['a', 'b', 'c', 'd'] * 6,
       ....:                    'numC': np.arange(24),
       ....:                    'numD': np.arange(24.) + .5})
       ....: 
    
    In [89]: df.describe(include=["object"])
    Out[89]: 
           catA catB
    count    24   24
    unique    2    4
    top     foo    a
    freq     16    6
    
    [4 rows x 2 columns]
    
    In [90]: df.describe(include=["number", "object"], exclude=["float"])
    Out[90]: 
           catA catB       numC
    count    24   24  24.000000
    unique    2    4        NaN
    top     foo    a        NaN
    freq     16    6        NaN
    mean    NaN  NaN  11.500000
    std     NaN  NaN   7.071068
    min     NaN  NaN   0.000000
    25%     NaN  NaN   5.750000
    50%     NaN  NaN  11.500000
    75%     NaN  NaN  17.250000
    max     NaN  NaN  23.000000
    
    [11 rows x 3 columns]
    

    Запрос всех столбцов возможен с использованием сокращения 'all'

    In [91]: df.describe(include='all')
    Out[91]: 
           catA catB       numC       numD
    count    24   24  24.000000  24.000000
    unique    2    4        NaN        NaN
    top     foo    a        NaN        NaN
    freq     16    6        NaN        NaN
    mean    NaN  NaN  11.500000  12.000000
    std     NaN  NaN   7.071068   7.071068
    min     NaN  NaN   0.000000   0.500000
    25%     NaN  NaN   5.750000   6.250000
    50%     NaN  NaN  11.500000  12.000000
    75%     NaN  NaN  17.250000  17.750000
    max     NaN  NaN  23.000000  23.500000
    
    [11 rows x 4 columns]
    

    Без этих аргументов, describe будет вести себя как раньше, включая только числовые столбцы или, если их нет, только категориальные столбцы. См. также документация

  • Добавлен split в качестве опции для orient аргумент в pd.DataFrame.to_dict. (GH 7840)

  • The get_dummies метод теперь можно использовать на DataFrames. По умолчанию только категориальные столбцы кодируются как 0 и 1, в то время как другие столбцы остаются без изменений.

    In [92]: df = pd.DataFrame({'A': ['a', 'b', 'a'], 'B': ['c', 'c', 'b'],
       ....:                 'C': [1, 2, 3]})
       ....: 
    
    In [93]: pd.get_dummies(df)
    Out[93]: 
       C    A_a    A_b    B_b    B_c
    0  1   True  False  False   True
    1  2  False   True  False   True
    2  3   True  False   True  False
    
    [3 rows x 5 columns]
    
  • PeriodIndex поддерживает resolution такой же, как DatetimeIndex (GH 7708)

  • pandas.tseries.holiday добавлена поддержка дополнительных праздников и способов их соблюдения (GH 7070)

  • pandas.tseries.holiday.Holiday теперь поддерживает список смещений в Python3 (GH 7070)

  • pandas.tseries.holiday.Holiday теперь поддерживает параметр days_of_week (GH 7070)

  • GroupBy.nth() теперь поддерживает выбор нескольких n-х значений (GH 7910)

    In [94]: business_dates = pd.date_range(start='4/1/2014', end='6/30/2014', freq='B')
    
    In [95]: df = pd.DataFrame(1, index=business_dates, columns=['a', 'b'])
    
    # get the first, 4th, and last date index for each month
    In [96]: df.groupby([df.index.year, df.index.month]).nth([0, 3, -1])
    Out[96]: 
                a  b
    2014-04-01  1  1
    2014-04-04  1  1
    2014-04-30  1  1
    2014-05-01  1  1
    2014-05-06  1  1
    2014-05-30  1  1
    2014-06-02  1  1
    2014-06-05  1  1
    2014-06-30  1  1
    
    [9 rows x 2 columns]
    
  • Period и PeriodIndex поддерживает сложение/вычитание с timedelta-подобные (GH 7966)

    Если Period частота равна D, H, T, S, L, U, N, Timedelta-подобное может быть добавлено, если результат может иметь ту же частоту. В противном случае только то же самое offsets может быть добавлен.

    In [104]: idx = pd.period_range('2014-07-01 09:00', periods=5, freq='H')
    
    In [105]: idx
    Out[105]:
    PeriodIndex(['2014-07-01 09:00', '2014-07-01 10:00', '2014-07-01 11:00',
                 '2014-07-01 12:00', '2014-07-01 13:00'],
                dtype='period[H]')
    
    In [106]: idx + pd.offsets.Hour(2)
    Out[106]:
    PeriodIndex(['2014-07-01 11:00', '2014-07-01 12:00', '2014-07-01 13:00',
                 '2014-07-01 14:00', '2014-07-01 15:00'],
                dtype='period[H]')
    
    In [107]: idx + pd.Timedelta('120m')
    Out[107]:
    PeriodIndex(['2014-07-01 11:00', '2014-07-01 12:00', '2014-07-01 13:00',
                 '2014-07-01 14:00', '2014-07-01 15:00'],
                dtype='period[H]')
    
    In [108]: idx = pd.period_range('2014-07', periods=5, freq='M')
    
    In [109]: idx
    Out[109]: PeriodIndex(['2014-07', '2014-08', '2014-09', '2014-10', '2014-11'], dtype='period[M]')
    
    In [110]: idx + pd.offsets.MonthEnd(3)
    Out[110]: PeriodIndex(['2014-10', '2014-11', '2014-12', '2015-01', '2015-02'], dtype='period[M]')
    
  • Добавлена экспериментальная совместимость с openpyxl для версий >= 2.0. The DataFrame.to_excel метод engine ключевое слово теперь распознает openpyxl1 и openpyxl2 которые будут явно требовать openpyxl v1 и v2 соответственно, завершаясь ошибкой, если запрашиваемая версия недоступна. Параметр openpyxl engine теперь является мета-движком, который автоматически использует любую установленную версию openpyxl. (GH 7177)

  • DataFrame.fillna теперь может принимать DataFrame в качестве значения заполнения (GH 8377)

  • Передача нескольких уровней в stack() теперь будет работать при передаче нескольких номеров уровней (GH 7660). См. Изменение формы путем укладки и разложения.

  • set_names(), set_labels(), и set_levels() методы теперь принимают необязательный level аргумент ключевого слова для всех модификаций определенного уровня(ей) MultiIndex. Кроме того, set_names() теперь принимает скалярное строковое значение при работе с Index или на определенном уровне MultiIndex (GH 7792)

    In [97]: idx = pd.MultiIndex.from_product([['a'], range(3), list("pqr")],
       ....:                                  names=['foo', 'bar', 'baz'])
       ....: 
    
    In [98]: idx.set_names('qux', level=0)
    Out[98]: 
    MultiIndex([('a', 0, 'p'),
                ('a', 0, 'q'),
                ('a', 0, 'r'),
                ('a', 1, 'p'),
                ('a', 1, 'q'),
                ('a', 1, 'r'),
                ('a', 2, 'p'),
                ('a', 2, 'q'),
                ('a', 2, 'r')],
               names=['qux', 'bar', 'baz'])
    
    In [99]: idx.set_names(['qux', 'corge'], level=[0, 1])
    Out[99]: 
    MultiIndex([('a', 0, 'p'),
                ('a', 0, 'q'),
                ('a', 0, 'r'),
                ('a', 1, 'p'),
                ('a', 1, 'q'),
                ('a', 1, 'r'),
                ('a', 2, 'p'),
                ('a', 2, 'q'),
                ('a', 2, 'r')],
               names=['qux', 'corge', 'baz'])
    
    In [100]: idx.set_levels(['a', 'b', 'c'], level='bar')
    Out[100]: 
    MultiIndex([('a', 'a', 'p'),
                ('a', 'a', 'q'),
                ('a', 'a', 'r'),
                ('a', 'b', 'p'),
                ('a', 'b', 'q'),
                ('a', 'b', 'r'),
                ('a', 'c', 'p'),
                ('a', 'c', 'q'),
                ('a', 'c', 'r')],
               names=['foo', 'bar', 'baz'])
    
    In [101]: idx.set_levels([['a', 'b', 'c'], [1, 2, 3]], level=[1, 2])
    Out[101]: 
    MultiIndex([('a', 'a', 1),
                ('a', 'a', 2),
                ('a', 'a', 3),
                ('a', 'b', 1),
                ('a', 'b', 2),
                ('a', 'b', 3),
                ('a', 'c', 1),
                ('a', 'c', 2),
                ('a', 'c', 3)],
               names=['foo', 'bar', 'baz'])
    
  • Index.isin теперь поддерживает level аргумент для указания, какой уровень индекса использовать для проверки принадлежности (GH 7892, GH 7890)

    In [1]: idx = pd.MultiIndex.from_product([[0, 1], ['a', 'b', 'c']])
    
    In [2]: idx.values
    Out[2]: array([(0, 'a'), (0, 'b'), (0, 'c'), (1, 'a'), (1, 'b'), (1, 'c')], dtype=object)
    
    In [3]: idx.isin(['a', 'c', 'e'], level=1)
    Out[3]: array([ True, False,  True,  True, False,  True], dtype=bool)
    
  • Index теперь поддерживает duplicated и drop_duplicates. (GH 4060)

    In [102]: idx = pd.Index([1, 2, 3, 4, 1, 2])
    
    In [103]: idx
    Out[103]: Index([1, 2, 3, 4, 1, 2], dtype='int64')
    
    In [104]: idx.duplicated()
    Out[104]: array([False, False, False, False,  True,  True])
    
    In [105]: idx.drop_duplicates()
    Out[105]: Index([1, 2, 3, 4], dtype='int64')
    
  • добавить copy=True аргумент для pd.concat чтобы включить сквозную передачу полных блоков (GH 8252)

  • Добавлена поддержка типов данных numpy 1.8+ (bool_, int_, float_, string_) для преобразования в фрейм данных R (GH 8400)

Производительность#

  • Улучшения производительности в DatetimeIndex.__iter__ для более быстрой итерации (GH 7683)

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

  • Улучшения в Series.transform для значительного повышения производительности (исправлено) (GH 6496)

  • Улучшения производительности в StataReader при чтении больших файлов (GH 8040, GH 8073)

  • Улучшения производительности в StataWriter при записи больших файлов (GH 8079)

  • Улучшения производительности и использования памяти при работе с несколькими ключами groupby (GH 8128)

  • Улучшения производительности в groupby .agg и .apply где встроенные max/min не были сопоставлены с версиями numpy/cython (GH 7722)

  • Улучшение производительности при записи в sql (to_sql) до 50% (GH 8208).

  • Тестирование производительности groupby для большого значения ngroups (GH 6787)

  • Улучшение производительности в CustomBusinessDay, CustomBusinessMonth (GH 8236)

  • Улучшение производительности для MultiIndex.values для многоуровневых индексов, содержащих даты и время (GH 8543)

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

  • Ошибка в pivot_table при использовании полей итогов и словаря aggfunc (GH 8349)

  • Ошибка в read_csv где squeeze=True возвращал бы представление (GH 8217)

  • Ошибка при проверке имени таблицы в read_sql в некоторых случаях (GH 7826).

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

  • Ошибка в типах данных мультииндексов, которые перемешиваются при сохранении DataFrame в таблицу SQL (GH 8021)

  • Ошибка в Series деление на 0 с операндами типов float и integer (GH 7785)

  • Ошибка в Series.astype("unicode") не вызывает unicode на значениях правильно (GH 7758)

  • Ошибка в DataFrame.as_matrix() со смешанными datetime64[ns] и timedelta64[ns] типы данных (GH 7778)

  • Ошибка в HDFStore.select_column() не сохраняет информацию о часовом поясе UTC при выборе DatetimeIndex (GH 7777)

  • Ошибка в to_datetime когда format='%Y%m%d' и coerce=True указаны, тогда как ранее возвращался массив объектов (а не приведенный временной ряд с NaT), (GH 7930)

  • Ошибка в DatetimeIndex и PeriodIndex добавление и вычитание на месте дают другой результат, чем обычные (GH 6527)

  • Ошибка при сложении и вычитании PeriodIndex с PeriodIndex raise TypeError (GH 7741)

  • Ошибка в combine_first с PeriodIndex данные вызывают TypeError (GH 3367)

  • Ошибка в срезе MultiIndex с отсутствующими индексаторами (GH 7866)

  • с функциями, которые не являютсяGH 8132)

  • Регрессия в индексации MultiIndex с нескалярным объектом типа (GH 7914)

  • Ошибка в Timestamp сравнения с == и int64 тип данных (GH 8058)

  • Ошибка в pickle содержит DateOffset может вызывать AttributeError когда normalize атрибут упоминается внутренне (GH 7748)

  • Ошибка в Panel при использовании major_xs и copy=False передается (предупреждение об устаревании не срабатывает из-за отсутствия warnings) (GH 8152).

  • Ошибка в десериализации pickle, которая не срабатывала для контейнеров версии до 0.14.1 с дублирующимися элементами при попытке избежать неоднозначности при сопоставлении элементов блока и менеджера, когда есть только один блок, неоднозначности нет (GH 7794)

  • Ошибка при размещении PeriodIndex в Series преобразуется в int64 тип данных, а не object of Periods (GH 7932)

  • Ошибка в HDFStore итерация при передаче условия where (GH 8014)

  • Ошибка в DataFrameGroupby.transform при преобразовании с переданным несортированным ключом (GH 8046, GH 8430)

  • Ошибка в повторяющихся временных рядах при построении линий и областей может привести к ValueError или неправильный тип (GH 7733)

  • Ошибка в выводе в MultiIndex с datetime.date входные данные (GH 7888)

  • Ошибка в get где IndexError не приведет к возврату значения по умолчанию (GH 7725)

  • Ошибка в offsets.apply, rollforward и rollback может сбросить наносекунды (GH 7697)

  • Ошибка в offsets.apply, rollforward и rollback может вызывать AttributeError if Timestamp имеет dateutil tzinfo (GH 7697)

  • Ошибка при сортировке фрейма с MultiIndex и Float64Index (GH 8017)

  • Ошибка в несогласованном panel setitem с правой частью DataFrame для выравнивания (GH 7763)

  • Ошибка в is_superperiod и is_subperiod не может обрабатывать частоты выше, чем S (GH 7760, GH 7772, GH 7803)

  • Ошибка на 32-битных платформах с Series.shift (GH 8129)

  • Ошибка в PeriodIndex.unique возвращает int64 np.ndarray (GH 7540)

  • Ошибка в groupby.apply с не влияющей на результат мутацией в функции (GH 8467)

  • Ошибка в DataFrame.reset_index который имеет MultiIndex содержит PeriodIndex или DatetimeIndex с tz вызывает ValueError (GH 7746, GH 7793)

  • Ошибка в DataFrame.plot с subplots=True может рисовать ненужные второстепенные деления по осям X и Y (GH 7801)

  • Ошибка в StataReader который не читал метки переменных в 117 файлах из-за различий между документацией Stata и реализацией (GH 7816)

  • Ошибка в StataReader где строки всегда преобразовывались в фиксированную ширину 244 символов независимо от фактического размера строки (GH 7858)

  • Ошибка в DataFrame.plot и Series.plot может игнорировать rot и fontsize ключевые слова (GH 7844)

  • Ошибка в DatetimeIndex.value_counts не сохраняет часовой пояс (GH 7735)

  • Ошибка в PeriodIndex.value_counts приводит к Int64Index (GH 7735)

  • Ошибка в DataFrame.join при выполнении левого соединения по индексу и наличии нескольких совпадений (GH 5391)

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

  • Ошибка в groupby где вызываемые объекты без атрибутов имени выбирали неправильный путь, и создавали DataFrame вместо Series (GH 7929)

  • Ошибка в groupby сообщение об ошибке, когда столбец группировки DataFrame дублируется (GH 7511)

  • Ошибка в read_html где infer_types аргумент принудительно приводил даты некорректно (GH 7762, GH 7032).

  • Ошибка в Series.str.cat с индексом, который был отфильтрован так, чтобы не включать первый элемент (GH 7857)

  • Ошибка в Timestamp не может разобрать nanosecond из строки (GH 7878)

  • Ошибка в Timestamp со строковым смещением и tz результаты некорректны (GH 7833)

  • Ошибка в tslib.tz_convert и tslib.tz_convert_single может возвращать разные результаты (GH 7798)

  • Ошибка в DatetimeIndex.intersection непересекающихся временных меток с tz вызывает IndexError (GH 7880)

  • Ошибка в выравнивании с TimeOps и неуникальными индексами (GH 8363)

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

  • Ошибка в date_range()/DatetimeIndex() когда часовой пояс определялся из входных дат, но возвращались некорректные времена при переходе границ летнего времени (GH 7835, GH 7901).

  • Ошибка в to_excel() где отрицательный знак добавлялся к положительной бесконечности и отсутствовал для отрицательной бесконечности (GH 7949)

  • Ошибка в построении графика area рисует легенду с некорректным alpha когда stacked=True (GH 8027)

  • Period и PeriodIndex сложение/вычитание с np.timedelta64 приводит к некорректным внутренним представлениям (GH 7740)

  • Ошибка в Holiday без смещения или соблюдения (GH 7987)

  • Ошибка в DataFrame.to_latex форматирование, когда столбцы или индекс являются MultiIndex (GH 7982).

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

  • Ошибка в DataFrame.shift где пустые столбцы вызывали бы исключение ZeroDivisionError на numpy 1.7 (GH 8019)

  • Ошибка при установке, когда html_encoding/*.html не был установлен и поэтому некоторые тесты выполнялись некорректно (GH 7927).

  • Ошибка в read_html где bytes объекты не проверялись на наличие в _read (GH 7927).

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

  • Ошибка в трансляции скаляров numpy с DataFrame (GH 8116)

  • Ошибка в pivot_table выполнено с безымянным index и columns вызывает KeyError (GH 8103)

  • Ошибка в DataFrame.plot(kind='scatter') рисует точки и полосы ошибок разными цветами, когда цвет задан c ключевое слово (GH 8081)

  • Ошибка в Float64Index где iat и at не тестировались и не проходили (GH 8092).

  • Ошибка в DataFrame.boxplot() где пределы y не были установлены корректно при создании нескольких осей (GH 7528, GH 5517).

  • Ошибка в read_csv где строковые комментарии обрабатывались некорректно при заданном пользовательском разделителе строк или delim_whitespace=True (GH 8122).

  • Ошибка в read_html где пустые таблицы вызывали StopIteration (GH 7575)

  • Ошибка в приведении типов при установке столбца в блоке того же типа данных (GH 7704)

  • Ошибка при доступе к группам из GroupBy когда исходный группировщик был кортежем (GH 8121).

  • Ошибка в .at который принимал бы целочисленные индексаторы на нецелочисленном индексе и выполнял откат (GH 7814)

  • Ошибка с графиком kde и NaN (GH 8182)

  • Ошибка в GroupBy.count с типом данных float32, где значения nan не исключались (GH 8169).

  • Ошибка с накопленными столбчатыми диаграммами и NaN (GH 8175).

  • Ошибка в resample с неравномерно делимыми смещениями (например, '7s') (GH 8371)

  • Ошибка в методах интерполяции с limit ключевое слово, когда значения не требуют интерполяции (GH 7173).

  • Ошибка, где col_space был проигнорирован в DataFrame.to_string() когда header=False (GH 8230).

  • Ошибка с DatetimeIndex.asof неправильное сопоставление частичных строк и возврат неверной даты (GH 8245).

  • Ошибка в методах построения графиков, изменяющих глобальные rcParams matplotlib (GH 8242).

  • Ошибка в DataFrame.__setitem__ которая вызывала ошибки при установке столбца датафрейма в разреженный массив (GH 8131)

  • Ошибка, где Dataframe.boxplot() не удалось, когда весь столбец был пустым (GH 8181).

  • Ошибка с перемешанными переменными в radviz визуализация (GH 8199).

  • Ошибка в методах интерполяции с limit ключевое слово, когда значения не требуют интерполяции (GH 7173).

  • Ошибка, где col_space был проигнорирован в DataFrame.to_string() когда header=False (GH 8230).

  • Ошибка в to_clipboard что обрежет длинные данные столбцов (GH 8305)

  • Ошибка в DataFrame терминальный вывод: Установка max_column/max_rows в ноль не вызывала автоматического изменения размера dfs для соответствия ширине/высоте терминала (GH 7180).

  • Ошибка в OLS, где запуск с параметрами “cluster” и “nw_lags” работал некорректно, но также не вызывал ошибку (GH 5884).

  • Ошибка в DataFrame.dropna который интерпретировал несуществующие столбцы в аргументе subset как 'последний столбец' (GH 8303)

  • Ошибка в Index.intersection на немонотонных неуникальных индексах (GH 8362).

  • Ошибка в присваивании маскированной серии, где несоответствие типов нарушало выравнивание (GH 8387)

  • Ошибка в NDFrame.equals дает ложные отрицания с dtype=object (GH 8437)

  • Исправлена ошибка при присваивании с индексатором, где разнообразие типов нарушало выравнивание (GH 8258)

  • Ошибка в NDFrame.loc индексирование, когда имена строк/столбцов терялись, когда целью был список/ndarray (GH 6552)

  • Регрессия в NDFrame.loc индексирование, когда строки/столбцы были преобразованы в Float64Index, если целью был пустой список/ndarray (GH 7774)

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

  • Ошибка в присваивании элемента DataFrame с MultiIndex столбцами, где правые столбцы не были выровнены (GH 7655)

  • Подавление FutureWarning, генерируемого NumPy при сравнении объектных массивов, содержащих NaN, на равенство (GH 7065)

  • Ошибка в DataFrame.eval() где dtype not оператор (~) не был корректно определён как bool.

Участники#

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

  • Aaron Schumacher +

  • Adam Greenhall

  • Andy Hayden

  • Anthony O’Brien +

  • Artemy Kolchinsky +

  • Бен Шиллер +

  • Benedikt Sauer

  • Benjamin Thyreau +

  • BorisVerk +

  • Chris Reynolds +

  • Chris Stoafer +

  • DSM

  • Dav Clark +

  • FragLegs +

  • German Gomez-Herrero +

  • Hsiaoming Yang +

  • Huan Li +

  • Hyungtae Kim +

  • Isaac Slavitt +

  • Джейкоб Шаер

  • Jacob Wasserman +

  • Ян Шульц

  • Jeff Reback

  • Jeff Tratner

  • Jesse Farnham +

  • Joe Bradish +

  • Joerg Rittinger +

  • John W. O’Brien

  • Joris Van den Bossche

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

  • Кайл Мейер

  • Max Chang +

  • Michael Mueller

  • Michael W Schatzow +

  • Mike Kelly

  • Mortada Mehyar

  • Nathan Sanders +

  • Nathan Typanski +

  • Пол Масюрель +

  • Филлип Клауд

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

  • RenzoBertocchi +

  • Росс Петчлер +

  • Shahul Hameed +

  • Шашанк Агарвал +

  • Stephan Hoyer

  • Tom Augspurger

  • TomAugspurger

  • Tony Lorenzo +

  • Wes Turner

  • Wilfred Hughes +

  • Yevgeniy Grechka +

  • Yoshiki Vázquez Baeza +

  • Бехазад Нури +

  • benjamin

  • bjonen +

  • dlovell +

  • dsm054

  • hunterowens +

  • immerrr

  • ischwabacher

  • jmorris0x0 +

  • jnmclarty +

  • jreback

  • klonuo +

  • лексический

  • mcjcode +

  • mtrbean +

  • onesandzeroes

  • rockg

  • seth-p

  • sinhrks

  • someben +

  • stahlous +

  • stas-sl +

  • thatneat +

  • tom-alcorn +

  • неизвестный

  • unutbu

  • zachcp +