当前位置: 首页 > 知识库问答 >
问题:

AttributeError:“PandaSexpervisitor”对象没有使用pandas eval的属性“visit_Ellipsis”

於英朗
2023-03-14

我有一系列的形式:

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)

然而,在更大的数据(10K的数量级)上,这失败得很惨!

len(s)
300000

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

我错过了什么?函数或我的数据是否有问题?

共有2个答案

斜和硕
2023-03-14

您的数据很好,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。即使在系列很小的工作环境中,您也无法真正确定未来的熊猫版本不会完全破坏此“功能”。

沃驰
2023-03-14

TL; DR
这是一个值得商榷的错误。请参阅开放的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'

无论是解析器还是引擎,此问题始终存在。

此错误是什么意思?
pd.eval对系列的\uuuu repr\uuu操作,而不是对其中包含的对象操作(这是此错误的原因)。\uuuu repr\uuuu截断行,用..替换它们(省略号)。引擎将此省略号误解为省略号对象-

...
Ellipsis

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

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

无论这是预期行为还是不完全行为(许多pandas方法根据输入操作不同,eval可以通过将自身映射到每一行来处理一个系列,这是我最初假设的工作方式),都有待讨论,因为跟踪这一点还有一个未解决的问题。

我能做些什么才能让这一切顺利进行?
目前,还没有解决方案(该问题截至2017年12月28日仍悬而未决),但是,有一些解决办法。

选项1
ast.literal\u 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适用于任意数量的行,速度慢,但可靠。您还可以对json数据使用pd.json.loads,应用与literal\u 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的文档。向下滚动一点,您将发现有关加载功能的更多详细信息。

笔记

>

  • 如果您使用的是JSON数据,那么首先可以使用pd.read\u JSONpd.io.JSON.JSON\u normalize读取文件。

    您还可以在读取数据时使用read\u csv-

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

    其中,converters参数将应用在读取列时传递给该列的函数,因此以后不必处理解析。

    继续上面的观点,如果你正在使用一个数据框,通过一个判决-

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

    其中,col是需要解析的列,您还可以传递pd.json.loads(对于json数据),或pd.eval(如果您有100行或更少)。

    感谢MaxU和Moondra发现了这个问题。

  •  类似资料:
    • 问题内容: 我想转换火花数据框架以使用以下代码添加: 详细的错误消息是: 有人知道我在这里做错了吗?谢谢! 问题答案: 您无法使用数据框,但可以将数据框转换为RDD并通过映射将其映射。在Spark 2.0之前,别名为。使用Spark 2.0,您必须先明确调用。

    • 问题内容: 我如何解决此错误,我是从GitHub下载此代码的。 引发错误 请帮我解决这个问题! 我用了: 我得到这个错误。有人帮我,我只想让它工作为什么这么难? 问题答案: 我怀疑您从中复制代码的地方启用了急切执行功能,即在程序开始时调用了该位置。 您也可以这样做。希望能有所帮助。 更新:请注意,默认情况下,TensorFlow 2.0中启用了急切执行。因此,以上答案仅适用于TensorFlow

    • 问题内容: 下面的代码给出了错误: 码: 问题答案: 从代码中,我可以看到你希望允许用户下载pdf。 现在开始 去 http://localhost:5000

    • 问题内容: 当我尝试时,会发生错误: 我找到了带有pyelasticsearch.py 的链接https://github.com/toastdriven/pyelasticsearch/blob/master/pyelasticsearch.py​​#L424-469,但我不知道它是哪个版本。无论如何,该代码中没有购买我的pyelasticsearch.py​​。任何人都有相同的经历吗?感谢您的

    • 我和cloud composer一起策划了两个数据流工作,它已经工作了一个月了。突然,这两个作业停止工作,并出现以下错误消息: 在作业中,我用存储客户端从google cloud storage下载一个文件。我以为这是因为一些依赖问题。在composer环境中,我安装了google-cloud-storage,但没有指定版本。我尝试指定包的不同版本,但似乎没有任何工作。 谢了!

    • 问题内容: 我正在使用Flask开发论坛模板。当我尝试使用表单在浏览器中创建新线程时,SQLAlchemy抛出AttributeError。当我尝试与论坛到线程实现一对多关系以及与线程到用户实现一对多关系时,出现了问题。 models.py 所有新的帖子/主题,并在views.py中处理 views.py 问题答案: 问题是这样的: 你要使用ORM对象,而不是主键列: 该错误表示整数被解释为ORM