首页 文章

如何在dplyr中创建mutate调用的动态数字和名称?

提问于
浏览
1

我正在创建一个动态排列函数来创建与顺序无关的参数 . 在函数之外,我已经能够使用dplyr对这种方法进行硬编码 . 但是,我想概括它,以便我可以使用相同的函数来置换3个因子或6个因子,而无需键入所有重复调用 . 但是,我还没弄清楚如何让它发挥作用 .

这是一个简单的数据框 df ,包含3个变量的所有排列:

#> dput(df)
structure(list(var1 = structure(c(1L, 1L, 2L, 2L, 3L, 3L), .Label = c("a", 
"b", "c"), class = "factor"), var2 = structure(c(2L, 3L, 1L, 
3L, 1L, 2L), .Label = c("a", "b", "c"), class = "factor"), var3 =     structure(c(3L, 
2L, 3L, 1L, 2L, 1L), .Label = c("a", "b", "c"), class = "factor"), 
    X1 = c(0.5, 0.5, 0.8, 0.8, 0.3, 0.3), X2 = c(0.8, 0.3, 0.5, 
    0.3, 0.5, 0.8), X3 = c(0.3, 0.8, 0.3, 0.5, 0.8, 0.5)), .Names = c("var1", 
"var2", "var3", "X1", "X2", "X3"), row.names = c(NA, -6L), class = "data.frame")

我的目标是获得每个变量的平均顺序无关值 . 为此,我需要创建两个中间变量:一个是乘法 m1, m2, m3, m4 ,一个是减法 s1, s2, s3, s4 . 变量 m1s1 是特殊的, m1 = X1s1 = X1-1 . 但是,其他人需要参考之前的那个: m2 = X2*X1s2 = m2-m1 .

我试图将这个SO问题的想法结合起来:R - dplyr - mutate - use dynamic variable names和一个lazyeval interp,这样我就可以动态地引用其他变量并动态命名变异列 . 但是,它只保留了最后一个发送,并且重命名不起作用,所以我得到一个额外的列,例如, X2*X3 ,这个例子很好用3 . 当我有5时,它给了一个附加栏目 X4*X5 .

for(n in 2:n_params) {
     varname <- paste("m", n, sep=".")
     df <- mutate_(df, .dots = setNames(interp(~one*two, one=as.name(paste0("X",n-1)),
                                               two=as.name(paste0("X",n))),varname))
     df
   }

由于我无法弄清楚为什么这不起作用,我设置了一系列if语句来计算 ms .

xx <- data.frame(df) %>%
     mutate(m1 = X1,
            s1 = X1 - 1)
   if(n_params >= 2) {
     xx <- data.frame(xx) %>%
       mutate(m2 = m1 * X2,
              s2 = m2 - m1)
   }
   if(n_params >= 3) {
     xx <- data.frame(xx) %>%
       mutate(m3 = m2 * X3,
              s3 = m3 - m2)
   }
   if(n_params >= 4) {
     xx <- data.frame(xx) %>%
       mutate(m4 = m3 * X4,
              s4 = m4 - m3)
   }
   if(n_params >= 5) {
     xx <- data.frame(xx) %>%
       mutate(m5 = m4 * X5,
         s5 = m5 - m4)
   }
   if(n_params >= 6) {
     xx <- data.frame(xx) %>%
       mutate(m6 = m5 * X6,
              s6 = m6 - m5)
   }

好像我应该能够编写一个创建它的函数,

在伪代码中:

function(n_params) {
 function(x) {
   new_df <- df %>% 
            mutate(m1 = X1,
                  s1 = X1 - 1)
   for(i in 2:n_params){
    new_df <- append(call to new_df, 
             mutate(mi = Xi*Xi-1,
                   si = mi-mi-1)
     }
   }
}

但是,我无法弄清楚如何组合 lazyeval interp 和setNames以允许引用先前的变异值 .

如果有功能的话,我可以把它留在里面,但如果可能的话,我希望能让它变得更紧凑 .

感兴趣的最终最终输出是每个初始变量的所有排列的平均s值 . 我在一个单独的功能中这样做 .

1 回答

  • 0

    不是最漂亮的东西,但它有效:

    n_params = 3
    
    xx1 = df %>%
    mutate(m1 = X1,
           s1 = X1 - 1)
    
    for (i in 2:n_params) {
    xx1 = xx1 %>%
        mutate_(.dots = setNames(list(varval = paste0("m", i - 1, " * X", i)),
                                 paste0("m", i))) %>%
        mutate_(.dots = setNames(list(varval = paste0("m", i, " - m", i - 1)),
                                 paste0("s", i)))
    }
    

    可能有更好的方法来使用 lazyeval . 希望其他人会显示一个很好的答案,但这确实符合你问题中产生的 xx (对于 n_params = 3 ):

    identical(xx, xx1)
    # [1] TRUE
    

相关问题