Ці рішення (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 Ми могли б використовувати SQL update
через пакет sqldf в конвеєрі для фреймів даних (але не таблиць даних, якщо ми їх не перетворимо - це може представляти помилку в 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 - оглядом відповідей тут.