пропущенной строки. Все остальное - желаемое за действительное: P Но комментарии в соответствующих публикациях SO предполагают, что это время от времени сбивает с толку пользователей, поэтому предоставление решения / альтернативы имеет ценность.

я есть серия вида:

s

0    [133, 115, 3, 1]
1    [114, 115, 2, 3]
2      [51, 59, 1, 1]
dtype: object

Обратите внимание, что его элементыстроки:

s[0]
'[133, 115, 3, 1]'

Я пытаюсь использоватьpd.eval разобрать эту строку в столбец списков. Это работает для этого примера данных.

pd.eval(s)

array([[133, 115, 3, 1],
       [114, 115, 2, 3],
       [51, 59, 1, 1]], dtype=object)

Тем не менее, на гораздо больших данных (порядка 10 КБ) это с треском проваливается!

len(s)
300000

pd.eval(s)
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'

Что мне здесь не хватает? Что-то не так с функцией или моими данными?

Ответы на вопрос(2)

Ваши данные в порядке, иpandas.eval глючит, но не так, как вы думаете. Есть подсказкана соответствующей странице выпуска GitHub что побудило меня присмотретьсяв документации.

pandas.eval(expr, parser='pandas', engine=None, truediv=True, local_dict=None,
            global_dict=None, resolvers=(), level=0, target=None, inplace=False)

    Evaluate a Python expression as a string using various backends.

    Parameters:
        expr: str or unicode
            The expression to evaluate. This string cannot contain any Python
            statements, only Python expressions.
        [...]

Как видите, задокументированное поведение должно пройтистроки вpd.evalв соответствии с общим (и ожидаемым) поведениемeval/exec класс функций. Вы передаете строку и в итоге получаете произвольный объект.

Как я вижу это,pandas.eval глючит, потому что не отвергаетSeries входexpr впереди, заставляя его догадываться перед лицом неоднозначности. Тот факт, что по умолчанию сокращениеSeries' __repr__ Разработанный для красивой печати может кардинально повлиять на ваш результат - лучшее доказательство этой ситуации.

Решение - отойти от проблемы XY и использоватьправильный инструмент для преобразования ваших данныхи желательно прекратить использованиеpandas.eval для этого целиком. Даже в рабочих случаях, когдаSeries маленький, вы не можете быть уверены, что будущие версии панд не нарушат эту «функцию» полностью.

 Andras Deak29 дек. 2017 г., 11:53
@ cᴏʟᴅsᴘᴇᴇᴅ в вашем ответе перечислены альтернативы, я просто хотел подчеркнуть, что вместо ожиданияpd.eval чтобы быть "исправленным", нужно выбрать один из них :)
 coldspeed29 дек. 2017 г., 11:52
Итак, вы упомянули проблему XY. Что ты предлагаешь?
 coldspeed29 дек. 2017 г., 11:56
Ах хорошо. Сначала я этого не понимал. Спасибо за разъяснения! Кроме того, я согласен с вашим ответом, потому что в документах не упоминается, что должно быть принято, а что нет. Таким образом, люди делают общую ошибку, полагая, чтоpd.eval будет работать с каждой строкой в ​​серии отдельно, а не со всей серией__repr__ в целом, что и делает.
 Andras Deak29 дек. 2017 г., 11:58
@ cᴏʟᴅsᴘᴇᴇᴅ Я не согласен: документы очень четкоexpr бытьstr/unicode экземпляр. Есть замечание, говорящее "Series а такжеDataFrame объекты поддерживаются и ведут себя так же, как и при обычной оценке Python", но это относится ксодержание пропущенной строки. Все остальное - желаемое за действительное: P Но комментарии в соответствующих публикациях SO предполагают, что это время от времени сбивает с толку пользователей, поэтому предоставление решения / альтернативы имеет ценность.
Решение Вопроса

TL; DR
По состоянию наv0.21, это ошибка и открытый вопрос на GitHub. ВидетьGH16289.

Почему я получаю эту ошибку?
Это (по всей вероятности)pd.evalОшибка, которая не может разобрать серию с более чем 100 строками. Вот пример.

len(s)
300000

pd.eval(s.head(100))  # returns a parsed result

В то время как,

pd.eval(s.head(101))
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'

Эта проблема сохраняется независимо от синтаксического анализатора или движка.

Что означает эта ошибка?
Когда серия с более чем 100 строк пройдена,pd.eval работает на__repr__ серии, а не объекты, содержащиеся в нем (что является причиной этой ошибки).__repr__ усеченные строки, заменяя их... (Многоточие). Этот многоточие неверно истолковывается двигателем какEllipsis объект -

...
Ellipsis

pd.eval('...')
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'

Именно это и является причиной этой ошибки.

Что я могу сделать, чтобы это работало?
На данный момент нет решения (проблема по-прежнему остается открытой на 28.12.2017),тем не мениеЕсть несколько обходных путей.

Опция 1
ast.literal_eval
Эта опция должна работать "из коробки", если вы можете гарантировать, что у вас нет искаженных строк.

from ast import literal_eval

s.apply(literal_eval)

0    [133, 115, 3, 1]
1    [114, 115, 2, 3]
2      [51, 59, 1, 1]
dtype: object 

Если есть вероятность искаженных данных, вам нужно написать небольшой код обработки ошибок. Вы можете сделать это с помощью функции -

def safe_parse(x):
    try:
        return literal_eval(x)
    except (SyntaxError, ValueError):
        return np.nan # replace with any suitable placeholder value

Передайте эту функциюapply -

s.apply(safe_parse)

0    [133, 115, 3, 1]
1    [114, 115, 2, 3]
2      [51, 59, 1, 1]
dtype: object

ast работает для любого числа строк, и медленно, но надежно. Вы также можете использоватьpd.json.loads для данных JSON, применяя те же идеи, что и сliteral_eval.

Вариант 2
yaml.load
Еще один отличный вариант для анализа простых данных, явзял это из @ayhan некоторое время назад.

import yaml
s.apply(yaml.load)

0    [133, 115, 3, 1]
1    [114, 115, 2, 3]
2      [51, 59, 1, 1]
dtype: object

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

Вы можете найти документацию для PyYAMLВот, Прокрутите немного вниз, и вы найдете более подробную информацию оload функция.

Запись

Если вы работаете с данными JSON, возможно, будет удобно прочитать ваш файл, используяpd.read_json или жеpd.io.json.json_normalize начать с.

Вы также можете выполнять синтаксический анализ, как вы читаете в ваших данных, используяread_csv -

s = pd.read_csv(converters=literal_eval, squeeze=True)

Гдеconverters Аргумент будет применять ту функцию, которая передается к столбцу, когда он читается, поэтому вам не придется разбирать его позже.

Продолжая пункт выше, если вы работаете с фреймом данных, передайтеdict -

df =  pd.read_csv(converters={'col' : literal_eval})

гдеcol это столбец, который нужно проанализировать Вы также можете передатьpd.json.loads (для данных JSON), илиpd.eval (если у вас есть 100 строк или меньше).

Кредиты MaxU и Moondra для раскрытия этой проблемы.

 Dark28 дек. 2017 г., 15:15
Я никогда не был на эту ошибку до сегодняшнего дня. Хорошо, что указал на это.
 MaxU28 дек. 2017 г., 14:23
да, я помню тот случай ...;)
 coldspeed28 дек. 2017 г., 14:37
@MaxU Ура! Не могу поверить, что я этого не помнил.
 MaxU28 дек. 2017 г., 14:27
Мне также понравилосьрешение @ ayhan много...
 coldspeed28 дек. 2017 г., 14:25
@MaxU Я убедился в ответе тебе и Мундре. Дайте мне знать, если я могу как-то улучшить ответ!

Ваш ответ на вопрос