如何使用三元运算符在lambda函数中apply的功能pandas数据帧?
首先,这段代码来自R/plyr,这正是我想要得到的:
ddply(mtcars, .(cyl), summarise, sum(ifelse(carb==4,1,0))/sum(ifelse(carb %in% c(4,1),1,0)))
Run Code Online (Sandbox Code Playgroud)
在上面的函数中,我可以使用ifelse函数 R 的三元运算符来计算结果数据帧。
但是,当我想使用以下代码在 Python/pandas 中执行相同操作时
mtcars.groupby(["cyl"]).apply(lambda x: sum(1 if x["carb"] == 4 else 0) / sum(1 if x["carb"] in (4, 1) else 0))
Run Code Online (Sandbox Code Playgroud)
,出现以下错误:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Run Code Online (Sandbox Code Playgroud)
那么如何计算并获得与 R/plyr 相同的数据帧?
供您参考,如果我使用三元运算符而不对列进行分组,例如
mtcars.apply(lambda x: sum(1 if x["carb"] == 4 else 0) / sum(1 if x["carb"] in (4, 1) else 0), axis=1)
Run Code Online (Sandbox Code Playgroud)
,由于某些原因,我可以获得结果数据框(但这不是我想要做的)。
谢谢。
[更新]
抱歉,在使用三元运算符时,原始示例不是一个好的示例,因为它使用1and 0,可以用作二进制。所以更新后的 R/plyr 代码如下:
ddply(mtcars, .(cyl), summarise, sum(ifelse(carb==4,6,3))/sum(ifelse(carb %in% c(4,1),8,4)))
Run Code Online (Sandbox Code Playgroud)
在这种情况下使用三元运算符是否可行?
我认为你的代码可以翻译成这样:
mtcars.groupby(["cyl"])['carb'].apply(lambda x: sum((x == 4).astype(float)) / sum(x.isin((4, 1))))
Run Code Online (Sandbox Code Playgroud)
玩具示例:
>>> mtcars = pd.DataFrame({'cyl':[8,8,6,6,6,4], 'carb':[4,3,1,5,4,1]})
>>> mtcars
carb cyl
0 4 8
1 3 8
2 1 6
3 5 6
4 4 6
5 1 4
>>> mtcars.groupby(["cyl"])['carb'].apply(lambda x: sum((x == 4).astype(float)) / sum(x.isin((4, 1))))
cyl
4 0.0
6 0.5
8 1.0
dtype: float64
Run Code Online (Sandbox Code Playgroud)
更新
在更复杂的情况下,您可以使用numpy.where()函数:
>>> import numpy as np
>>> mtcars.groupby(["cyl"])['carb'].apply(lambda x: sum(np.where(x == 4,6,3).astype(float)) / sum(np.where(x.isin((4,1)),8,4)))
cyl
4 0.375
6 0.600
8 0.750
dtype: float64
Run Code Online (Sandbox Code Playgroud)