这些解决方案(1)维护管道,(2)不覆盖输入,(3)只要求条件指定一次:
1a) mutate_cond 为可以合并到管道中的数据帧或数据表创建一个简单的函数。这个函数类似于mutate,但只作用于满足条件的行:
mutate_cond <- function(.data, condition, ..., envir = parent.frame()) {
condition <- eval(substitute(condition), .data, envir)
.data[condition, ] <- .data[condition, ] %>% mutate(...)
.data
}
DF %>% mutate_cond(measure == 'exit', qty.exit = qty, cf = 0, delta.watts = 13)
1b) mutate_last 这是数据帧或数据表的替代函数,同样类似于mutate,但仅在group_by 中使用(如下例所示)并且仅在最后一组而不是每组。请注意,TRUE > FALSE,因此如果group_by 指定了一个条件,那么mutate_last 将只对满足该条件的行进行操作。
mutate_last <- function(.data, ...) {
n <- n_groups(.data)
indices <- attr(.data, "indices")[[n]] + 1
.data[indices, ] <- .data[indices, ] %>% mutate(...)
.data
}
DF %>%
group_by(is.exit = measure == 'exit') %>%
mutate_last(qty.exit = qty, cf = 0, delta.watts = 13) %>%
ungroup() %>%
select(-is.exit)
2) 分解条件 分解条件,使其成为一个额外的列,稍后将其删除。然后使用ifelse、replace 或带逻辑的算术,如图所示。这也适用于数据表。
library(dplyr)
DF %>% mutate(is.exit = measure == 'exit',
qty.exit = ifelse(is.exit, qty, qty.exit),
cf = (!is.exit) * cf,
delta.watts = replace(delta.watts, is.exit, 13)) %>%
select(-is.exit)
3) sqldf 我们可以通过管道中的 sqldf 包将 SQL update 用于数据帧(但不能使用数据表,除非我们转换它们——这可能代表 dplyr 中的错误。请参阅dplyr issue 1579)。由于update 的存在,我们似乎不希望地修改了此代码中的输入,但实际上update 作用于临时生成的数据库中的输入副本,而不是实际输入。
library(sqldf)
DF %>%
do(sqldf(c("update '.'
set 'qty.exit' = qty, cf = 0, 'delta.watts' = 13
where measure = 'exit'",
"select * from '.'")))
4) row_case_when 还可以查看定义的row_case_when
Returning a tibble: how to vectorize with case_when? 。它使用类似于case_when 的语法,但适用于行。
library(dplyr)
DF %>%
row_case_when(
measure == "exit" ~ data.frame(qty.exit = qty, cf = 0, delta.watts = 13),
TRUE ~ data.frame(qty.exit, cf, delta.watts)
)
注意 1:我们将其用作DF
set.seed(1)
DF <- data.frame(site = sample(1:6, 50, replace=T),
space = sample(1:4, 50, replace=T),
measure = sample(c('cfl', 'led', 'linear', 'exit'), 50,
replace=T),
qty = round(runif(50) * 30),
qty.exit = 0,
delta.watts = sample(10.5:100.5, 50, replace=T),
cf = runif(50))
注意 2: dplyr 问题134、631、1518 和1573 和631 中也讨论了如何轻松指定更新行子集的问题作为主线程,1573 是对这里答案的评论。