当前位置: 首页 > 知识库问答 >
问题:

突变(跨)以在tidyverse中生成多个新列

邢昂然
2023-03-14

我通常必须对一系列变量/列执行等价的计算,这些变量/列可以通过它们的后缀来标识(范围,假设从_a到_i),并将结果保存在新的变量/列中。计算是等效的,但计算中使用的变量不同。这些也可以通过相同的后缀(_a to _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的新列中,保存到oldvar2_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)
}

因此,我想知道是否/如何使突变(跨)循环在可以通过后缀标识的多个列上(如上例所示)

共有2个答案

韩自怡
2023-03-14

有一个相当简单的方法来做我相信你正在尝试做的事情。

# 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在一个步骤中完成整个精简。

东方震博
2023-03-14

在这种情况下,您可以使用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

如果您想使用with case_when,请确保使用< code>[[进行索引,您可以在此处阅读更多信息。

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
 类似资料:
  • 我有一个国家和年份级别的面板数据集,我想根据现有的变量创建两个新变量。 我想做的是创建两个新变量集:(1)每年(跨国家)平均值的变量集和(2)国家/地区值相对于年平均值的变量集。例如,对于 var1(1) 将产生 mean_var1 和 (2) relmean_var1我希望这些变量用于所有其他变量。总的来说,数据集中有超过1000个变量,但我只将此函数应用于大约6个。 我有适用于第一部分的代码,

  • 我的数据帧 所有值都是字符串。同学们,我想用空格代替非空格。我知道 但是有没有一种(tidyverse风格的)更普遍的方式来做到这一点呢?大约 也就是说,我正在寻找一种可以很好地扩展的解决方案。 提前致谢。

  • 我想自动为我的存储创建一个新变量。 它的工作原理应该是: 如果var_count是例如4,它应该生成一个名为var4的变量。

  • 我想避免的一个问题是两个分支更新JOOQ生成的代码。我想这可能会导致混乱的合并冲突。使用JOOQ管理跨两个不同分支的数据库更改是否有最佳实践策略?

  • 我有这样的调查数据。唯一的回答是“na”或“yes”。 我不得不对数据应用以下逻辑: null null 任何建议都非常感谢!我想我可能得用一个循环,但我不知道怎么用。如果我转换为数值并将所有4列求和,我可以使用类似…?

  • 这里有一个关于如何在Spring中生成SOAP Web服务的很好的例子:https://spring.io/guides/gs/producing-web-service/ 此示例演示如何执行一个终结点和一个服务。如何通过多个服务和endpoint获得相同的结果?