【问题标题】:R dplyr choose value from column with column name to choose in a separate columnR dplyr 从具有列名的列中选择值以在单独的列中选择
【发布时间】:2019-09-18 01:41:47
【问题描述】:

您好,我有一个数据框,其中包含不同的数据列(例如 x、y、z)和另一列指定选择哪一个。我想使用 dplyr::mutate (或类似的)创建一个新列,其值对应于“选择”指定的列中的值。但我想首先保留所有列。在我的真实数据中,我还有其他一些包含元数据的列。

示例数据:

library(dplyr)
testdf <- data.frame(x = 1:5, y = 11:15, z = 101:105, choose = c("z","y","x","y","z"))

我可以在我的示例中使用case_when 来完成这项工作,但在我的实际脚本中,生成的列名和选择列可能具有不同的值,因此我不想硬编码可能的名称。

期望的输出/测试

mutate(testdf, selectedValue = case_when(choose == "x" ~x,
                                     choose == "y"~ y,
                                     choose == "z"~ z, T~NA_integer_))

#>   x  y   z choose selectedValue
#> 1 1 11 101      z           101
#> 2 2 12 102      y            12
#> 3 3 13 103      x             3
#> 4 4 14 104      y            14
#> 5 5 15 105      z           105

reprex package (v0.3.0) 于 2019 年 9 月 18 日创建

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是一个 data.table 解决方案。在这种情况下,我认为 dplyr 解决方案并不比其他解决方案(特别是 base r 和 data.table)更具人类可读性。

    library(data.table)
    testdt <- data.table(x = 1:5, y = 11:15, z = 101:105, choose = c("z","y","x","y","z"))
    testdt[,selectedValue := get(choose), by = choose]
    testdt
    #>    x  y   z choose selectedValue
    #> 1: 1 11 101      z           101
    #> 2: 2 12 102      y            12
    #> 3: 3 13 103      x             3
    #> 4: 4 14 104      y            14
    #> 5: 5 15 105      z           105
    

    reprex package (v0.3.0) 于 2019 年 9 月 17 日创建

    【讨论】:

    • 谢谢。通常我真的很难理解 data.table 发生了什么,但我在这里同意它实际上非常易读
    【解决方案2】:

    如果您将purrrdplyr 一起使用:

    testdf %>%
        mutate(selectedValue = purrr::map2_dbl(row_number(),choose,~testdf[.x,.y]))
    
    

    【讨论】:

    • 谢谢,这是一个优雅的解决方案,并且确实按照我的要求使用了 mutate。在这种情况下,我选择了 data.table,因为我认为(异常)它比 tidyverse 解决方案更具可读性,并且这个脚本将被新手使用。但我可以想象将来会使用这种技术,所以谢谢
    【解决方案3】:

    基本的 R 方法是从testdf 创建一个行/列索引矩阵作为子集。我们使用match 来获取列索引并为行创建一个顺序计数器。

    testdf$selectedvalue <- testdf[cbind(seq_len(nrow(testdf)), 
                                   match(testdf$choose, names(testdf)))]
    testdf
    #  x  y   z choose selectedvalue
    #1 1 11 101      z           101
    #2 2 12 102      y            12
    #3 3 13 103      x             3
    #4 4 14 104      y            14
    #5 5 15 105      z           105
    

    【讨论】:

      猜你喜欢
      • 2016-02-08
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多