Python, use of lambda



我有以下代码语句:

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

可能应该有一种使用lambda函数来简化的方法,但我无法弄清楚如何做。

在您的示例代码中,您使用的df.apply与正常使用模式不同。正常用法将是从提供的数据中生成新的值,而无需修改原始数据(请参阅.apply()文档中的副作用的警告)。这也是lambda函数行为的方式 - 它们通过单行计算生成新值,但无法进行直接分配。但是,在您的情况下,您正在修改给予的行,然后返回。

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

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

步骤2是非常非标准的(将原始dataFrame修改为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矢量化计算,因此它应该比以前的计算快得多。

lambdas的想法是他们不做"副作用",也就是说,它们只是在输入参数上运行(检查此答案是否更详细)

所以您可以只需返回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}

但实际上,您的完整功能效果很好,而且可以阅读得比此东西

更容易读取

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

energy['Energy Supply'] *= 1000000

最新更新