โซลูชันเหล่านี้ (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เป็นการตรวจสอบคำตอบที่นี่