r语言 - 使用并粘贴当前列名到突变case_when

  • 本文关键字:突变 case when r语言 r tidyverse
  • 更新时间 :
  • 英文 :


我的数据如下:

dt <- structure(list(var1_dummy = c(0, 1, 0, 0, 0, 1, 0, 0, 1, 1), 
var2_dummy = c(1, 0, 0, 0, 0, 1, 0, 0, 1, 1), var1_scale = c(NA, 
3, NA, NA, NA, 3, NA, NA, 4, 4), var2_scale = c(3, NA, NA, 
NA, NA, 2, NA, NA, 3, 5)), class = "data.frame", row.names = c(NA, 
-10L))
var1_dummy var2_dummy var1_scale var2_scale
1           0          1         NA          3
2           1          0          3         NA
3           0          0         NA         NA
4           0          0         NA         NA
5           0          0         NA         NA
6           1          1          3          2
7           0          0         NA         NA
8           0          0         NA         NA
9           1          1          4          3
10          1          1          4          5

我现在想要mutate后缀"scale"在case_when中,它计算带有后缀"dummy"的相应变量。(所以var1_scale的操作应该依赖于var1_dummy等)如果var1_dummy为0,新版本的var1-scale应该是0,如果var1_dummy为1,应该增加1。

请注意,我有许多这样的列,因此应该避免单独改变每个列。

要突变的变量在以下向量中:

vars <- v(var1_scale, var2_scale)

现在我可以用good ol' loop做我想做的事情了:

for (var in vars) {
dummy <- gsub("scale", "dummy", var)
dt[, outlet] <- case_when(
dt[[outlet_expo]] == 0 ~ 0,
dt[[outlet_expo]] == 1 ~ dt[[outlet]] + 1)
}

然而,我更喜欢矢量化的解决方案。下面是我的尝试:

dt %>% 
mutate(across(all_of(vars),
~ case_when(
!!as.symbol(gsub("scale", "dummy", as.name(cur_column()))) == 0 ~ 0,
!!as.symbol(gsub("scale", "dummy", as.name(cur_column()))) == 1 ~ . + 1))

…我的想法是,我采取当前列的名称,用gsub改变它,然后再次评估它作为一个列。但cur_column似乎不能在case-when中工作。

使用data.table,您可以这样做:

dummy_vars <- names(dt)[grep("dummy", names(dt))] 
scale_vars <- names(dt)[grep("scale", names(dt))] 
setDT(dt)[, (scale_vars) := map2(mget(dummy_vars), mget(scale_vars), ~ifelse(.x == 0, .x, .y + 1))]

或者更简单,当dummy col为0时,比例1是NA:

scale_vars <- names(dt)[grep("scale", names(dt))] 
setDT(dt)[, (scale_vars) := map(.SD, ~ifelse(is.na(.x), 0, .x + 1)), .SDcols = scale_vars]

有点晚了,但这可能有帮助:

library(tidyverse)
dt %>% 
mutate(across(ends_with("_scale"),
~case_when(
cur_data() %>% select(all_of(gsub("scale","dummy",cur_column()))) == 0 ~ 0,
cur_data() %>% select(all_of(gsub("scale","dummy",cur_column()))) == 1 ~ . + 1)
))

我不使用as.symbol,而是简单地使用cur_data(),然后再次使用select()函数中的gsub()从中选择虚拟列。

还请记住,cur_column()已经为您提供了列名的字符向量。

你可以考虑在末尾添加一个pull(),以确保你有一个矢量,但我认为没有它也可以。

希望这对你有帮助!

您可以直接添加两个类似大小的数据框,只需将scale列中的NA值更改为0。

dummy_cols <- grep('dummy', names(dt))
scale_cols <- grep('scale', names(dt))
dt[scale_cols] <- dt[dummy_cols] + replace(dt[scale_cols], is.na(dt[scale_cols]), 0)
dt
#   var1_dummy var2_dummy var1_scale var2_scale
#1           0          1          0          4
#2           1          0          4          0
#3           0          0          0          0
#4           0          0          0          0
#5           0          0          0          0
#6           1          1          4          3
#7           0          0          0          0
#8           0          0          0          0
#9           1          1          5          4
#10          1          1          5          6

最新更新