代码之家  ›  专栏  ›  技术社区  ›  mmyoung77

处理dpylr中的动态变量名

  •  1
  • mmyoung77  · 技术社区  · 8 年前

    我重新发布这个问题是因为在我以前的可复制示例中有一个非常严重的错误。

    我的数据如下:

    set.seed(123)
    X_foo <- runif(6, 0, 1)
    X_bar <- runif(6, 0, 100) 
    Y_foo <- runif(6, 0, 1) 
    Y_bar <- runif(6, 0, 100)
    Z_foo <- runif(6, 0, 1)
    Z_bar <- runif(6, 0, 100)
    df <- data.frame(X_foo, X_bar, Y_foo, Y_bar, Z_foo, Z_bar)
    df
          X_foo    X_bar      Y_foo    Y_bar     Z_foo     Z_bar
    1 0.2875775 52.81055 0.67757064 32.79207 0.6557058 96.302423
    2 0.7883051 89.24190 0.57263340 95.45036 0.7085305 90.229905
    3 0.4089769 55.14350 0.10292468 88.95393 0.5440660 69.070528
    4 0.8830174 45.66147 0.89982497 69.28034 0.5941420 79.546742
    5 0.9404673 95.68333 0.24608773 64.05068 0.2891597  2.461368
    6 0.0455565 45.33342 0.04205953 99.42698 0.1471136 47.779597
    

    我将被要求从数据中的六个变量中的任何一个(并且只有一个)返回排名前三的值。我写的函数是:

    aRankingFunction <- function(aMetric1 = "X", aMetric2 = "foo") {
      # list of names that the function will accept
      good_metric1 <- c("X", "Y", "Z")
      good_metric2 <- c("foo", "bar")
      # use an if statement, so if user enters a bad name they get an error back 
      if((aMetric1 %in% good_metric1) & (aMetric2 %in% good_metric2)) {
        thePull <- df %>%
          # Select statement should pull exactly one variable (by default, X_foo)
          select(contains(aMetric1)) %>%
          select(contains(aMetric2))
        } else {
          return("Error")
        }
      theOutput <- thePull %>%
        # Create a new variable with the ranks of the variable pulled
        mutate(Rank = min_rank()) %>% # This is where the function breaks
        # Sort the ranks
        arrange(desc(Rank)) %>%
        # Filter for ranks 1,2,3
        filter(Rank <= 3)
      return(theOutput)
    }
    

    但当我跑步时 aRankingFunction() ,它坏了。我已经指出了中断发生的位置:我不知道*应该在语句中出现什么。 mutate(Rank = min_rank(*)) .该语句将对所选六个变量中的一个进行排序,但直到运行时我才知道是哪个变量。

    我怎么说 mutate 语句,动态地,“使用已选择的变量名”?

    2 回复  |  直到 8 年前
        1
  •  3
  •   MrFlick    8 年前

    只关注需要工作的部分,你需要把你拥有的字符串变成一个符号,然后用砰的一声把它注入到dplyr调用中。 !! 操作人员

    ...
    rankvar <- as.symbol(names(thePull))
    theOutput <- thePull %>%
      # Create a new variable with the ranks of the variable pulled
      mutate(Rank = min_rank(!!rankvar)) %>%
    ...
    

    在这个只有一列的特殊情况下,另一种选择是

    ...
    theOutput <- thePull %>%
      # Create a new variable with the ranks of the variable pulled
      mutate_all(funs(Rank = min_rank)) %>%
    ...
    
        2
  •  1
  •   zack    8 年前

    你可以提交 thePull 作为一个论点 min_rank()

    aRankingFunction <- function(aMetric1 = "X", aMetric2 = "foo") {
      # list of names that the function will accept
      good_metric1 <- c("X", "Y", "Z")
      good_metric2 <- c("foo", "bar")
      # use an if statement, so if user enters a bad name they get an error back 
      if((aMetric1 %in% good_metric1) & (aMetric2 %in% good_metric2)) {
        thePull <- df %>%
          # Select statement should pull exactly one variable (by default, X_foo)
          select(contains(aMetric1)) %>%
          select(contains(aMetric2))
      } else {
        return("Error")
      }
      theOutput <- df %>%
        # Create a new variable with the ranks of the variable pulled
        mutate(Rank = min_rank(thePull)) %>% # This is where the function breaks
        # Sort the ranks
        arrange(desc(Rank)) %>%
        # Filter for ranks 1,2,3
        filter(Rank <= 3)
      return(theOutput)
    }
    
    > aRankingFunction()
          X_foo    X_bar      Y_foo    Y_bar     Z_foo    Z_bar Rank
    1 0.4089769 55.14350 0.10292468 88.95393 0.5440660 69.07053    3
    2 0.2875775 52.81055 0.67757064 32.79207 0.6557058 96.30242    2
    3 0.0455565 45.33342 0.04205953 99.42698 0.1471136 47.77960    1