【问题标题】:How to subtract two columns using tidyverse mutate with columns named by external variables如何使用 tidyverse 变异减去由外部变量命名的列的两列
【发布时间】:2021-09-12 20:15:11
【问题描述】:

我想动态分配要相互减去的列。我已经阅读过,看起来我需要使用all_of,也许还有acrossHow to subtract one column from multiple columns in a dataframe in R using dplyrHow to you use objects in dplyr filter?)。我可以让它为变异短语中的一个变量工作(例如mutate(y = all_of(x))),但我似乎无法使用两个进行简单的计算。这是我想做的一个简化示例:

var1 <- c("Sepal.Length")
var2 <- c("Sepal.Width")

result <- iris %>%
  mutate(calculation = all_of(var1) - all_of(var2))

【问题讨论】:

    标签: r tidyverse dplyr across


    【解决方案1】:

    我们可以使用.data 将列子集化为向量。 all_of/any_ofacross 一起用于循环遍历列

    library(dplyr)
    iris %>%
      mutate(calculation = .data[[var1]] - .data[[var2]])%>%
      head
    

    -输出

    Sepal.Length Sepal.Width Petal.Length Petal.Width Species calculation
    1          5.1         3.5          1.4         0.2  setosa         1.6
    2          4.9         3.0          1.4         0.2  setosa         1.9
    3          4.7         3.2          1.3         0.2  setosa         1.5
    4          4.6         3.1          1.5         0.2  setosa         1.5
    5          5.0         3.6          1.4         0.2  setosa         1.4
    6          5.4         3.9          1.7         0.4  setosa         1.5
    

    或者也可以使用cur_data()

    iris %>%
        head %>%
        mutate(calculation = cur_data()[[var1]] - cur_data()[[var2]])
    

    -输出

     Sepal.Length Sepal.Width Petal.Length Petal.Width Species calculation
    1          5.1         3.5          1.4         0.2  setosa         1.6
    2          4.9         3.0          1.4         0.2  setosa         1.9
    3          4.7         3.2          1.3         0.2  setosa         1.5
    4          4.6         3.1          1.5         0.2  setosa         1.5
    5          5.0         3.6          1.4         0.2  setosa         1.4
    6          5.4         3.9          1.7         0.4  setosa         1.5
    

    或者另一种选择是传递across 中的两个变量,然后传递reduce-

    library(purrr)
    iris %>%
       head %>%
       mutate(calculation = reduce(across(all_of(c(var1, var2))), `-`))
    

    -输出

    Sepal.Length Sepal.Width Petal.Length Petal.Width Species calculation
    1          5.1         3.5          1.4         0.2  setosa         1.6
    2          4.9         3.0          1.4         0.2  setosa         1.9
    3          4.7         3.2          1.3         0.2  setosa         1.5
    4          4.6         3.1          1.5         0.2  setosa         1.5
    5          5.0         3.6          1.4         0.2  setosa         1.4
    6          5.4         3.9          1.7         0.4  setosa         1.5
    

    或者可以转换为symbol 并评估 (!!)

    iris %>% 
       head %>% 
       mutate(calculation = !! rlang::sym(var1) - !! rlang::sym(var2))
      Sepal.Length Sepal.Width Petal.Length Petal.Width Species calculation
    1          5.1         3.5          1.4         0.2  setosa         1.6
    2          4.9         3.0          1.4         0.2  setosa         1.9
    3          4.7         3.2          1.3         0.2  setosa         1.5
    4          4.6         3.1          1.5         0.2  setosa         1.5
    5          5.0         3.6          1.4         0.2  setosa         1.4
    6          5.4         3.9          1.7         0.4  setosa         1.5
    

    或者如果我们想在across 中使用all_of,只需使用[[ 对列进行子集化

    iris %>% 
       head %>% 
       mutate(calculation = across(all_of(var1))[[1]] - 
                             across(all_of(var2))[[1]])
    Sepal.Length Sepal.Width Petal.Length Petal.Width Species calculation
    1          5.1         3.5          1.4         0.2  setosa         1.6
    2          4.9         3.0          1.4         0.2  setosa         1.9
    3          4.7         3.2          1.3         0.2  setosa         1.5
    4          4.6         3.1          1.5         0.2  setosa         1.5
    5          5.0         3.6          1.4         0.2  setosa         1.4
    6          5.4         3.9          1.7         0.4  setosa         1.5
    

    我们需要子集的原因是,across 默认会在.names 不存在时更新原始列。 calculation 将是一个具有单列的 data.frame

    out <- iris %>%
        head %>% 
        mutate(calculation = across(all_of(var1)) -
               across(all_of(var2)))
    out
      Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length
    1          5.1         3.5          1.4         0.2  setosa          1.6
    2          4.9         3.0          1.4         0.2  setosa          1.9
    3          4.7         3.2          1.3         0.2  setosa          1.5
    4          4.6         3.1          1.5         0.2  setosa          1.5
    5          5.0         3.6          1.4         0.2  setosa          1.4
    6          5.4         3.9          1.7         0.4  setosa          1.5
    
    str(out)
    data.frame':    6 obs. of  6 variables:
     $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4
     $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9
     $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7
     $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4
     $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1
     $ calculation :'data.frame':   6 obs. of  1 variable:
      ..$ Sepal.Length: num  1.6 1.9 1.5 1.5 1.4 1.5
    

    【讨论】:

    • 我不明白。我试过library(rlang) iris %&gt;% mutate(calculation = !!enquo(var1) - !!enquo(var2)),但它不起作用
    • @TarJae 'var1', 'var2' 是字符串对象,en 前缀用于函数中。 enquo 主要用于通过在函数中传递未加引号的变量来尝试转换为 quosure。
    • .data 选项完美运行,谢谢!
    【解决方案2】:

    我们可以使用get 来访问变量名存储在字符串中的变量值(感谢 akrun 的帮助):

    iris %>% 
        mutate(calculation = get(var1) - get(var2)) 
    
       Sepal.Length Sepal.Width Petal.Length Petal.Width Species calculation
              <dbl>       <dbl>        <dbl>       <dbl> <fct>         <dbl>
     1          5.1         3.5          1.4         0.2 setosa          1.6
     2          4.9         3            1.4         0.2 setosa          1.9
     3          4.7         3.2          1.3         0.2 setosa          1.5
     4          4.6         3.1          1.5         0.2 setosa          1.5
     5          5           3.6          1.4         0.2 setosa          1.4
     6          5.4         3.9          1.7         0.4 setosa          1.5
     7          4.6         3.4          1.4         0.3 setosa          1.2
     8          5           3.4          1.5         0.2 setosa          1.6
     9          4.4         2.9          1.4         0.2 setosa          1.5
    10          4.9         3.1          1.5         0.1 setosa          1.8
    # ... with 140 more rows
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-11
      • 1970-01-01
      • 2022-01-16
      • 2013-02-24
      相关资源
      最近更新 更多