python pandas 如何将函数与数学结合使用 apply 和 lambda
python pandas how to use function with math use apply and lambda
我有一些带有示例 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)
它工作正常,但是当我改变一点 func 并向其添加 floor
时:
def func(x,y):
return floor((1-x)*(y+1)*0.9)
我有错误:
TypeError: cannot convert the series to <class 'float'>
如何更改 df2 或 func 以使其正常工作?
在好的答案后编辑:
现在我明白了,我忘记了我有功能条件,我需要其他东西来工作。
def func(x,y):
if x == 1:
return y
else:
return floor((1-x)*(y+1)*0.9)
在这个包含你的答案的函数中,我得到:
ValueError: The truth value of a Series is ambiguous. Use a.empty,
a.bool(), a.item(), a.any() or a.all().
指向线上if x == 1:
如果您想使用 math
模块中的 floor
,您必须传递标量值而不是类似列表的值。您可以使用理解:
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
替代方法是使用 numpy
中的 floor
:
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
更新
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
但这确实不是最佳选择。你必须使用 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
我有一些带有示例 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)
它工作正常,但是当我改变一点 func 并向其添加 floor
时:
def func(x,y):
return floor((1-x)*(y+1)*0.9)
我有错误:
TypeError: cannot convert the series to <class 'float'>
如何更改 df2 或 func 以使其正常工作?
在好的答案后编辑:
现在我明白了,我忘记了我有功能条件,我需要其他东西来工作。
def func(x,y):
if x == 1:
return y
else:
return floor((1-x)*(y+1)*0.9)
在这个包含你的答案的函数中,我得到:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
指向线上if x == 1:
如果您想使用 math
模块中的 floor
,您必须传递标量值而不是类似列表的值。您可以使用理解:
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
替代方法是使用 numpy
中的 floor
:
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
更新
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
但这确实不是最佳选择。你必须使用 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