这些解决方案(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我们可以update
通过流水线中的sqldf包使用SQL来存储数据帧(除非对数据表进行转换,否则就不能使用它-这可能表示dplyr中的错误。请参见dplyr第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
定义的内容
:如何使用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是这里的答案进行了审查。