在Pandas DataFrame中,我想根据另一列的值有条件地创建一个新列.在我的应用程序中,DataFrame通常有几百万行,并且唯一条件值的数量很小,大约为1.性能非常重要:生成新列的最快方法是什么?
我在下面创建了一个示例案例,并尝试并比较了不同的方法.在该示例中,条件填充由基于列的值的字典查找表示label (这里:一个1, 2, 3).
lookup_dict = {
1: 100, # arbitrary
2: 200, # arbitrary
3: 300, # arbitrary
}
Run Code Online (Sandbox Code Playgroud)
然后我希望我的DataFrame被填充为:
label output
0 3 300
1 2 200
2 3 300
3 3 300
4 2 200
5 2 200
6 1 100
7 1 100
Run Code Online (Sandbox Code Playgroud)
以下是在10M行上测试的6种不同方法(Nlines测试代码中的参数):
pandas.groupby().apply()pandas.groupby().indices.items()pandas.Series.mapnumpy.select完整的代码在答案的最后提供,包含所有方法的运行时.在比较性能之前,断言每种方法的输出相等.
pandas.groupby().apply()我使用pandas.groupby()上label,然后填充以利用相同的值的每个块apply().
def fill_output(r):
''' called …Run Code Online (Sandbox Code Playgroud) 使用scipy interp2d函数时,我一直有无效的输入错误.事实证明问题来自bisplrep函数,如下所示:
import numpy as np
from scipy import interpolate
# Case 1
x = np.linspace(0,1)
y = np.zeros_like(x)
z = np.ones_like(x)
tck = interpolate.bisplrep(x,y,z) # or interp2d
Run Code Online (Sandbox Code Playgroud)
返回: ValueError: Invalid inputs
事实证明,我给出的测试数据interp2d仅包含第二轴的一个不同值,如上面的测试样本.该bisplrep函数内部interp2d认为它作为一个无效的输出:这可以被认为是可接受的行为:interp2d与bisplrep期待的2D网格,我只是给他们值沿着一条线.
另外,我发现错误信息还不清楚.其中一个可能包括一个测试interp2d来处理这种情况:类似的东西
if len(np.unique(x))==1 or len(np.unique(y))==1:
ValueError ("Can't build 2D splines if x or y values are all the same")
Run Code Online (Sandbox Code Playgroud)
可能足以检测到这种无效输入,并引发更明确的错误消息,甚至直接调用更合适的interp1d函数(这在这里工作得很好)
我以为我已正确理解了这个问题.但是,请考虑以下代码示例:
# Case 2
x = np.linspace(0,1)
y …Run Code Online (Sandbox Code Playgroud)