我的数据如下:
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