2

I am using python 3.X. I am trying to use the eval()dataframe method including custom functions like this

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'T': [0, 10, 0, 10, 10, 30],
    'P': [0, 0, 1000, 1000, 0, 0],
    'S': [25, 25, 25, 25, 40, 40]
})

def custom(A, B, C):
    # some operations

    aux = pd.DataFrame({
        'A': [0, 10, 0, 10, 10, 30],
    })
    return aux.A      # here is where I want to return the numpy array or list, or dataframe column

eq = 'RES = T + @custom(S, T, P) + 2'
df.eval(eq, engine='numexpr', inplace=True)

But I can only return one float or integer value in the function, a simple value.

So I would like to return a numpy array or a list of values because I want to use the result to operate with the rest of the equation variables. I get this error:

TypeError: unhashable type: 'numpy.ndarray'

Another example:

import pandas as pd
import numpy as np
import seawater as sw
from seawater.library import T90conv

df = pd.DataFrame({
    'T': T90conv([0, 10, 0, 10, 10, 30]),
    'P': [0, 0, 1000, 1000, 0, 0],
    'S': [25, 25, 25, 25, 40, 40]
})

cndr = sw.cndr                  # it returns a numpy array
eq = 'NEW = @cndr(S, T, P)'
df.eval(eq, engine='numexpr', inplace=True)

Is that possible? What kind of types can I return? Is there another way to achieve this?

9
  • what is your expected/desired data set? Commented Nov 7, 2017 at 17:05
  • Can't you do this without eval? Commented Nov 7, 2017 at 17:05
  • I would like to operate with the returned value of the function as it were another column. I have added another example @maxu Commented Nov 7, 2017 at 17:14
  • 1
    Yes, you should use them like this sw.cndr(df['T'], df['P'], df['S']) instead of using the dot notation @maxu Commented Nov 7, 2017 at 17:43
  • 1
    @ChesuCR, i couldn't make it work using numexpr. Using engine='python' - it works properly... Commented Nov 7, 2017 at 17:48

1 Answer 1

2

I couldn't make it work using numexpr engine - it always gives me TypeError: unhashable type: 'numpy.ndarray'.

I also tried to convert that numpy.ndarray into list or tuple - it still says: TypeError: unsupported expression type: <class 'tuple'> or TypeError: unhashable type: 'list'

But it does work with python engine:

In [47]: df.eval("NEW = @sw.cndr(S, T, P)", engine='python', inplace=True)

In [48]: df
Out[48]:
      P   S          T       NEW
0     0  25   0.000000  0.498008
1     0  25   9.997601  0.654990
2  1000  25   0.000000  0.506244
3  1000  25   9.997601  0.662975
4     0  40   9.997601  1.000073
5     0  40  29.992802  1.529967

What about the following workaround?

In [77]: df = df.assign(RES=sw.cndr(df['S'], df['T'], df['P'])) \
                .eval("RES = T + RES + 2", inplace=False)

In [78]: df
Out[78]:
      P   S          T        RES
0     0  25   0.000000   2.498008
1     0  25   9.997601  12.652591
2  1000  25   0.000000   2.506244
3  1000  25   9.997601  12.660576
4     0  40   9.997601  12.997674
5     0  40  29.992802  33.522769
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the workaround but I need to do it directly within the expression. I appreciate your help
The next step will be let me choose what function can be used in the expression, because it could be a security hole if the user can execute any function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.