【问题标题】:Issues with list comprehension in Lambda functionLambda 函数中的列表理解问题
【发布时间】:2020-01-15 16:40:08
【问题描述】:

我正在尝试在应用程序中构建一个 lambda 函数:

  • 检查输入的列表是否在另一个列表中
  • 如果存在,则将值附加到同一数据框中的另一列

例子:

初始数据框:

id list_1 list_2
1 [1,2,3] []
2 [1,2,4] []
3 [1,3,4] []

现在,我想检查[1,2] 是否存在于list_1 中。如果是,请将test 附加到list_2 列表中。

final_dataframe:

id list_1 list_2
1 [1,2,3] ['test']
2 [1,2,4] ['test']
3 [1,3,4] []

这是我的第一次尝试:

df.apply(lambda row: row['list_2'].append(['test' if all(elem in [1,2] for elem in row['list_1'])]), axis = 1)

但我收到invalid systax 错误。我觉得这可能很简单,但我不知道是什么问题

这是完整的错误:

  File "<ipython-input-126-f45b74393598>", line 3
    movies_test.apply(lambda row: row['displayable'].append(['comedy_drama' if all(elem in ['comedy','drama'] for elem in row['test'])]), axis = 1)
                                                                                                                                      ^
SyntaxError: invalid syntax

【问题讨论】:

  • 无效的语法错误通常会准确地指出您需要修复的地方。分享完整的错误回溯,以便我们查看。无论哪种方式,这个函数对于 lambda 来说都太长了,而且完全不可读。代码不应该不惜一切代价放在一行中,如果您能真正阅读代码,您将有更好的时间进行调试。
  • 那是公平的,写它的时候看起来很简单,但我想它有点失控了。会建议我构建一个单独的函数并将其传递给我的应用函数吗?
  • 我愿意,是的。此外,您收到错误的原因是因为您有一个没有和 else 的单行 if 语句 - 您不能这样做

标签: python pandas lambda apply


【解决方案1】:

您正在使用一个表达式(lambda 只能包含一个表达式),因此必须使用 conditional expression。表达式always产生一个对象,所以条件表达式必须有一个true表达式和一个false表达式,格式为

<true> if <condition> else <false>`

您遗漏了else &lt;false&gt; 部分。

你又犯了三个错误:

  • 您将单个列视为列表列表
  • 您正在附加您的测试是否为真
  • 您正在将一个列表追加到一个列表中,而您想在其中追加一个字符串。

您的测试应该只查看两个元素是否都在列表中;您可以使用集合操作;你想知道{1, 2} 是不是subset of the column values

{1, 2}.issubset(row['list_1'])

然后才将某些内容附加到另一列,因此只有在上述情况为真时,您才想执行row['list_2'].append()。而你想附加一个字符串,所以调用.append('test')

对于else 部分,您可以返回None,因此不要进行追加调用:

row['list_2'].append('test') if {1, 2}.issubset(row['list_1']) else None

或者,在df.apply()电话中就地:

df.apply(lambda row: row['list_2'].append('test') if {1, 2}.issubset(row['list_1']) else None)

但是,如果您使用 apply() 仅返回一个 boolean 值会更好,这样您就可以使用它选择行,然后使用 separate追加到所选行的操作:

test = df.list_1.apply(lambda c: {1, 2}.issubset(c))
df.list_2[test].apply(lambda c: c.append('test'))

这里,test 包含一系列布尔值FalseTrue,对应于list_1 值是{1, 2} 超集的行。该系列可用于选择df.list_2 中的行,您可以在其中执行其他操作,包括追加到每个单元格中的列表对象。

如果您想从附加到嵌套列表对象切换到仅分配不同的值,它的可读性更高,并且更容易更改;例如当子集测试通过时将df.outcome 列设置为'tested',否则设置为'failed',使用numpy.where()

test = df.list_1.apply(lambda c: {1, 2}.issubset(c))
df.outcome = np.where(test, 'tested', 'failed')

【讨论】:

    【解决方案2】:

    这个:

    ['test' if all(elem in [1,2] for elem in row['list_1'])]
    

    是一个不完整的三元表达式。语法应该是:

    a if condition else b
    

    你有

    a if condition
    

    【讨论】:

      【解决方案3】:

      这应该会得到您想要的结果。看起来您的列表理解缺少一些括号。

      mask = [key for key, value in df['list_1'].items() if 1 in value and 2 in value]
      df.loc[mask]['list_2'].apply(lambda x: x.append('test_2'))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-12
        • 2012-11-26
        • 2021-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多