通过带有 if 语句的函数对数据框中的数字执行操作

Perform operations on numbers in dataframe through a function with an if statement

我一直在与 pandas 合作,通过定义的函数对数据集进行分析和执行一些冗长的操作(为了方便,也因为我在不涉及 pandas 的操作中使用了相同的函数)。我正在尝试使用 if 和 else 语句根据哪个数字更大来执行一些操作。

我没能在其他答案中找到解决方法。这是我尝试执行的逻辑操作类型的简短示例:

import pandas as pd

df = pd.DataFrame({"A": [177,166,155,125,146,149,192,160,111,85], 
                   "B": [26.2,27,26.8,23.4,23.3,17.5,26.4,25.7,18.9,15.8], 
                   "C": [9.2,99.1,29.3,8.6,8,7.2,10,39.4,47.25,4.5,]})

x = 'A'
y = 'B'
z = 'C'

def test(a,b,c):
    h = a*b/c
    return h

df['D'] = test(df[x],df[y],df[z])

到目前为止,函数一直在为我工作:

print(df['D'])

0    504.065217
1     45.227043
2    141.774744
3    340.116279
4    425.225000
5    362.152778
6    506.880000
7    104.365482
8     44.400000
9    298.444444
Name: D, dtype: float64

我希望让这样的操作正常工作:

def test2(a,b,c):
    if a > b:
        return a*c
    else:
        return b*c

df['E'] = test2(df[x],df[y],df[z])
print(df['E'])

我收到了明显的错误:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

你需要:

df['E'] = df.apply(lambda x: test2(x['A'], x['B'], x['C']) ,1)

输出:

   A    B       C       E
0   177 26.2    9.20    1628.40
1   166 27.0    99.10   16450.60
2   155 26.8    29.30   4541.50
3   125 23.4    8.60    1075.00
4   146 23.3    8.00    1168.00
5   149 17.5    7.20    1072.80
6   192 26.4    10.00   1920.00
7   160 25.7    39.40   6304.00
8   111 18.9    47.25   5244.75
9   85  15.8    4.50    382.50

另一个解决方案是使用 np.where:

df["E"] = np.where(df.A > df.B, df.A*df.C, df.B*df.C)
print(df)
#      A     B      C         E
# 0  177  26.2   9.20   1628.40
# 1  166  27.0  99.10  16450.60
# 2  155  26.8  29.30   4541.50
# 3  125  23.4   8.60   1075.00
# 4  146  23.3   8.00   1168.00
# 5  149  17.5   7.20   1072.80
# 6  192  26.4  10.00   1920.00
# 7  160  25.7  39.40   6304.00
# 8  111  18.9  47.25   5244.75
# 9   85  15.8   4.50    382.50

在这种情况下,np.where 似乎比 apply 更有效率(快 40 倍)。这里的效率结果:

import timeit

def numpy_where(df):
    def func():
        df["E"] = np.where(df.A > df.B, df.A*df.C, df.B*df.C)
    return func


def pandas_apply(df):
    def test2(a, b, c):
        if a > b:
            return a*c
        return b*c

    def func():
        df["E"] = df.apply(lambda x: test2(x['A'], x['B'], x['C']), 1)
    return func

t = timeit.Timer(numpy_where(df))
print(t.timeit(100))
# 0.0711541

t = timeit.Timer(pandas_apply(df))
print(t.timeit(100))
# 2.8589093
#try this (still using a function):

def test2(row):
    if row['A'] > row['B']:
        return row['A'] * row['C']
    else:
        return row['B']*row['C']

df['E'] = df.apply(test2, axis=1)



    A   B       C       D           E
0   177 26.2    9.20    504.065217  1628.40
1   166 27.0    99.10   45.227043   16450.60
2   155 26.8    29.30   141.774744  4541.50
3   125 23.4    8.60    340.116279  1075.00
4   146 23.3    8.00    425.225000  1168.00
5   149 17.5    7.20    362.152778  1072.80
6   192 26.4    10.00   506.880000  1920.00
7   160 25.7    39.40   104.365482  6304.00
8   111 18.9    47.25   44.400000   5244.75
9   85  15.8    4.50    298.444444  382.50

但使用 np.where 是最好的解决方案。