首页 > 解决方案 > 在 Python 中减少多个 lamda 表达式

问题描述

我有一系列 lambda 表达式,我觉得它们可以在某些方面有效地减少。我想知道最好的方法是什么。将它们重写为循环或任何好的解决方案?

df = ( 
    df
    .assign(
        result_1 = lambda x: x['body'].apply(lambda s: function1(s)), 
        result_2 = lambda x: x['body'].apply(lambda s: function2(s)), 
        result_3 = lambda x: x['body'].apply(lambda s: function3(s)),
        result_4 = lambda x: x['mind'].apply(lambda s: function1(s)), 
        result_5 = lambda x: x['mind'].apply(lambda s: function2(s)), 
        result_6 = lambda x: x['mind'].apply(lambda s: function3(s)))
    .assign(
        A_body_label = lambda x: x['result_1'].apply(lambda s: (s[0]['label'])),
        A_body_score = lambda x: x['result_1'].apply(lambda s: (s[0]['score'])),
        B_body_label = lambda x: x['result_2'].apply(lambda s: (s[0]['label'])),
        B_body_score = lambda x: x['result_2'].apply(lambda s: (s[0]['score'])),
        C_body_label = lambda x: x['result_3'].apply(lambda s: (s[0]['label'])),
        C_body_score = lambda x: x['result_3'].apply(lambda s: (s[0]['score'])),
        A_mind_label = lambda x: x['result_4'].apply(lambda s: (s[0]['label'])),
        A_mind_score = lambda x: x['result_4'].apply(lambda s: (s[0]['score'])),
        A_mind_label = lambda x: x['result_5'].apply(lambda s: (s[0]['label'])),
        A_mind_score = lambda x: x['result_5'].apply(lambda s: (s[0]['score'])),
        A_mind_label = lambda x: x['result_6'].apply(lambda s: (s[0]['label'])),
        A_smind_score = lambda x: x['result_6'].apply(lambda s: (s[0]['score'])))

标签: pythonpandaslambda

解决方案


lambda s: function1(s)等价于function1,只是更昂贵,因为首先要调用一个无操作的包装器。

遗憾的是,其他的更难摆脱,因为 Python 不提供对函数组合的内置支持。相反,我会定义生成其他函数的函数。

例如,

def make_result_function(part, f):
    return lambda x: x[part].apply(f)


def foo(result, kind):
    return lambda x: x[result].apply(lambda s: s[0][kind])


df = ( 
    df
    .assign(
        result_1=make_result_function("body", function1), 
        result_2=make_result_function("body", function2),
        result_3=make_result_function("body", function3),
        result_4=make_result_function("mind", function1),
        result_5=make_result_function("mind", function2),
        result_6=make_result_function("mind", function3))
    .assign(
        A_body_label=foo('result_1', 'label'),
        A_body_score=foo('result_1', 'score'),
        B_body_label=foo('result_2', 'label'),
        B_body_score=foo('result_2', 'score'),
        C_body_label=foo('result_3', 'label'),
        C_body_score=foo('result_3', 'score'),
        A_mind_label=foo('result_4', 'label'),
        A_mind_score=foo('result_4', 'score'),
        B_mind_label=foo('result_5', 'label'),
        B_mind_score=foo('result_5', 'score'),
        C_mind_label=foo('result_6', 'label'),
        C_mind_score=foo('result_6', 'score'),
        ))

要查看内置组合如何提供帮助,请定义一个函数pipe

# This is backwards from normal mathematical composition, where
# compose = lambda f, g: lambda x: f(g(x))
def pipe(f, g):
    return lambda x: g(f(x))

我们还将从operator模块中导入一对函数

from operator import itemgetter, methodcaller

df = ( 
    df
    .assign(
        result_1=pipe(itemgetter('body'), methodcaller('apply', function1)), 
        result_2=pipe(itemgetter('body'), methodcaller('apply', function2)), 

        result_3=pipe(itemgetter('body'), methodcaller('apply', function3)), 
        result_4=pipe(itemgetter('mind'), methodcaller('apply', function4)), 
        result_5=pipe(itemgetter('mind'), methodcaller('apply', function5)),
        result_6=pipe(itemgetter('mind'), methodcaller('apply', function6)))
    .assign(
        A_body_label = pipe(itemgetter('result_1'), methodcaller('apply', lambda s: s[0]['label']),
        A_body_score = pipe(itemgetter('result_1'], methodcaller('apply', lambda s: s[0]['score'])),
        B_body_label = pipe(itemgetter('result_2'), methodcaller('apply', lambda s: s[0]['label'])),
        B_body_score = pipe(itemgetter('result_2'], methodcaller('apply', lambda s: s[0]['score'])),
        C_body_label = pipe(itemgetter('result_3'), methodcaller('apply', lambda s: s[0]['label'])),
        C_body_score = pipe(itemgetter('result_3'], methodcaller('apply', lambda s: s[0]['score'])),
        A_mind_label = pipe(itemgetter('result_4'), methodcaller('apply', lambda s: s[0]['label'])),
        A_mind_score = pipe(itemgetter('result_4'], methodcaller('apply', lambda s: s[0]['score'])),
        B_mind_label = pipe(itemgetter('result_5'), methodcaller('apply', lambda s: s[0]['label'])),
        B_mind_score = pipe(itemgetter('result_5'], methodcaller('apply', lambda s: s[0]['score'])),
        C_mind_label = pipe(itemgetter('result_6'), methodcaller('apply', lambda s: s[0]['label'])),
        C_mind_score = pipe(itemgetter('result_6'], methodcaller('apply', lambda s: s[0]['score']))))

现在考虑用 Coconut 编写的相同作业,Coconut是专为函数式编程设计的 Python 超集。特别是,为使用 , 和我们上面编写的函数提供了特殊itemgettermethodcaller语法pipe

df = ( 
    df
    .assign(
        result_1 = .['body'] |> .apply(function1), 
        result_2 = .['body'] |> .apply(function2), 
        result_3 = .['body'] |> .apply(function3),
        result_4 = .['mind'] |> .apply(function4), 
        result_5 = .['mind'] |> .apply(function5), 
        result_6 = .['mind'] |> .apply(function6))
    .assign(
        A_body_label = .['result_1'] |> .apply(.[0] |> .['label']),
        A_body_score = .['result_1'] |> .apply(.[0] |> .['score']),
        B_body_label = .['result_2'] |> .apply(.[0] |> .['label']),
        B_body_score = .['result_2'] |> .apply(.[0] |> .['score']),
        C_body_label = .['result_3'] |> .apply(.[0] |> .['label']),
        C_body_score = .['result_3'] |> .apply(.[0] |> .['score']),
        A_mind_label = .['result_4'] |> .apply(.[0] |> .['label']),
        A_mind_score = .['result_4'] |> .apply(.[0] |> .['score']),
        B_mind_label = .['result_5'] |> .apply(.[0] |> .['label'])
        B_mind_score = .['result_5'] |> .apply(.[0] |> .['score']),
        C_mind_label = .['result_6'] |> .apply(.[0] |> .['label']),
        C_mind_score = .['result_6'] |> .apply(.[0] |> .['score'])))

推荐阅读