[英]Conditional rowwise sum of subset of columns in specific row dplyr
我的问题有点棘手:我正在研究数据编辑,并且我即将找到正确的解决方案。 得到一个 dataframe 像这样:
ID name var1 var2 var3 var_total
1 a 1 1 2 4
2 b 2 3 2 7
3 c 1 -1 -1 1
其中var_total
是从 var1 到 var3 的每个大于零的数字的总和。 比如说,在 ID == 2 上,我需要将 var2 更改为 -1,这样做:
df %>% mutate(var2 = if_else(ID == 2, -1, var2))
这带来了:
ID name var1 var2 var3 var_total
1 a 1 1 2 4
2 b 2 -1 2 7
3 c 1 -1 -1 1
问题是,我需要找到一种方法来自动重新计算该行的var_total
。 我知道如何为整个 dataframe 做到这一点,但这有点慢:
df %>%
rowwise() %>%
mutate(var_total = {
x <- c_across(starts_with('var'))
sum(x[x > 0])
})
有没有办法只对选定的ID
执行此操作? 在这种情况下,我最终的 dataframe 将是:
ID name var1 var2 var3 var_total
1 a 1 1 2 4
2 b 2 -1 2 4
3 c 1 -1 -1 1
谢谢!
如果您想有效地更新单行(或行的一小部分),我会使用直接分配,而不是dplyr
。
var_cols = grep(names(df), pattern = "var[0-9]+", value = T)
recalc_id = 2
df[df$ID %in% recalc_id, "var_total"] = apply(df[df$ID %in% recalc_id, var_cols], 1, \(x) sum(x[x > 0]))
正如 akrun 在评论中指出的那样,如果它只是一行,则可以跳过apply
:
i = which(df$ID == recalc_id)
row = unlist(df[i, var_cols])
df$var_total[i] = sum(row[row > 0])
对于dplyr
解决方案,这与dplyr::case_when
相同:
df = df %>%
rowwise() %>%
mutate(var_total = case_when(
ID %in% 2 ~{
x <- c_across(starts_with('var[0-9]+'))
sum(x[x > 0])
},
TRUE ~ var_total
)
)
(请注意,在这两种情况下,我们都需要将列名模式更改为在总和中不包括var_total
。)
rowwise
会破坏一些矢量化并减慢速度,因此,如果您非常担心重新计算总和“太慢”的效率,我强烈推荐base
解决方案。 您甚至可能会找到一个非条件基本解决方案,该解决方案对于这种逐行操作来说足够快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.