【问题标题】:how to parameter a variable name using dplyr如何使用 dplyr 参数化变量名
【发布时间】:2017-08-25 07:32:59
【问题描述】:

如果我的标题不是很好,我很抱歉,如果有人有更好的,请改进它。

我目前正在努力使用新的 dplyr 0.7,它可以使用 dplyr 在我自己的函数中使用变量。我不知道我的尝试是不可能的,还是我用错了方法。

我有一个简单的数据框,每家公司一行,每家公司都有一堆 2015 年和 2014 年的变量:

evo <- data.frame(id=1:5,
              CA2015 = c(1200,1500,1550,200,0),
              CA2014 = c(800,50,654,8555,0),
              VA2015 = c(6984,6588,633,355,84),
              VA2014 = c(35,358,358,1331,86))

我希望能够为我的每个变量创建一个“evo”变量,它基本上是 2015 年的值减去 2013 年的值。

在我的示例中,我想得到一个名为 evoCA 的变量,它等于 CA2015 - CA2014,以及一个名为 evoVA 的变量,它等于 VA2015 - VA2014。

(基本上:

evo %>%
  mutate(evoCA= CA2015 - CA2014,
     evoVA = VA2015 - VA2014)

)

所以我尝试创建一个函数,将我想要比较的变量的名称作为参数,但我无法使其工作。这是我能做的最好的:

addEvo <- function(table,var,var2014,var2015) {
var <- enquo(var)
var2014 <- enquo(var2014)
var2015 <- enquo(var2015)
evoName <- paste0("evo",var)[2]
table %>%
 mutate(!!evoNom := (!!var2015) - (!!var2013)) %>%
  return()

}

但这不是很干净,因为我不仅要传递变量名,还要传递带有后缀的变量。

有什么办法让它变得更好吗?

【问题讨论】:

  • 你的最终目标是什么,你想遍历多个前缀还是多年,或者两者兼而有之?
  • @RobinGertenbach : 多个前缀,我有很多变量但只有两年。
  • 你有多少个前缀?您的目标是循环应用 addEvo 的变量?我认为有一种方法可以添加所有 evo 列,但是您的函数需要更多的行...
  • 大约 20 个前缀

标签: r dplyr


【解决方案1】:

这是一个不需要编写新函数的解决方案:

library(dplyr)
evo <- data.frame(id=1:5,
                  CA2015 = c(1200,1500,1550,200,0),
                  CA2014 = c(800,50,654,8555,0),
                  VA2015 = c(6984,6588,633,355,84),
                  VA2014 = c(35,358,358,1331,86))

# This creates two dataframes with the same properties and two diff years
evo2014 <- evo %>%
  select(contains("2014"))
evo2015 <- evo %>%
  select(contains("2015"))

# If both have the same amount of columns make a matrix subtraction and obtain the difference. Then bind the difference dataframe to the original df
if (ncol(evo2014) == ncol(evo2015)) {
  evodiff <- as.matrix(evo2015 - evo2014)
  varnames <- substr(colnames(evo2014), 1, 2)
  colnames(evodiff) <- paste0("evo", varnames)
  evo <- bind_cols(evo, as.data.frame(evodiff))
}
evo
#>   id CA2015 CA2014 VA2015 VA2014 evoCA evoVA
#> 1  1   1200    800   6984     35   400  6949
#> 2  2   1500     50   6588    358  1450  6230
#> 3  3   1550    654    633    358   896   275
#> 4  4    200   8555    355   1331 -8355  -976
#> 5  5      0      0     84     86     0    -2

【讨论】:

    【解决方案2】:

    使用tidyr,您可以将数据转换为更整洁的数据。

    如果年份总是相同的两年并且前缀总是在年份之前,则可以添加您想要的所有列:

    evo <- data.frame(id=1:5,
                      CA2015 = c(1200,1500,1550,200,0),
                      CA2014 = c(800,50,654,8555,0),
                      VA2015 = c(6984,6588,633,355,84),
                      VA2014 = c(35,358,358,1331,86))
    library(dplyr, warn.conflicts = F)
    library(tidyr, warn.conflicts = F)
    evo %>%
      gather(key = "type", value = "value", -id) %>%
      separate(type, c("prefix", "year"), sep = -5) %>%
      spread(year, value) %>%
      mutate(evo = `2015` - `2014`) %>%
      gather(key = "key", value = "value", -(id:prefix)) %>%
      unite("type", prefix:key, sep = "") %>%
      spread(type, value) %>%
      select(id, ends_with("2015"), ends_with("2014"), ends_with("evo"))
    #>   id CA2015 VA2015 CA2014 VA2014 CAevo VAevo
    #> 1  1   1200   6984    800     35   400  6949
    #> 2  2   1500   6588     50    358  1450  6230
    #> 3  3   1550    633    654    358   896   275
    #> 4  4    200    355   8555   1331 -8355  -976
    #> 5  5      0     84      0     86     0    -2
    

    如果这两年与 2014 年和 2015 年不同,你也可以做一个函数。

    【讨论】:

    • 我真的必须学会使用tidyr,你的解决方案很聪明,谢谢!
    猜你喜欢
    • 2018-01-29
    • 2014-08-25
    • 2017-09-10
    • 2018-07-04
    • 2018-09-13
    • 2022-01-20
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多