cs9*_*s95 7 python eval apply pandas
我有一系列的形式:
s
0 [133, 115, 3, 1]
1 [114, 115, 2, 3]
2 [51, 59, 1, 1]
dtype: object
Run Code Online (Sandbox Code Playgroud)
请注意,其元素是字符串:
s[0]
'[133, 115, 3, 1]'
Run Code Online (Sandbox Code Playgroud)
我正在尝试pd.eval将此字符串解析为一列列表.这适用于此示例数据.
pd.eval(s)
array([[133, 115, 3, 1],
[114, 115, 2, 3],
[51, 59, 1, 1]], dtype=object)
Run Code Online (Sandbox Code Playgroud)
但是,在更大的数据(10K的数量级)上,这很难失败!
len(s)
300000
pd.eval(s)
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么?功能或我的数据有问题吗?
TL; DR
截至v0.21,这是一个bug,也是GitHub上的一个未解决的问题.见GH16289.
为什么我收到此错误?
这(很可能)是pd.eval错误,不能解析超过100行的系列.这是一个例子.
len(s)
300000
pd.eval(s.head(100)) # returns a parsed result
Run Code Online (Sandbox Code Playgroud)
然而,
pd.eval(s.head(101))
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'
Run Code Online (Sandbox Code Playgroud)
无论解析器或引擎如何,此问题都会持续存在.
这个错误是什么意思?
当传递超过100行的系列时,pd.eval操作__repr__系列,而不是其中包含的对象(这是此错误的原因).所述__repr__截短的行,具有替换它们...(省略号).这个省略号被引擎误解为一个Ellipsis对象 -
...
Ellipsis
pd.eval('...')
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'
Run Code Online (Sandbox Code Playgroud)
这正是导致此错误的原因.
我该怎么做才能让它发挥作用?
目前,还没有解决方案(截至2017年12月28日仍然存在问题),但是,有几种解决方法.
选项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
Run Code Online (Sandbox Code Playgroud)
如果数据格式错误,您需要编写一些错误处理代码.你可以用一个功能 -
def safe_parse(x):
try:
return literal_eval(x)
except (SyntaxError, ValueError):
return np.nan # replace with any suitable placeholder value
Run Code Online (Sandbox Code Playgroud)
将此功能传递给apply-
s.apply(safe_parse)
0 [133, 115, 3, 1]
1 [114, 115, 2, 3]
2 [51, 59, 1, 1]
dtype: object
Run Code Online (Sandbox Code Playgroud)
ast适用于任意数量的行,速度慢但可靠.您也可以使用pd.json.loadsJSON数据,应用与之相同的想法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
Run Code Online (Sandbox Code Playgroud)
我没有在更复杂的结构上测试它,但这应该适用于几乎任何基本的数据字符串表示.
你可以在这里找到PyYAML的文档.向下滚动一下,您将找到有关该load功能的更多详细信息.
注意
pd.read_json或pd.io.json.json_normalize开始阅读您的文件.您还可以在读取数据时执行解析,使用read_csv-
s = pd.read_csv(converters=literal_eval, squeeze=True)
Run Code Online (Sandbox Code Playgroud)
凡converters论点将应用功能上的柱子,因为它是阅读,因此,您不必处理后解析.
继续上述观点,如果您正在处理数据帧,请传递dict-
df = pd.read_csv(converters={'col' : literal_eval})
Run Code Online (Sandbox Code Playgroud)
col需要解析的列在哪里您也可以传递pd.json.loads(对于json数据),或者pd.eval(如果您有100行或更少行).
致MaxU和Moondra发现此问题.
你的数据很好,但也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.
[...]
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,记录的行为是将字符串传递给,与/函数类pd.eval的一般(和预期)行为一致。您传递一个字符串,最终得到一个任意对象。evalexec
在我看来,这pandas.eval是有问题的,因为它不会预先拒绝Series输入expr,导致它在面对歧义时进行猜测。事实上,为漂亮打印而设计的Series'的默认缩短__repr__会极大地影响您的结果,这一事实就是这种情况的最好证明。
然后,解决方案是从 XY 问题退一步,使用正确的工具来转换数据,最好pandas.eval完全停止用于此目的。即使在很小的工作情况下Series,你也不能真正确定未来的 pandas 版本不会完全破坏这个“功能”。
| 归档时间: |
|
| 查看次数: |
1287 次 |
| 最近记录: |