Diese Lösungen (1) hält die Rohrleitung (2) noch nicht überschreiben , die Eingabe und (3) nur erfordert , dass die Bedingung einmal spezifiziert werden:
1a) mutate_cond Erstellen Sie eine einfache Funktion für Datenrahmen oder Datentabellen, die in Pipelines integriert werden können. Diese Funktion ist wie mutate
, wirkt jedoch nur auf die Zeilen, die die Bedingung erfüllen:
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 Dies ist eine alternative Funktion für Datenrahmen oder Datentabellen, die wiederum ähnlich ist, mutate
aber nur innerhalb group_by
(wie im folgenden Beispiel) verwendet wird und nur für die letzte Gruppe und nicht für jede Gruppe ausgeführt wird. Beachten Sie, dass TRUE> FALSE. Wenn Sie also group_by
eine Bedingung angeben, mutate_last
werden nur Zeilen bearbeitet, die diese Bedingung erfüllen.
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) Bedingung ausklammern Die Bedingung ausklammern, indem sie zu einer zusätzlichen Spalte gemacht wird, die später entfernt wird. Dann verwenden ifelse
, replace
oder Arithmetik mit Logicals wie dargestellt. Dies funktioniert auch für Datentabellen.
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 Wir könnten SQL update
über das sqldf-Paket in der Pipeline für Datenrahmen verwenden (aber keine Datentabellen, es sei denn, wir konvertieren sie - dies könnte einen Fehler in dplyr darstellen. Siehe dplyr-Ausgabe 1579 ). Es mag den Anschein haben, als würden wir die Eingabe in diesem Code unerwünscht ändern, da das vorhanden ist, update
aber tatsächlich update
wirkt sich dies auf eine Kopie der Eingabe in der vorübergehend generierten Datenbank und nicht auf die tatsächliche Eingabe aus.
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 Überprüfen Sie auch, row_case_when
wie unter
Zurückgeben eines Tibbles definiert: Wie wird mit case_when vektorisiert? . Es verwendet eine Syntax ähnlich der case_when
, gilt jedoch für Zeilen.
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)
)
Anmerkung 1: Wir haben dies als verwendetDF
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))
Anmerkung 2: Das Problem, wie die Aktualisierung einer Teilmenge von Zeilen einfach angegeben werden kann, wird auch in den dplyr-Ausgaben 134 , 631 , 1518 und 1573 erörtert , wobei 631 der Hauptthread und 1573 eine Überprüfung der Antworten hier ist.