I have some slice of program with example df:
import pandas as pd
from math import floor
d = {'ind': ['a', 'b', 'c'], 'col1': [1, 2, 3], 'col2': [4, 5, 6], 'col3': [7, 8, 9], 'spec': [9, 6, 3]}
df = pd.DataFrame(data=d).set_index('ind')
def func(x,y):
return (1-x)*(y 1)*0.9
print(df)
df2 = df.apply(lambda x: func(x, df.spec))
print(df2)
Its working ok, but when i change a bit func and add floor
to it:
def func(x,y):
return floor((1-x)*(y 1)*0.9)
with it i have error:
TypeError: cannot convert the series to <class 'float'>
how can I change df2 or func to get it to work?
EDIT AFTER GOOD ANWSER:
Now i see, that i forgot that i have condition in function, and i need something else to work.
def func(x,y):
if x == 1:
return y
else:
return floor((1-x)*(y 1)*0.9)
In this func with yours answers i get:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
pointing on line if x == 1:
CodePudding user response:
If you want to use floor
from math
module, you have to pass scalar values and not a list-like. You can use a comprehension:
def func(x,y):
return [floor(r) for r in (1-x)*(y 1)*0.9]
print(df.apply(lambda x: func(x, df.spec)))
# Output:
col1 col2 col3 spec
ind
a 0 -27 -54 -72
b -7 -26 -45 -32
c -8 -18 -29 -8
Alternative is to use floor
from numpy
:
def func(x,y):
return np.floor((1-x)*(y 1)*0.9).astype(int)
print(df.apply(lambda x: func(x, df.spec)))
# Output:
col1 col2 col3 spec
ind
a 0 -27 -54 -72
b -7 -26 -45 -32
c -8 -18 -29 -8
Update
Now i see, that i forgot that i have condition in function, and i need something else to work.
def func(x, y):
out = []
for i, j in zip(x, y):
if i == 1:
out.append(j)
else:
out.append(floor((1-i)*(j 1)*0.9))
return out
print(df.apply(lambda x: func(x, df.spec)))
# Output:
col1 col2 col3 spec
ind
a 9 -27 -54 -72
b -7 -26 -45 -32
c -8 -18 -29 -8
But it's really not optimal. You have to use Pandas/NumPy:
def func(x, y):
x = x.mask(x == 1)
r = (1-x)*(y 1)*0.9
return np.floor(r.fillna(y)).astype(int)
print(df.apply(lambda x: func(x, df.spec)))
# Output:
col1 col2 col3 spec
ind
a 9 -27 -54 -72
b -7 -26 -45 -32
c -8 -18 -29 -8