在您的示例代码中,您使用的 df.apply 与正常使用模式不同。通常的用法是在不修改原始数据的情况下从提供的数据生成新的一行值(请参阅.apply() documentation 中有关副作用的警告)。这也是lambda 函数的行为方式——它们通过单行计算生成新值,但不能进行直接赋值。但是,在您的情况下,您正在修改给定的行,然后返回该行。
请注意,您的代码执行的操作可能与您的预期完全不同。它执行以下操作:
-
gigajoule 从数据框中接收一行
-
gigajoule 修改它收到的行,可能修改原始数据帧本身
-
gigajoule 返回修改后的行
- pandas 将
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 的最标准方式:
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来向量化计算,所以应该比前面的要快很多。