I finally figured out why I was getting a "weird" error in a function call. But I do not understand WHY I got the error or how to avoid it in the future.
The error was:
rates = Qi*np.exp(-Di*(days-T0))
AttributeError: 'float' object has no attribute 'exp'
This question was asked over 5 years ago (Numpy AttributeError: 'float' object has no attribute 'exp' and it is similar to Different behavior of arithmetics on dtype float 'object' and 'float'), but neither answer tells me how to arbitrarily avoid the problem.
I am using pandas and numpy. The function is called as follows:
df3['Model_EXP'], df3['Model_EXPcum'] =arps.arps(days = df3[dayscol], Qi=parmexp[0], Di=parmexp[1], T0=parmexp[2])
where df3 is a dataframe, the column df3[dayscol] is a column of type int64, and parmexp is a tuple containing parameters for the function.
The function was originally written for numpy (not pandas) and expects numpy vectors. The start of the function def is as follows:
def arps(days = None, Qi = None, Di = None, Bi = 0., T0=None, DTMIN=-5., QMIN = 1., Oil=True):
if (not Di or not Qi):
print("Nominal Decline or Rate not entered in routine arps. Stopping.")
sys.exit()
if (np.isnan(np.sum(days))):
print("Error in days passed to routine arps. Some non-days in vector. Stopping.")
sys.exit()
if (Di < 0.):
Di = -1.*Di # just in case someone got their signs wrong
#
rates = np.zeros(len(days))
cums = np.zeros(len(days))
dtval = np.zeros(len(days))
if (T0 == None):
T0 = days[0]
if (Bi == 0.): # Exponential Decline
rates = Qi*np.exp(-Di*(days-T0)) # THIS IS WHERE THINGS GET INTERESTING
I have called this function multiple times in my application. It had always worked. I added another function to call this routine with another dataframe. However, even though this works during the same execution, I started getting the following error:
File "...Local\conda\conda\envs\py36\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "decline_curve_analysis.py", line 993, in predpred
df3['Model_EXP'], df3['Model_EXPcum'] =arps.arps(days = df3[dayscol], Qi=parmexp[0], Di=parmexp[1], T0=parmexp[2])
File "...\PetroPy\DeclineCurves.py", line 110, in arps
rates = Qi*np.exp(-Di*(days-T0))
AttributeError: 'float' object has no attribute 'exp'
I didn't understand why, so I printed out the dataframe just before the function call. The "dayscol" column had different values, but in both working and non-working cases the days vector (which is the df3[dayscol] column) in "int64". However, when I made the following change in the called function:
print("Type of days",days.dtype)
newexp = (-Di*(days-T0))
print("Type of newexp",newexp.dtype)
rates = Qi*np.exp(-Di*(days-T0)) # THIS IS WHERE THINGS GET INTERESTING
I discovered that I got the following response on the calls which worked:
Type of days int64
Type of newexp float64
but got the following for those which failed:
Type of days int64
Type of newexp object
which I've now solved by rewriting my original function to be:
newexp = (-Di*(days-T0))
newexp = newexp.astype(np.float64)
rates = Qi*np.exp(-Di*(days-T0)) # THIS IS WHERE THINGS GET INTERESTING
QUESTION:
Is there a way I can ensure that this doesn't occur again? It's taken me over a day to debug this, and I'm concerned because I have a lot of non-pandas functions that I don't want to fail when I use them in other projects. Is this even related to the way the function is called?
Thanks.