Версия 0.12.0 (24 июля 2013)#

Это основной выпуск с версии 0.11.0 и включает несколько новых функций и улучшений, а также большое количество исправлений ошибок.

Основные возможности включают единообразную схему именования I/O API, функции для чтения html, записи MultiIndex в csv файлы, чтения и записи файлов данных STATA, чтения и записи файлов формата JSON, поддержку Python 3 для HDFStore, фильтрация выражений groupby через filter, и обновленный replace процедура, принимающая регулярные выражения.

Изменения API#

  • API ввода-вывода теперь гораздо более согласован с набором функций верхнего уровня reader функции, доступные как pd.read_csv() которые обычно возвращают pandas объект.

    • read_csv

    • read_excel

    • read_hdf

    • read_sql

    • read_json

    • read_html

    • read_stata

    • read_clipboard

    Соответствующий writer функции являются методами объектов, которые доступны как df.to_csv()

    • to_csv

    • to_excel

    • to_hdf

    • to_sql

    • to_json

    • to_html

    • to_stata

    • to_clipboard

  • Исправление операции по модулю и целочисленного деления для Series и DataFrames, чтобы они работали аналогично float типы данных для возврата np.nan или np.inf при необходимости (GH 3590). Это исправляет ошибку numpy, которая обрабатывает integer и float типы данных по-разному.

    In [1]: p = pd.DataFrame({"first": [4, 5, 8], "second": [0, 0, 3]})
    
    In [2]: p % 0
    Out[2]: 
       first  second
    0    NaN     NaN
    1    NaN     NaN
    2    NaN     NaN
    
    In [3]: p % p
    Out[3]: 
       first  second
    0    0.0     NaN
    1    0.0     NaN
    2    0.0     0.0
    
    In [4]: p / p
    Out[4]: 
       first  second
    0    1.0     NaN
    1    1.0     NaN
    2    1.0     1.0
    
    In [5]: p / 0
    Out[5]: 
       first  second
    0    inf     NaN
    1    inf     NaN
    2    inf     inf
    
  • Добавить squeeze ключевое слово для groupby чтобы разрешить редукцию из DataFrame -> Series, если группы уникальны. Это регрессия с версии 0.10.1. Мы возвращаемся к предыдущему поведению. Это означает, что groupby будет возвращать объекты той же формы, независимо от того, уникальны группы или нет. Откат этой проблемы (GH 2893) с (GH 3596).

    In [2]: df2 = pd.DataFrame([{"val1": 1, "val2": 20},
       ...:                     {"val1": 1, "val2": 19},
       ...:                     {"val1": 1, "val2": 27},
       ...:                     {"val1": 1, "val2": 12}])
    
    In [3]: def func(dataf):
       ...:     return dataf["val2"] - dataf["val2"].mean()
       ...:
    
    In [4]: # squeezing the result frame to a series (because we have unique groups)
       ...: df2.groupby("val1", squeeze=True).apply(func)
    Out[4]:
    0    0.5
    1   -0.5
    2    7.5
    3   -7.5
    Name: 1, dtype: float64
    
    In [5]: # no squeezing (the default, and behavior in 0.10.1)
       ...: df2.groupby("val1").apply(func)
    Out[5]:
    val2    0    1    2    3
    val1
    1     0.5 -0.5  7.5 -7.5
    
  • Вызвать исключение при iloc при булевом индексировании с маской на основе меток, например, булева Series, даже с целочисленными метками, вызовет исключение. Поскольку iloc основан исключительно на позиции, метки на Series не выравниваются (GH 3631)

    Этот случай редко используется, и существует множество альтернатив. Это сохраняет iloc API должен быть чисто на основе позиции.

    In [6]: df = pd.DataFrame(range(5), index=list("ABCDE"), columns=["a"])
    
    In [7]: mask = df.a % 2 == 0
    
    In [8]: mask
    Out[8]: 
    A     True
    B    False
    C     True
    D    False
    E     True
    Name: a, dtype: bool
    
    # this is what you should use
    In [9]: df.loc[mask]
    Out[9]: 
       a
    A  0
    C  2
    E  4
    
    # this will work as well
    In [10]: df.iloc[mask.values]
    Out[10]: 
       a
    A  0
    C  2
    E  4
    

    df.iloc[mask] вызовет ValueError

  • The raise_on_error аргумент функций построения графиков удалён. Вместо этого, функции построения графиков вызывают TypeError когда dtype объекта составляет object чтобы напомнить вам избегать object массивы, когда это возможно и поэтому вам следует привести к соответствующему числовому dtype, если вам нужно построить график чего-либо.

  • Добавить colormap ключевое слово для методов построения графиков DataFrame. Принимает либо объект цветовой карты matplotlib (например, matplotlib.cm.jet), либо строковое имя такого объекта (например, 'jet'). Цветовая карта используется для выбора цвета для каждого столбца. Пожалуйста, смотрите Цветовые карты для получения дополнительной информации. (GH 3860)

  • DataFrame.interpolate() теперь устарел. Пожалуйста, используйте DataFrame.fillna() и DataFrame.replace() вместо этого. (GH 3582, GH 3675, GH 3676)

  • the method и axis аргументы DataFrame.replace() устарели

  • DataFrame.replace 's infer_types параметр удалён и теперь выполняет преобразование по умолчанию. (GH 3907)

  • Добавить ключевое слово allow_duplicates to DataFrame.insert чтобы разрешить вставку дублирующегося столбца, если True, по умолчанию False (так же, как до версии 0.12) (GH 3679)

  • Реализовать __nonzero__ для NDFrame объекты (GH 3691, GH 3696)

  • API ввода-вывода

    • добавлена функция верхнего уровня read_excel чтобы заменить следующее, Исходный API устарел и будет удалён в будущей версии

      from pandas.io.parsers import ExcelFile
      
      xls = ExcelFile("path_to_file.xls")
      xls.parse("Sheet1", index_col=None, na_values=["NA"])
      

      С

      import pandas as pd
      
      pd.read_excel("path_to_file.xls", "Sheet1", index_col=None, na_values=["NA"])
      
    • добавлена функция верхнего уровня read_sql что эквивалентно следующему

      from pandas.io.sql import read_frame
      
      read_frame(...)
      
  • DataFrame.to_html и DataFrame.to_latex теперь принимают путь в качестве первого аргумента (GH 3702)

  • Не разрешать astypes на datetime64[ns] кроме object, и timedelta64[ns] to object/int (GH 3425)

  • Поведение datetime64 типы данных изменились в отношении определенных так называемых операций редукции (GH 3726). Следующие операции теперь вызывают TypeError при выполнении на Series и возвращает пустой Series при выполнении на DataFrame аналогично выполнению этих операций на, например, DataFrame of slice объектах:

    • sum, prod, mean, std, var, skew, kurt, corr и cov

  • read_html теперь по умолчанию None при чтении и возвращается к bs4 + html5lib когда lxml не может выполнить парсинг. список парсеров для попыток до успеха также допустим

  • Внутренний pandas иерархия классов изменилась (незначительно). Предыдущая PandasObject теперь называется PandasContainer и новый PandasObject стал базовым классом для PandasContainer а также Index, Categorical, GroupBy, SparseList, и SparseArray (+ их базовые классы). В настоящее время, PandasObject предоставляет строковые методы (из StringMixin). (GH 4090, GH 4092)

  • Новый StringMixin который, учитывая __unicode__ метод, получает строковые методы, совместимые с python 2 и python 3 (__str__, __bytes__, и __repr__). Плюс безопасность строк по всему коду. Теперь используется во многих местах в библиотеке pandas. (GH 4090, GH 4092)

Улучшения ввода-вывода#

  • pd.read_html() теперь может анализировать HTML-строки, файлы или URL-адреса и возвращать DataFrames, благодаря @cpcloud. (GH 3477, GH 3605, GH 3606, GH 3616). Он работает с одиночный парсер бэкенда: BeautifulSoup4 + html5lib См. документацию

    Вы можете использовать pd.read_html() для чтения вывода из DataFrame.to_html() вот так

    In [11]: df = pd.DataFrame({"a": range(3), "b": list("abc")})
    
    In [12]: print(df)
       a  b
    0  0  a
    1  1  b
    2  2  c
    
    In [13]: html = df.to_html()
    
    In [14]: alist = pd.read_html(html, index_col=0)
    
    In [15]: print(df == alist[0])
          a     b
    0  True  True
    1  True  True
    2  True  True
    

    Обратите внимание, что alist вот пример на Python list так pd.read_html() и DataFrame.to_html() не являются обратными.

    • pd.read_html() больше не выполняет жесткое преобразование строк дат (GH 3656).

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

    Возможно, вам придется установить более старую версию BeautifulSoup4, См. документацию по установке

  • Добавлен модуль для чтения и записи файлов Stata: pandas.io.stata (GH 1512) доступно через read_stata функция верхнего уровня для чтения, to_stata Метод DataFrame для записи, См. документацию

  • Добавлен модуль для чтения и записи файлов в формате json: pandas.io.json доступно через read_json функция верхнего уровня для чтения, to_json Метод DataFrame для записи, См. документацию различные проблемы (GH 1226, GH 3804, GH 3876, GH 3867, GH 1305)

  • MultiIndex поддержка столбцов для чтения и записи файлов формата csv

    • The header опция в read_csv теперь принимает список строк, из которых следует читать индекс.

    • Опция, tupleize_cols теперь можно указать в обоих to_csv и read_csv, для обеспечения совместимости с поведением до версии 0.12 при записи и чтении MultIndex столбцы через список кортежей. По умолчанию в 0.12 — записывать списки кортежей и не интерпретировать список кортежей как MultiIndex столбец.

      Примечание: Поведение по умолчанию в версии 0.12 остаётся неизменным по сравнению с предыдущими версиями, но начиная с версии 0.13, по умолчанию to запись и чтение MultiIndex столбцы будут в новом формате. (GH 3571, GH 1651, GH 3141)

    • Если index_col не указан (например, у вас нет индекса или вы написали его с df.to_csv(..., index=False), тогда любой names в индексе столбцов будет потерян.

      In [16]: mi_idx = pd.MultiIndex.from_arrays([[1, 2, 3, 4], list("abcd")], names=list("ab"))
      
      In [17]: mi_col = pd.MultiIndex.from_arrays([[1, 2], list("ab")], names=list("cd"))
      
      In [18]: df = pd.DataFrame(np.ones((4, 2)), index=mi_idx, columns=mi_col)
      
      In [19]: df.to_csv("mi.csv")
      
      In [20]: print(open("mi.csv").read())
      c,,1,2
      d,,a,b
      a,b,,
      1,a,1.0,1.0
      2,b,1.0,1.0
      3,c,1.0,1.0
      4,d,1.0,1.0
      
      
      In [21]: pd.read_csv("mi.csv", header=[0, 1, 2, 3], index_col=[0, 1])
      Out[21]: 
      c                    1                  2
      d                    a                  b
      a   Unnamed: 2_level_2 Unnamed: 3_level_2
      1                  1.0                1.0
      2 b                1.0                1.0
      3 c                1.0                1.0
      4 d                1.0                1.0
      
  • Поддержка HDFStore (через PyTables 3.0.0) на Python3

  • Поддержка итератора через read_hdf который автоматически открывает и закрывает хранилище по завершении итерации. Это только для tables

    In [25]: path = 'store_iterator.h5'
    
    In [26]: pd.DataFrame(np.random.randn(10, 2)).to_hdf(path, 'df', table=True)
    
    In [27]: for df in pd.read_hdf(path, 'df', chunksize=3):
       ....:     print(df)
       ....:
              0         1
    0  0.713216 -0.778461
    1 -0.661062  0.862877
    2  0.344342  0.149565
              0         1
    3 -0.626968 -0.875772
    4 -0.930687 -0.218983
    5  0.949965 -0.442354
              0         1
    6 -0.402985  1.111358
    7 -0.241527 -0.670477
    8  0.049355  0.632633
              0         1
    9 -1.502767 -1.225492
    
  • read_csv теперь будет выдавать более информативное сообщение об ошибке, когда файл не содержит столбцов, например, все символы новой строки

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

  • DataFrame.replace() теперь позволяет использовать регулярные выражения на содержащихся Series с типом данных object. См. раздел примеров в обычной документации Замена через строковое выражение

    Например, вы можете сделать

    In [22]: df = pd.DataFrame({"a": list("ab.."), "b": [1, 2, 3, 4]})
    
    In [23]: df.replace(regex=r"\s*\.\s*", value=np.nan)
    Out[23]: 
         a  b
    0    a  1
    1    b  2
    2  NaN  3
    3  NaN  4
    

    заменить все вхождения строки '.' с нулем или более экземплярами окружающих пробелов с NaN.

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

    In [24]: df.replace(".", np.nan)
    Out[24]: 
         a  b
    0    a  1
    1    b  2
    2  NaN  3
    3  NaN  4
    

    заменить все вхождения строки '.' с NaN.

  • pd.melt() теперь принимает необязательные параметры var_name и value_name для указания пользовательских имён столбцов возвращаемого DataFrame.

  • pd.set_option() теперь позволяет N опций, пар значений (GH 3667).

    Допустим, у нас был опцион 'a.b' и другой вариант 'b.c'. Мы можем установить их одновременно:

    In [31]: pd.get_option('a.b')
    Out[31]: 2
    
    In [32]: pd.get_option('b.c')
    Out[32]: 3
    
    In [33]: pd.set_option('a.b', 1, 'b.c', 4)
    
    In [34]: pd.get_option('a.b')
    Out[34]: 1
    
    In [35]: pd.get_option('b.c')
    Out[35]: 4
    
  • The filter метод для групповых объектов возвращает подмножество исходного объекта. Предположим, мы хотим взять только элементы, принадлежащие группам с суммой группы больше 2.

    In [25]: sf = pd.Series([1, 1, 2, 3, 3, 3])
    
    In [26]: sf.groupby(sf).filter(lambda x: x.sum() > 2)
    Out[26]: 
    3    3
    4    3
    5    3
    dtype: int64
    

    Аргумент filter должна быть функцией, которая, примененная к группе в целом, возвращает True или False.

    Еще одна полезная операция — фильтрация элементов, принадлежащих группам с небольшим количеством участников.

    In [27]: dff = pd.DataFrame({"A": np.arange(8), "B": list("aabbbbcc")})
    
    In [28]: dff.groupby("B").filter(lambda x: len(x) > 2)
    Out[28]: 
       A  B
    2  2  b
    3  3  b
    4  4  b
    5  5  b
    

    В качестве альтернативы удалению проблемных групп, мы можем возвращать объекты с похожей индексацией, где группы, не прошедшие фильтр, заполняются значениями NaN.

    In [29]: dff.groupby("B").filter(lambda x: len(x) > 2, dropna=False)
    Out[29]: 
         A    B
    0  NaN  NaN
    1  NaN  NaN
    2  2.0    b
    3  3.0    b
    4  4.0    b
    5  5.0    b
    6  NaN  NaN
    7  NaN  NaN
    
  • Методы hist для Series и DataFrame теперь принимают figsize аргумент (GH 3834)

  • DatetimeIndex больше не пытается преобразовывать смешанные целочисленные индексы во время операций соединения (GH 3877)

  • Timestamp.min и Timestamp.max теперь представляют действительные экземпляры Timestamp вместо стандартных datetime.min и datetime.max (соответственно), спасибо @SleepingPills

  • read_html теперь вызывает исключение, когда таблицы не найдены и обнаружен BeautifulSoup==4.2.0 (GH 4214)

Экспериментальные функции#

  • Добавлен экспериментальный CustomBusinessDay класс для поддержки DateOffsets с пользовательскими календарями праздников и пользовательскими weekmasks. (GH 2301)

    Примечание

    Это использует numpy.busdaycalendar API, представленный в Numpy 1.7 и поэтому требует Numpy 1.7.0 или новее.

    In [30]: from pandas.tseries.offsets import CustomBusinessDay
    
    In [31]: from datetime import datetime
    
    # As an interesting example, let's look at Egypt where
    # a Friday-Saturday weekend is observed.
    In [32]: weekmask_egypt = "Sun Mon Tue Wed Thu"
    
    # They also observe International Workers' Day so let's
    # add that for a couple of years
    In [33]: holidays = ["2012-05-01", datetime(2013, 5, 1), np.datetime64("2014-05-01")]
    
    In [34]: bday_egypt = CustomBusinessDay(holidays=holidays, weekmask=weekmask_egypt)
    
    In [35]: dt = datetime(2013, 4, 30)
    
    In [36]: print(dt + 2 * bday_egypt)
    2013-05-05 00:00:00
    
    In [37]: dts = pd.date_range(dt, periods=5, freq=bday_egypt)
    
    In [38]: print(pd.Series(dts.weekday, dts).map(pd.Series("Mon Tue Wed Thu Fri Sat Sun".split())))
    2013-04-30    Tue
    2013-05-02    Thu
    2013-05-05    Sun
    2013-05-06    Mon
    2013-05-07    Tue
    Freq: C, dtype: object
    

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

  • Функции построения графиков теперь вызывают TypeError прежде чем пытаться построить график если связанные объекты имеют тип данных object (GH 1818, GH 3572, GH 3911, GH 3912), но они будут пытаться преобразовать объектные массивы в числовые массивы, если возможно, чтобы вы могли, например, построить график объектного массива с плавающими числами. Это происходит до начала рисования, что устраняет появление ложных графиков.

  • fillna методы теперь вызывают TypeError если value параметр является списком или кортежем.

  • Series.str теперь поддерживает итерацию (GH 3638). Вы можете перебирать отдельные элементы каждой строки в Series. Каждая итерация возвращает Series либо с одним символом на каждой позиции исходного Series или NaN. Например,

    In [38]: strs = "go", "bow", "joe", "slow"
    
    In [32]: ds = pd.Series(strs)
    
    In [33]: for s in ds.str:
        ...:     print(s)
    
    0    g
    1    b
    2    j
    3    s
    dtype: object
    0    o
    1    o
    2    o
    3    l
    dtype: object
    0    NaN
    1      w
    2      e
    3      o
    dtype: object
    0    NaN
    1    NaN
    2    NaN
    3      w
    dtype: object
    
    In [41]: s
    Out[41]:
    0    NaN
    1    NaN
    2    NaN
    3      w
    dtype: object
    
    In [42]: s.dropna().values.item() == "w"
    Out[42]: True
    

    Последний элемент, возвращаемый итератором, будет Series содержащий последний элемент самой длинной строки в Series со всеми остальными элементами, являющимися NaN. Здесь, поскольку 'slow' является самой длинной строкой и нет других строк такой же длины 'w' является единственной непустой строкой в полученном Series.

  • HDFStore

    • сохранит атрибуты индекса (freq,tz,name) при воссоздании (GH 3499)

    • будет предупреждать с AttributeConflictWarning если вы пытаетесь добавить индекс с другой частотой, чем существующий, или пытаетесь добавить индекс с другим именем, чем существующий

    • поддерживать столбцы с датами и временными зонами как data_columns (GH 2852)

  • Поддержка неуникальных индексов уточнена (GH 3468).

    • Исправлено: назначение нового индекса дублирующемуся индексу в DataFrame завершалось ошибкой (GH 3468)

    • Исправление создания DataFrame с дублирующимся индексом

    • поддержка ref_locs для разрешения дублирующих индексов между типами данных, позволяет iget всегда находить индекс (даже между типами данных) (GH 2194)

    • applymap на DataFrame с неуникальным индексом теперь работает (предупреждение удалено)GH 2786), и исправить (GH 3230)

    • Исправление to_csv для обработки неуникальных столбцов (GH 3495)

    • Дублирующиеся индексы с getitem будут возвращать элементы в правильном порядке (GH 3455, GH 3457) и обрабатывать отсутствующие элементы, такие как уникальные индексы (GH 3561)

    • Дублирующиеся индексы с пустым DataFrame.from_records вернут корректный фрейм (GH 3562)

    • Concat для создания неуникальных столбцов, когда дубликаты находятся в разных типах данных, исправлено (GH 3602)

    • Разрешить вставку/удаление в неуникальные столбцы (GH 3679)

    • Неуникальная индексация срезом через loc и исправления друзей (GH 3659)

    • Разрешить вставку/удаление в неуникальные столбцы (GH 3679)

    • Расширить reindex для правильной обработки неуникальных индексов (GH 3679)

    • DataFrame.itertuples() теперь работает с фреймами с повторяющимися именами столбцов (GH 3873)

    • Ошибка при не уникальном индексировании через iloc (GH 4017); добавлено takeable аргумент для reindex для выбора на основе местоположения

    • Разрешить не уникальную индексацию в сериях через .ix/.loc и __getitem__ (GH 4246)

    • Исправлена проблема выделения памяти при не-уникальной индексации с .ix/.loc (GH 4280)

  • DataFrame.from_records не принимал пустые recarrays (GH 3682)

  • read_html теперь правильно пропускает тесты (GH 3741)

  • Исправлена ошибка, где DataFrame.replace со скомпилированным регулярным выражением в to_replace аргумент не работал (GH 3907)

  • Улучшено network декоратор теста для перехвата IOError (и, следовательно, URLError а также). Добавлено with_connectivity_check декоратор для явной проверки веб-сайта как прокси для определения наличия сетевого подключения. Плюс, новый optional_args фабрика декораторов для декораторов. (GH 3910, GH 3914)

  • Исправлена проблема тестирования, когда было открыто слишком много сокетов, что приводило к проблеме сброса соединения (GH 3982, GH 3985, GH 4028, GH 4054)

  • Исправлены падающие тесты в test_yahoo, test_google, где символы не извлекались, но к ним осуществлялся доступ (GH 3982, GH 3985, GH 4028, GH 4054)

  • Series.hist теперь будет брать рисунок из текущей среды, если он не передан

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

  • Исправлено выполнение tox в python3, где импорт pickle переписывался несовместимым образом (GH 4062, GH 4063)

  • Исправлена ошибка, когда sharex и sharey не передавались в grouped_hist (GH 4089)

  • Исправлена ошибка в DataFrame.replace где вложенный словарь не перебирался при regex=False (GH 4115)

  • Исправлена ошибка в разборе микросекунд при использовании format аргумент в to_datetime (GH 4152)

  • Исправлена ошибка в PandasAutoDateLocator где invert_xaxis сработал неправильно MilliSecondLocator (GH 3990)

  • Исправлена ошибка в построении графиков, которая не вызывала исключение при недопустимой цветовой карте для matplotlib 1.1.1 (GH 4215)

  • Исправлено отображение легенды в DataFrame.plot(kind='kde') (GH 4216)

  • Исправлена ошибка, при которой срезы Index не сохраняли атрибут name (GH 4226)

  • Исправлена ошибка при инициализации DatetimeIndex с массивом строк в определённом часовом поясе (GH 4229)

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

  • Исправлена ошибка, где get_data_famafrench не использовал правильные границы файлов (GH 4281)

См. полные заметки о выпуске или трекер задач на GitHub для полного списка.

Участники#

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

  • Andy Hayden

  • Chang She

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

  • Damien Garaud

  • Dan Allan

  • Dan Birken

  • Dieter Vandenbussche

  • Dražen Lučanin

  • Gábor Lipták +

  • Jeff Mellen +

  • Джефф Тратнер +

  • Джеффри Тратнер +

  • Jonathan deWerd +

  • Joris Van den Bossche +

  • Juraj Niznan +

  • Karmel Allison

  • Келси Джордал

  • Kevin Stone +

  • Kieran O’Mahony

  • Kyle Meyer +

  • Mike Kelly +

  • PKEuS +

  • Patrick O’Brien +

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

  • 1.#QNAN

  • Skipper Seabold

  • SleepingPills +

  • Тобиас Брандт

  • Tom Farnbauer +

  • TomAugspurger +

  • Trent Hauck +

  • Wes McKinney

  • Wouter Overmeire

  • Yaroslav Halchenko

  • conmai +

  • danielballan +

  • davidshinn +

  • dieterv77

  • duozhang +

  • ejnens +

  • gliptak +

  • jniznan +

  • jreback

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

  • nipunreddevil +

  • ogiaquino +

  • stonebig +

  • tim smith +

  • timmie

  • y-p