【问题标题】:Let dplyr mutate use formula让 dplyr 变异使用公式
【发布时间】:2016-06-07 16:08:48
【问题描述】:

我有一个大型数据集存储在一个长数据框中。我想提取一些变量的数据并使用公式生成新数据。应从公式中提取所有必要的信息。首先,我想使用公式中的信息来过滤数据集以查找相应的变量——我为此使用了all.vars() 函数。我还依赖于 CRAN 上的 formula.tools 包。它用于轻松提取等式的左侧和右侧(分别为lhsrhs)。

library(dplyr)
library(reshape2)
library(formula.tools)

set.seed(100)

the_data <- data.frame(country = c(rep("USA", 9), rep("DEU", 9), rep("CHN", 9)),
                       year    = c(2000, 2010, 2020),
                       variable = c(rep("GDP", 3), rep("Population", 3), rep("Consumption", 3)),
                       value = rnorm(27, 100, 100))

add_variable <- function(df, equation){
  df <- filter(df, variable %in% all.vars(equation))

  df <- dcast(df, country + year ~ variable)

  df <- mutate_(df, rhs(equation))

  # code to keep only the newly generated column
  # ...

  df <- melt(df, id.vars = c("country", "year"))
}

result <- add_variable(the_data, GDPpC ~ GDP / Population)

新生成的列应命名为GDPpC,目前为GDP/Population。如何改进?在最后一步中,我还想过滤数据,以便结果中只包含新生成的数据,然后可以通过rbind 将其附加到源数据帧。

【问题讨论】:

  • 很难说出你的问题是什么
  • 谢谢,你是对的。我已经尝试过改进。

标签: r dplyr formula


【解决方案1】:

这会是一个解决方案吗?

add_variable <- function(df, equation){
      df <- filter(df, variable %in% all.vars(equation))
      orig_vars <- unique(df$variable)
      df <- dcast(df, country + year ~ variable)

      df <- mutate_(df, rhs(equation))
      colnames(df)[ncol(df)] <- as.character(lhs(equation))

      df <- melt(df, id.vars = c("country", "year"))
      df <- filter(df, !variable%in%orig_vars)
    }

    result <- add_variable(the_data, GDPpC ~ GDP / Population)
    result
  country year variable      value
1     CHN 2000    GDPpC 0.04885649
2     CHN 2010    GDPpC 2.62313658
3     CHN 2020    GDPpC 0.31685382
4     DEU 2000    GDPpC 0.80180998
5     DEU 2010    GDPpC 0.62642877
6     DEU 2020    GDPpC 0.97587188
7     USA 2000    GDPpC 0.26383912
8     USA 2010    GDPpC 1.01303516
9     USA 2020    GDPpC 0.69851501

【讨论】:

    【解决方案2】:

    多年后,我在寻找有关在 dplyr::mutate 中使用公式的信息时来到这里,因为我经常发现它更加简洁明了。 dplyr 自 2016 年以来当然已经成长和改变,包括 transmute 现在已被弃用的事实。但好消息是,如果您愿意使用formula.tools,该解决方案非常简洁。如下图。

    library(dplyr)
    
    # reproducible play_data
    
    set.seed(2020)
    play_data <- 
      data.frame(
        a = runif(20, 0.01, .5),
        b = runif(20, 0.02, .5),
        c = runif(20, 0.03, .5),
        d = runif(20, 0.04, .5),
        e = runif(20,1,5),
        f = runif(20,10,50)
      )
    
    my_formula <- newvariable ~ a * b^c / d * log(e) - f
    
    require(formula.tools)
    
    mutate_by_formula <- function(df, equation){
      df %>% transmute( !!lhs(equation) := !!rhs(equation) )
    }
    
    mutate_by_formula(play_data, my_formula)
    #>    newvariable
    #> 1    -25.80405
    #> 2    -20.48974
    #> 3    -37.87361
    #> 4    -46.52231
    #> 5    -19.88420
    #> 6    -16.49153
    #> 7    -37.25498
    #> 8    -41.02025
    #> 9    -31.88338
    #> 10   -42.17896
    #> 11   -30.75905
    #> 12   -10.42447
    #> 13   -25.84538
    #> 14   -46.08206
    #> 15   -13.51940
    #> 16   -25.30124
    #> 17   -19.80536
    #> 18   -26.42881
    #> 19   -38.02190
    #> 20   -30.51113
    

    至于 OP 的原始示例和细节,它稍微复杂一些,因为必须对数据进行整形,但基本概念是相同的。唯一的转折是 dcast 和最后的 select 以删除计算中使用的变量。

    library(dplyr)
    library(reshape2)
    library(formula.tools)
    
    set.seed(100)
    
    the_data <- data.frame(country = c(rep("USA", 9), rep("DEU", 9), rep("CHN", 9)),
                           year    = c(2000, 2010, 2020),
                           variable = c(rep("GDP", 3), rep("Population", 3), rep("Consumption", 3)),
                           value = rnorm(27, 100, 100))
    
    specific_function <- function(df, equation){
      df %>% 
        filter(variable %in% all.vars(equation)) %>%
        dcast(country + year ~ variable) %>%
        mutate(!!lhs(equation) := !!rhs(equation)) %>%
        select(-all.vars(equation)[2:length(all.vars(equation))])
    }
    
    specific_function(the_data, GDPpC ~ GDP / Population)
    #>   country year      GDPpC
    #> 1     CHN 2000 0.04885649
    #> 2     CHN 2010 2.62313658
    #> 3     CHN 2020 0.31685382
    #> 4     DEU 2000 0.80180998
    #> 5     DEU 2010 0.62642877
    #> 6     DEU 2020 0.97587188
    #> 7     USA 2000 0.26383912
    #> 8     USA 2010 1.01303516
    #> 9     USA 2020 0.69851501
    

    reprex package (v0.3.0) 于 2020 年 5 月 4 日创建

    【讨论】:

      猜你喜欢
      • 2021-12-13
      • 2021-12-06
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 2018-08-24
      • 1970-01-01
      • 2020-01-16
      • 1970-01-01
      相关资源
      最近更新 更多