-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
BUG: pd.eval with engine="numexpr" fails with simple expressions with float literals #59736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I tried forcibly setting sanitize to False in so the problem is twofold: pandas is adding If you do the hack: then |
Thanks for the report. I can reproduce the OP on 2.2.x, but on main I am seeing |
I'm happy to upload my hack to necompiler.py, but it really seems a hack.... The original code was
|
Alternatively, it looks like you could put something here on the pandas side in
|
@Tunneller - it seems to me removing text from |
Well, I assume the root cause is that Pandas decided to send explicit type information to numexpr and didn’t tell the numexpr guys.
Meanwhile Numexpr believes that the string “np.float64” is evidence of a seditious attempt to hack the eval operation. No surprise what happens next.
So I guess the deeper issue is communication, working in silos, etc. Nothing that can’t be solved. Out of my pay grade though.
In the mean-time, the only solution users have is to roll back to the previous pandas version, which seems a shame. Well, that or hack the expression with str.replace()
Regards, John
From: Richard Shadrach ***@***.***>
Sent: Sunday, September 22, 2024 09:27 AM
To: pandas-dev/pandas ***@***.***>
Cc: John Lovell ***@***.***>; Mention ***@***.***>
Subject: Re: [pandas-dev/pandas] BUG: pd.eval with engine="numexpr" fails with simple expressions with float literals (Issue #59736)
@Tunneller <https://github.com/Tunneller> - it seems to me removing text from parsed_expr could have unintended ill-effects, and is likely covering up the deeper issue.
—
Reply to this email directly, view it on GitHub <#59736 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/AEMBZGK3FFLXB5FJQAKVUJDZX3HTPAVCNFSM6AAAAABNYW6B32VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNRWHAYTENRZGY> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/AEMBZGPSC25XMCTZ66KQ74TZX3HTPA5CNFSM6AAAAABNYW6B32WGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTUNCKZBQ.gif> Message ID: ***@***.*** ***@***.***> >
|
Not sure why you state this, on main pandas is giving the result PRs to fix are welcome. |
Completely bizarre. Maybe I had earlier version of panda??
On mine if you sent 4. / 9. to numexp eval, then be necompiler.py died with an Error about invalid string which was caused because only valid string operations defined should be “real” and “imag” whereas pandas had sent the string “np.float64 (4.) / np.float64 (9.)”
Maybe you have a different test case.
What version of Pandas and Numexpr do you have? I’ll install tomorrow.
John
…
On Sep 22, 2024, at 8:28 PM, Richard Shadrach ***@***.***> wrote:
Well, I assume the root cause is that Pandas decided to send explicit type information to numexpr and didn’t tell the numexpr guys.
Meanwhile Numexpr believes that the string “np.float64” is evidence of a seditious attempt to hack the eval operation. No surprise what happens next.
Not sure why you state this, on main pandas is giving the result 0.0. The code is currently seeing that all scalars are integers and sets the return type to being an integer. We should consider the operations along with the scalars and when division is seen, the result should be float.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.
|
I am working off of the main branch with numexpr 2.10.1. |
Hi, on pandas 2.2.2, then pd.eval("1.0/2.0") sent the expression (np.float64(1.0)) / (np.float64(2.0)) which caused numexpr to die. So I think the original post can be closed as fixed. |
There is conceivably a different aspect which is that for integer division while pd.eval("1/2") now returns the correct value of zero, with no complaints, perhaps it should have returned a integer 0 rather than a float64 0.0 I think this is the issue that @rhshadrach found. |
I would expect print(1/2)
# 0.5
print(np.array([1]) / np.array([2]))
# [0.5]
print(pd.Series([1]) / pd.Series([2]))
# 0 0.5
# dtype: float64 Why do you think it should give |
Hi Richard, I had assumed it was integer division, but you are correct, that’s not quite how numexpr does it
>> import numexpr as ne
>> ne.evaluate("1/2")
array(0.5)
>> ne.evaluate("1./2.")
array(0.5)
>> ne.evaluate("1/2")
array(0.5)
>> ne.evaluate("1//2")
array(0, dtype=int32)
Meanwhile with pandas 2.2.3
>> import pandas as pd
>> pd.eval("1/2")
np.float64(0.0)
>> pd.eval("1./2.")
np.float64(0.5)
>> pd.eval("1//2")
np.int64(0)
>> pd.eval("21/9")
np.float64(2.0)
>> pd.eval("21//9")
np.int64(2)
So it seems like pd.eval( (int a) / (int b) ) somehow converts (int a )/(int b) into (float) [ (int a ) // ( int b )]. Not completely intuitive.
But either way, it appears to be a different bug from the one we had posted abut before a few weeks back. I think you can close the first one.
Regards, John
From: Richard Shadrach ***@***.***>
Sent: Monday, September 23, 2024 07:55 PM
To: pandas-dev/pandas ***@***.***>
Cc: John Lovell ***@***.***>; Mention ***@***.***>
Subject: Re: [pandas-dev/pandas] BUG: pd.eval with engine="numexpr" fails with simple expressions with float literals (Issue #59736)
I would expect 1/2 to give 0.5 as it does in Python, NumPy, and pandas.
print(1/2)
# 0.5
print(np.array([1]) / np.array([2]))
# [0.5]
print(pd.Series([1]) / pd.Series([2]))
# 0 0.5
# dtype: float64
Why do you think it should give 0?
—
Reply to this email directly, view it on GitHub <#59736 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/AEMBZGLDWCNZ3JFI7RQCVH3ZYCZ7XAVCNFSM6AAAAABNYW6B32VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNRZHA4DIMZZGY> .
You are receiving this because you were mentioned. <https://github.com/notifications/beacon/AEMBZGJVXB35OMOYYK4XPZ3ZYCZ7XA5CNFSM6AAAAABNYW6B32WGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTUNIGIOY.gif> Message ID: ***@***.*** ***@***.***> >
|
I am leaving this issue open because the example in the OP does not produce the correct result. |
I ran into the issue of
pandas/pandas/core/computation/engines.py Lines 85 to 86 in 23c497b
but in reconstruct_object , typ is numpy.int64 and then typ(obj) becomes 0.pandas/pandas/core/computation/align.py Line 216 in 23c497b
|
Pandas version checks
I have checked that this issue has not already been reported.
I have confirmed this bug exists on the latest version of pandas.
I have confirmed this bug exists on the main branch of pandas.
Reproducible Example
Issue Description
This throws an exception
ValueError: Expression (np.float64(1.0)) / (np.float64(2.0)) has forbidden control characters.
Changing engine to "python" makes it work again. Strangely, replacing the division with any other operator also fixes things. I tried this in a clean venv with just the minimal packages installed.
This is similar to older #54542 but different. If I try to run the expression pandas is generating directly in numexpr I get the same error. Using
sanitize=False
is not enough to make it work howeverThis leads to a different exception:
AttributeError: 'VariableNode' object has no attribute 'float64'
.Not sure if this is really a bug in pandas or numexpr. It seems related to numpy 2.0 as well.
Expected Behavior
It should just return 0.5.
Installed Versions
INSTALLED VERSIONS
commit : d9cdd2e
python : 3.11.7.final.0
python-bits : 64
OS : Darwin
OS-release : 22.6.0
Version : Darwin Kernel Version 22.6.0: Mon Jun 24 01:25:37 PDT 2024; root:xnu-8796.141.3.706.2~1/RELEASE_X86_64
machine : x86_64
processor : i386
byteorder : little
LC_ALL : None
LANG : en_US
LOCALE : en_US.UTF-8
pandas : 2.2.2
numpy : 2.1.1
pytz : 2024.1
dateutil : 2.9.0.post0
setuptools : 65.5.0
pip : 24.2
Cython : None
pytest : None
hypothesis : 6.112.0
sphinx : None
blosc : None
feather : None
xlsxwriter : None
lxml.etree : None
html5lib : None
pymysql : None
psycopg2 : None
jinja2 : None
IPython : None
pandas_datareader : None
adbc-driver-postgresql: None
adbc-driver-sqlite : None
bs4 : None
bottleneck : None
dataframe-api-compat : None
fastparquet : None
fsspec : None
gcsfs : None
matplotlib : None
numba : None
numexpr : 2.10.1
odfpy : None
openpyxl : None
pandas_gbq : None
pyarrow : None
pyreadstat : None
python-calamine : None
pyxlsb : None
s3fs : None
scipy : None
sqlalchemy : None
tables : None
tabulate : None
xarray : None
xlrd : None
zstandard : None
tzdata : None
qtpy : None
pyqt5 : None
The text was updated successfully, but these errors were encountered: