โซลูชันเหล่านี้ (1) รักษาไปป์ไลน์ (2) ไม่เขียนทับอินพุตและ (3) กำหนดให้ระบุเงื่อนไขเพียงครั้งเดียวเท่านั้น:
1a) mutate_condสร้างฟังก์ชันง่ายๆสำหรับ data frames หรือตารางข้อมูลที่สามารถรวมเข้ากับ pipeline ฟังก์ชั่นนี้เหมือน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นี่เป็นฟังก์ชันทางเลือกสำหรับ data frames หรือตารางข้อมูลซึ่งเหมือนอีกครั้ง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หรือทางคณิตศาสตร์กับ logicals ดังแสดงในภาพ นอกจากนี้ยังใช้ได้กับตารางข้อมูล
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 ในไปป์ไลน์สำหรับ data frames (แต่ไม่ใช่ตารางข้อมูลเว้นแต่เราจะแปลง - นี่อาจแสดงถึงจุดบกพร่องใน 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กำหนดไว้ใน
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เป็นการตรวจสอบคำตอบที่นี่