【问题标题】:Python, use of lambdaPython,使用 lambda
【发布时间】:2018-06-07 12:55:57
【问题描述】:

我有以下代码语句:

def gigajoule(row):
 row['Energy Supply'] *= 1000000
 return row
energy = energy.apply(gigajoule, axis = 1)

可能应该有一种方法可以通过使用 lambda 函数来简化,但我不知道该怎么做。

【问题讨论】:

  • Lambdas 不允许您(轻松地)更改输入变量,但是(假设这是 Pandas,在这种情况下您应该适当地标记)看起来这不是必要的副作用,因为无论如何,行都会被输出替换。

标签: python lambda


【解决方案1】:

实际上有一个非常简单的方法确实需要 lambda:

energy['Energy Supply'] *= 1000000

【讨论】:

    【解决方案2】:

    在您的示例代码中,您使用的 df.apply 与正常使用模式不同。通常的用法是在不修改原始数据的情况下从提供的数据生成新的一行值(请参阅.apply() documentation 中有关副作用的警告)。这也是lambda 函数的行为方式——它们通过单行计算生成新值,但不能进行直接赋值。但是,在您的情况下,您正在修改给定的行,然后返回该行。

    请注意,您的代码执行的操作可能与您的预期完全不同。它执行以下操作:

    1. gigajoule 从数据框中接收一行
    2. gigajoule 修改它收到的行,可能修改原始数据帧本身
    3. gigajoule 返回修改后的行
    4. pandas 将gigajoule 返回的行组合成一个新的数据帧
    5. 您将现有数据框替换为新数据框。

    第 2 步非常不标准(修改原始数据帧作为 apply 操作的副作用)。例如,以下代码更改了原来的energy 框架,可能是出乎意料的:

    import pandas as pd
    energy = pd.DataFrame({'Energy Supply': [100, 200, 300], 'Temperature': [201, 202, 203]})
    def gigajoule(row):
        row['Energy Supply'] *= 1000000
        return row
    energy2 = energy.apply(gigajoule, axis = 1)
    energy # has been modified!
    

    您可以将相同的模式与 lambda 一起使用,就像这样,它还会以非标准方式更改原始帧:

    import pandas as pd
    energy = pd.DataFrame({'Energy Supply': [100, 200, 300], 'Temperature': [201, 202, 203]})
    energy2 = energy.apply(
      lambda row: row.set_value('Energy Supply', row['Energy Supply']*1000000), 
      axis=1
    )
    energy # has been modified
    

    您可以通过使用.copy() 来避免对原始帧的非标准副作用,如下所示:

    import pandas as pd
    energy = pd.DataFrame({'Energy Supply': [100, 200, 300], 'Temperature': [201, 202, 203]})
    energy = energy.apply(
      lambda row: row.copy().set_value('Energy Supply', row['Energy Supply']*1000000), 
      axis=1
    )
    

    但由于您实际上并没有尝试生成新的数据框(即,您实际上想要修改现有的数据框),您可以直接这样做,这将是使用 pandas 的最标准方式:

    import pandas as pd
    energy = pd.DataFrame({'Energy Supply': [100, 200, 300], 'Temperature': [201, 202, 203]})
    energy['Energy Supply'] *= 1000000
    # or energy.loc[:, 'Energy Supply'] *= 1000000
    

    这个例子也使用了numpy来向量化计算,所以应该比前面的要快很多。

    【讨论】:

      【解决方案3】:

      lambdas 的想法是它们不做“副作用”,即它们只是对输入参数进行操作(查看this answer 以获得更详细的答案)

      所以你可以返回row,将Energy Supply乘以100万:

      gigajoule = lambda row: dict([(k,v*1000000) if k=='Energy Supply' else (k,v) for k,v in row.items()])
      

      并像这样使用它:

      >>> row = {'something': 1, 'Energy Supply': 1}
      >>> row = gigajoule(row)
      >>> row
      {'Energy Supply': 1000000, 'something': 1}
      

      但实际上,您的完整功能工作得很好,并且比这个东西更具可读性

      【讨论】:

        猜你喜欢
        • 2021-04-13
        • 1970-01-01
        • 2020-12-31
        • 1970-01-01
        • 2021-09-19
        • 2018-06-27
        • 1970-01-01
        • 1970-01-01
        • 2018-04-23
        相关资源
        最近更新 更多