r - 给定多个条件,为分组变量的所有行赋值
问题描述
我有一个带有分组 ID 变量的数据框。对于每个分组 ID 中的每条记录,我们需要根据另一列的条件为新列分配一个值,该值是我们的“最终值”。我通常以循环的方式来做这类事情,虽然效率低下,但对我来说通常影响不大,但这里的数据很大,而且需要的时间太长。如何转换以下逻辑以应用函数族以提高效率?我很难理解这些功能。
library(data.table)
df <- data.frame("Group_ID" = c(1,1,2,2), "Values" = c("A", "B", "B", "C"))
df_list <- list()
for(grp_id in levels(unique(as.factor(df$Group_ID)))){
grp <- df[df$Group_ID == grp_id, ]
vals <- droplevels(unique(as.factor(grp$Values)))
if("C" %in% vals){
final_value <- "C"
} else if("B" %in% vals){
final_value <- "B"
} else{
final_value <- "A"
}
grp$Final_Value <- final_value
df_list[[grp_id]] <- grp
}
new_df <- rbindlist(df_list)
解决方案
这是一种可能适合您的基本 R 方法。我将添加进一步的解释,并希望这会有所帮助。
首先,获取您的Values
列并转换为有序因子:
df$Values <- ordered(df$Values, levels = c("C", "B", "A"))
有序因子对于有序或有序数据很有用。这里的级别有方向标志(在本例中为<
),表明它是有序的。
R> df$Values
[1] A B B C
Levels: C < B < A
这有助于指定“C”、“B”和“A”的优先级值。
然后我们使用ave
, 并指定FUN
要使用的函数作为min
最小值:
df$Final_Value <- ave(df$Values, df$Group_ID, FUN = min)
这是有关如何与ave
. 首先,ave
函数是这样的:
function (x, ..., FUN = mean)
{
if (missing(...))
x[] <- FUN(x)
else {
g <- interaction(...)
split(x, g) <- lapply(split(x, g), FUN)
}
x
}
这个函数将首先split
按组给定一个向量(所以我们可以对每个组应用一些函数)。在我们的例子中,我们希望每个人Group_ID
独立工作。如果我们split
使用整个数据框,我们将拥有:
R> split(df, df$Group_ID)
$`1`
Group_ID Values
1 1 A
2 1 B
$`2`
Group_ID Values
3 2 B
4 2 C
在我们的例子中,如果split
我们df$Values
得到:
R> split(df$Values, df$Group_ID)
$`1`
[1] A B
Levels: C < B < A
$`2`
[1] B C
Levels: C < B < A
请注意,即使在按组拆分后,即使仅存在一些值(例如,仅 A 和 B),每个组也会显示因子(A、B 和 C)的所有级别。
然后,ave
用于lapply
将min
函数应用于这两组中的每一个。lapply
将遍历每个组,并使用 确定该组中的最小值min
。
使用我们的因子,每个级别在背景中都有一个相关的整数值。按照顺序,哪些水平低于或高于其他水平(Levels: C < B < A
)是很清楚的。在这种情况下,如果任何值为 C,则结果将为 C,因为这是基于我们的有序级别的最低值。如果最小值为 B,则结果为 B。请注意,无论给定组的最低值是多少,都将包含在该组内的所有行中(例如,如果一个值是 C,那么该组中的所有行都将是 C)。
最后,您只需要:
df$Values <- ordered(df$Values, levels = c("C", "B", "A"))
df$Final_Value <- ave(df$Values, df$Group_ID, FUN = min)
我希望这是有帮助的。
输出
Group_ID Values Final_Value
1 1 A B
2 1 B B
3 2 B C
4 2 C C
数据
df <- structure(list(Group_ID = c(1, 1, 2, 2), Values = c("A", "B",
"B", "C")), class = "data.frame", row.names = c(NA, -4L))
推荐阅读
- html - 我在 HTML/CSS 中的动画边框有问题
- spotfire - 计算选择占总数的百分比
- sql - 当`select where like`直到结果只有一行时如何动态循环列?
- python - 创建 PDF 并使用烧瓶邮件作为附件发送
- javascript - 如何从 ajax 响应执行 HTML 代码
- sql - 检查值是否存在于 Select Query 中的另一个表中
- python - 使用 HDF5 附加模拟数据
- asp.net - 下拉菜单的必填字段,但视图模型类中文本框的可选字段
- sql - 数字时间戳日期差异计算
- python - 我希望能够打印字典中键的名称,然后是描述、值和数量