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