r-mutate(跨)以在tidyverse中生成多个新列



我通常必须对一系列可以通过后缀(比如从_a到_I(识别的变量/列执行等效计算,并将结果保存在新的变量/栏中。计算是等效的,但在计算中使用的变量之间有所不同。这些也可以通过相同的后缀(_a到_i(来识别。所以我基本上想要实现的是:

newvar_a = (oldvar1_a + oldvar2_a) - z
...
newvar_i = (oldvar1_i + oldvar2_i) - z

这是我的告别:

mutate(across(c(oldvar1_a:oldvar1_i), ~ . - z, .names = "{col}_new"))

因此,我能够";循环;在oldvar1_a到oldvar1_i上,从它们减去z,并将结果保存在名为oldvar1_a_new到oldvarl_i_new的新列中。然而,我不能在计算中包括oldvar2_a到oldvar2_I,因为R不会在它们上循环。(此外,我仍然需要重命名新列(。

我找到了一种使用for循环实现结果的方法。然而,这看起来绝对不是最有效、最直接的方法:

for (i in letters[1:9]) {
oldvar1_x <- paste0("oldvar1_", i)
oldvar2_x <- paste0("oldvar2_", i)
newvar_x <- paste0("newvar_", i)
df <- df %>%
mutate(!!sym(newvar_x) := (!!sym(oldvar1_x) + !!sym(oldvar2_x)) - z)
}

因此,我想知道是否/如何在多个可以通过后缀识别的列上进行mutate(跨(循环(如上面的例子中所示(

在这种情况下,您可以使用cur_data()cur_column()来利用我们想要将具有相同后缀但只需要交换数字的列相加的优势。

library(dplyr)
df <- data.frame(
oldvar1_a = 1:3,
oldvar2_a = 4:6,
oldvar1_i = 7:9,
oldvar2_i = 10:12,
z = c(1,10,20)
)
mutate(
df,
across(
starts_with("oldvar1"),
~ (.x + cur_data()[gsub("1", "2", cur_column())]) - z,
.names = "{col}_new"
)
)
#>   oldvar1_a oldvar2_a oldvar1_i oldvar2_i  z oldvar2_a oldvar2_i
#> 1         1         4         7        10  1         4        16
#> 2         2         5         8        11 10        -3         9
#> 3         3         6         9        12 20       -11         1

如果你想与case_when一起使用,只需确保使用[[进行索引,你可以在这里阅读更多。

df <- data.frame(
oldvar1_a = 1:3,
oldvar2_a = 4:6,
oldvar1_i = 7:9,
oldvar2_i = 10:12,
z = c(1,2,0)
)
mutate(
df,
across(
starts_with("oldvar1"),
~ case_when(
z == 1 ~ .x,
z == 2 ~ cur_data()[[gsub("1", "2", cur_column())]],
TRUE ~ NA_integer_
),
.names = "{col}_new"
)
)
#>   oldvar1_a oldvar2_a oldvar1_i oldvar2_i z oldvar1_a_new oldvar1_i_new
#> 1         1         4         7        10 1             1             7
#> 2         2         5         8        11 2             5            11
#> 3         3         6         9        12 0            NA            NA

有一种相当简单的方法可以做我认为你正在尝试做的事情。

# first lets create data
library(dplyr)
df <- data.frame(var1_a=runif(10, min = 128, max = 131), 
var2_a=runif(10, min = 128, max = 131),
var1_b=runif(10, min = 128, max = 131), 
var2_b=runif(10, min = 128, max = 131),
var1_c=runif(10, min = 128, max = 131), 
var2_c=runif(10, min = 128, max = 131))
# taking a wild guess at what your z is
z <- 4
# initialize a list
fnl   <- list()
# iterate over all your combo, put in list
for (i in letters[1:3])
{
dc   <- df %>% select(ends_with(i))
i    <- dc %>% mutate(a = rowSums(dc[1:ncol(dc)]) - z)
fnl  <- append(fnl, i)
}  
# convert to a dataframe/tibble  
final <- bind_cols(fnl)

假设您在这里有特定的要求,我就把列名写得很草率。您可以将这个循环转换为一个函数,并使用purrr在一个步骤中完成整个精简。

最新更新