首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AttributeError:“PandasExprVisitor”对象没有属性“PandasExprVisitor_Ellipsis”,使用的是“熊猫级别”

AttributeError:“PandasExprVisitor”对象没有属性“PandasExprVisitor_Ellipsis”,使用的是“熊猫级别”
EN

Stack Overflow用户
提问于 2017-12-28 13:14:30
回答 2查看 4K关注 0票数 8

我有一系列的表格:

代码语言:javascript
复制
s

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

注意,它的元素是字符串:

代码语言:javascript
复制
s[0]
'[133, 115, 3, 1]'

我试图使用pd.eval将这个字符串解析为一个列表列。此方法适用于此示例数据。

代码语言:javascript
复制
pd.eval(s)

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

然而,在更大的数据(10K的顺序)上,这是不幸的失败!

代码语言:javascript
复制
len(s)
300000

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

我在这里错过了什么?这个函数或我的数据有什么问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-29 10:39:15

您的数据是好的,pandas.eval是错误的,但不是您认为的那样。有一个提示在相关的github问题页面中敦促我仔细看看在文件上

代码语言:javascript
复制
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很小的工作情况下,你也不能确定未来的熊猫版本不会完全破坏这个“功能”。

票数 3
EN

Stack Overflow用户

发布于 2017-12-28 13:14:30

TL;博士

这无疑是个早期的错误。请参阅打开的github发行版GH16289

为什么我会犯这个错误?

这是因为pd.eval不能解析超过100行的系列。下面是一个例子。

代码语言:javascript
复制
len(s)
300000

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

然而,

代码语言:javascript
复制
pd.eval(s.head(101))
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'

无论解析器或引擎如何,此问题仍然存在。

这个错误是什么意思?

pd.eval运行在系列的__repr__上,而不是包含在其中的对象(这就是这个错误的原因)。__repr__截断行,将它们替换为... (省略号)。这个省略号被引擎误解为Ellipsis对象-

代码语言:javascript
复制
...
Ellipsis

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

从技术上讲,pd.eval不应该解析一系列字符串(所提到的文档是用来接收字符串的),并且(正如可接受的答案所描述的),它将尝试对结果进行合理的猜测,而不是直接拒绝输入。

不管这是有意的行为还是不完全的行为(许多熊猫方法根据输入操作不同--而eval可以通过将自己映射到每一行来处理一个系列,这也是我最初认为这是如何工作的)是值得讨论的,因为有一个跟踪这一问题的未决问题。

,我能做些什么才能让它起作用呢?

目前,还没有一个解决办法(截至2017年12月28日,这一问题仍未解决),然而,有几个解决办法。

选项1

ast.literal_eval

如果您可以保证没有任何格式错误的字符串,则此选项应立即生效。

代码语言:javascript
复制
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 

如果有可能出现格式错误的数据,则需要编写一些错误处理代码。你可以用一个函数来做-

代码语言:javascript
复制
def safe_parse(x):
    try:
        return literal_eval(x)
    except (SyntaxError, ValueError):
        return np.nan # replace with any suitable placeholder value

将此函数传递给apply -

代码语言:javascript
复制
s.apply(safe_parse)
    
0    [133, 115, 3, 1]
1    [114, 115, 2, 3]
2      [51, 59, 1, 1]
dtype: object

ast适用于任意数量的行,速度慢,但可靠。您还可以对JSON数据使用pd.json.loads,应用与literal_eval相同的思想。

选项2

yaml.load

解析简单数据的另一个很好的选择是,我不久前来自@ayhan的把这个捡起来

代码语言:javascript
复制
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函数的更多细节。

Note

  • 如果您正在处理JSON数据,那么首先使用pd.read_jsonpd.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发现这个问题的功劳。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48008191

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档