在Python/Pandas中,将自定义函数应用于数据帧的列(其中输入包含字符串)最有效的方法是什么?

在Python/Pandas中,将自定义函数应用于数据帧的列(其中输入包含字符串)最有效的方法是什么?,python,pandas,performance,numpy,vectorization,Python,Pandas,Performance,Numpy,Vectorization,我有一个非常大的数据框,其中一列包含数字,另一列包含文本。我想以最有效的方式,基于数字列和文本列以及复杂的自定义函数创建第三列 因此,最有效的方法是使用NumPy矢量化 (下面是简化的示例代码,以澄清我尝试了什么以及我遇到了什么问题。实际的自定义函数非常复杂,但确实需要输入数字列和文本列。通过下面的简化代码,我想了解如何应用将字符串作为整列输入的函数) 到目前为止,这一切都非常完美: def fun_test1(no1, no2): res = no1 + no2 return

我有一个非常大的数据框,其中一列包含数字,另一列包含文本。我想以最有效的方式,基于数字列和文本列以及复杂的自定义函数创建第三列

因此,最有效的方法是使用NumPy矢量化

(下面是简化的示例代码,以澄清我尝试了什么以及我遇到了什么问题。实际的自定义函数非常复杂,但确实需要输入数字列和文本列。通过下面的简化代码,我想了解如何应用将字符串作为整列输入的函数)

到目前为止,这一切都非常完美:

def fun_test1(no1, no2):
    res = no1 + no2
    return res

Test1 = pd.DataFrame({'no1':[1, 2, 3],
                     'no2':[1, 2, 3]})

Test1['result'] = fun_test1(Test1['no1'].values, Test1['no2'].values)

    no1 no2 result
0   1   1   2
1   2   2   4
2   3   3   6
然而,这不起作用,这就是我被卡住的地方:

def fun_test2(no1, text):
    if text == 'one':
        no2 = 1
    elif text == 'two':
        no2 = 2
    elif text == 'three':
        no2 = 3
    res = no1 + no2
    return res

Test2 = pd.DataFrame({'no1':[1, 2, 3],
                      'text':['one', 'two', 'three']})

Test2['result'] = fun_test2(Test2['no1'].values, Test2['text'].values)

ValueError                                Traceback (most recent call last)
<ipython-input-30-a8f100d7d4bd> in <module>()
----> 1 Test2['result'] = fun_test2(Test2['no1'].values, Test2['text'].values)

<ipython-input-27-8347aa91d765> in fun_test2(no1, text)
      1 def fun_test2(no1, text):
----> 2     if text == 'one':
      3         no2 = 1
      4     elif text == 'two':
      5         no2 = 2

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
def fun_test2(编号1,文本):
如果文本==‘一’:
no2=1
elif text==“两个”:
no2=2
elif text==‘三’:
no2=3
res=no1+no2
返回res
Test2=pd.DataFrame({'no1':[1,2,3],
‘text’:[‘一’、‘二’、‘三’]})
Test2['result']=fun_Test2(Test2['no1'].值,Test2['text']值)
ValueError回溯(最近一次调用上次)
在()
---->1 Test2['result']=fun_Test2(Test2['no1'].值,Test2['text']值)
在fun_test2中(第1部分,文本)
1 def fun_测试2(编号1,文本):
---->2如果文本=‘一’:
3 no2=1
4 elif text==“两个”:
5 no2=2
ValueError:包含多个元素的数组的真值不明确。使用a.any()或a.all()
我尝试了更多的变体,但最终无法使用字符串输入实现NumPy矢量化

我做错了什么

如果NumPy矢量化不适用于字符串,那么下一个最有效的方法是什么

def fun_test2(no1, text, idx):
    if text[idx] == 'one':
        no2 = 1
    elif text[idx] == 'two':
        no2 = 2
    elif text[idx] == 'three':
        no2 = 3
    res = no1[idx] + no2
    return res

Test2 = pd.DataFrame({'no1':[1, 2, 3],
                      'text':['one', 'two', 'three']})

Test2['result'] = [fun_test2(Test2['no1'].values, Test2['text'].values, i) for i in range(Test2.shape[0])]
输出:

>>> Test2
   no1   text  result
0    1    one       2
1    2    two       4
2    3  three       6
或回到传统方式,输出相同:

def fun_test2(no1, text):
    if text == 'one':
        no2 = 1
    elif text == 'two':
        no2 = 2
    elif text == 'three':
        no2 = 3
    res = no1 + no2
    return res

Test2 = pd.DataFrame({'no1':[1, 2, 3],
                      'text':['one', 'two', 'three']})

Test2['result'] = [fun_test2(Test2['no1'].values[i], Test2['text'].values[i]) for i in range(Test2.shape[0])]

这回答了你的问题吗?您可以将文本值(基于字典)转换为数字值,然后应用求和列。正如@HenryYik所说,有更简单的方法来完成您要做的事情。但是,如果您仍要使用客户功能,则必须使用
apply
&一次执行一行。出现错误的原因是该条件是对整个列进行检查&有些行可能是
True
,有些行可能是'False',对于您给定的条件,正如错误所说,您必须说
any()
或'all()`来清除此错误。只需将函数的第二行从
if text=='one':
更改为
if(text=='one')。any():
。它可以正常运行,但结果可能不是您想要的。@HenryYik:不会,因为答案是使用标准函数。我需要使用一个相当复杂的自定义函数。我提供的代码非常简单,便于演示。这些代码只是简单的示例代码,用于说明我尝试了什么以及我遇到了什么困难。实际的自定义函数相当复杂,但确实需要输入数字列和文本列。通过这段简化的代码,我想了解如何应用将字符串作为整个列的输入的函数。实际上就是这样:如果一个或多个输入是string.Thx,那么如何有效地将自定义函数应用于整个数据帧列,但这不是非常低效,因为它是一个循环吗?