我有以下代码声明:
def gigajoule(row):
row['Energy Supply'] *= 1000000
return row
energy = energy.apply(gigajoule, axis = 1)
可能应该有一种方法可以通过使用lambda函数来简化,但我无法弄清楚如何做到这一点。
答案 0 :(得分:2)
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}
但实际上,你的完整功能可以正常工作,而且这个东西更具可读性
答案 1 :(得分:2)
在您的示例代码中,您使用df.apply
与正常使用模式不同。正常用法是从提供的数据生成新的值行而不修改原始数据(请参阅.apply() documentation中有关副作用的警告)。这也是lambda
函数的行为方式 - 它们通过单行计算生成新值,但无法进行直接赋值。但是,在您的情况下,您正在修改您给定的行,然后返回该行。
请注意,您的代码可能正在执行与您期望的完全不同的操作。它执行以下操作:
gigajoule
从数据框gigajoule
修改收到的行,可能会修改原始数据框本身gigajoule
返回修改后的行gigajoule
返回的行汇编为新的数据帧第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的最标准方法:< / p>
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对计算进行矢量化,因此它应该比以前的速度快得多。
答案 2 :(得分:0)
实际上有一种非常简单的方法需要lambda:
energy['Energy Supply'] *= 1000000