我正在try 一个基于dplyr的工作流(而不是使用我习惯的data.table),我遇到了一个无法找到等效dplyr解决方案的问题.我通常会遇到这样的情况:我需要根据一个条件有条件地更新/替换多个列.下面是一些示例代码,以及我的数据.表格解决方案:

library(data.table)

# Create some sample data
set.seed(1)
dt <- data.table(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))

# Replace the values of several columns for rows where measure is "exit"
dt <- dt[measure == 'exit', 
         `:=`(qty.exit = qty,
              cf = 0,
              delta.watts = 13)]

对于同样的问题,有没有一个简单的dplyr解决方案?我希望避免使用ifelse,因为我不想多次键入条件——这是一个简化的示例,但有时有许多基于单个条件的赋值.

提前感谢您的帮助!

推荐答案

(2)只需覆盖(1)指定的输入条件(3)即可维护(not):

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 This is an alternative function for data frames or data tables which again is like mutate but is only used within group_by (as in the example below) and only operates on the last group rather than every group. Note that TRUE > FALSE so if group_by specifies a condition then mutate_last will only operate on rows satisfying that condition.

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) factor out condition通过使其成为一个额外的列,然后将其移除,从而计算出该条件.然后使用ifelsereplace或算术与逻辑,如图所示.这也适用于数据表.

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我们可以通过管道中的sqldf包使用SQL update来处理数据帧(但不能使用数据表,除非我们转换它们——这可能代表dplyr中的一个缺陷.参见dplyr issue 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

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)
  )

Note 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))

Note 2: dplyr第13463115181573期中也讨论了如何轻松指定更新行子集的问题,其中631是主线,1573是对这里答案的回顾.

R相关问答推荐

pivot_longer:names_to和names_pattern

Select 与特定列中最大值对应的数据帧行

如何判断某列中由某些行组成的百分比

将模拟变量乘以多个观测结果中的模拟变量

更改绘图上的x轴断点,而不影响风险?

从R导出全局环境中的所有sf(numrames)对象

R根据条件进行累积更改

标识R中多个列中缺少的唯一值

提取一个列表中单个列的重复观察结果R

如何对2个列表元素的所有组合进行操作?

如何在R中描绘#符号?

比较理论阿尔法和经验阿尔法

如何通过匹配R中所有可能的组合来从宽到长旋转多个列?

在多页PDF中以特定布局排列的绘图列表不起作用

在带有`R`中的`ggmosaic`的马赛克图中使用图案而不是 colored颜色

从R中发出的咕噜声中的BUG?

主题(Legend.key=Element_RECT(Fill=&Quot;White&Quot;))不起作用

如何在AER::ivreg中指定仪器?

使用LAG和dplyr执行计算,以便按行和按组迭代

R没有按顺序显示我的有序系数?