【问题标题】:dplyr:如何通过列索引而不是使用变异的列名来引用列?
【发布时间】:2015-12-13 15:20:02
【问题描述】:

使用 dplyr,您可以执行以下操作:

iris %>% head %>% mutate(sum=Sepal.Length + Sepal.Width) 
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species sum
1          5.1         3.5          1.4         0.2  setosa 8.6
2          4.9         3.0          1.4         0.2  setosa 7.9
3          4.7         3.2          1.3         0.2  setosa 7.9
4          4.6         3.1          1.5         0.2  setosa 7.7
5          5.0         3.6          1.4         0.2  setosa 8.6
6          5.4         3.9          1.7         0.4  setosa 9.3

但在上面,我通过列名引用了这些列。如何使用 12 来获得相同的结果?

这里我有以下,但我觉得它没有那么优雅。

iris %>% head %>% mutate(sum=apply(select(.,1,2),1,sum))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species sum
1          5.1         3.5          1.4         0.2  setosa 8.6
2          4.9         3.0          1.4         0.2  setosa 7.9
3          4.7         3.2          1.3         0.2  setosa 7.9
4          4.6         3.1          1.5         0.2  setosa 7.7
5          5.0         3.6          1.4         0.2  setosa 8.6
6          5.4         3.9          1.7         0.4  setosa 9.3

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    你可以试试:

    iris %>% head %>% mutate(sum = .[[1]] + .[[2]])
    
      Sepal.Length Sepal.Width Petal.Length Petal.Width Species sum
    1          5.1         3.5          1.4         0.2  setosa 8.6
    2          4.9         3.0          1.4         0.2  setosa 7.9
    3          4.7         3.2          1.3         0.2  setosa 7.9
    4          4.6         3.1          1.5         0.2  setosa 7.7
    5          5.0         3.6          1.4         0.2  setosa 8.6
    6          5.4         3.9          1.7         0.4  setosa 9.3
    

    【讨论】:

    • 请注意,这与group_by 不能很好地结合:iris %>% group_by(Species) %>% mutate(sum = .[[1]] + .[[2]])iris %>% group_by(Species) %>% mutate(sum=Sepal.Length + Sepal.Width) 可以。
    • @MrFlick - 也许我错过了什么。当您按行计算时,为什么分组很重要?如果他们正在执行其他操作,他们可能会在其中抛出ungroup() 然后重新组合。我以前发现这是必要的。
    • @RichardScriven 这更像是一个警告,这种方法实际上绕过了大部分 dplyr 基础架构,因此它可能会破坏原本应该起作用的分组之类的东西。您实际上是在跳过 mutate 的 data= 参数。你是对的,这对于逐行的mutate() 并不重要,但请考虑:iris %>% group_by(Species) %>% summarize(x=mean(.[[1]] + .[[2]])) 这不是按索引指定列的好“通用”方法。
    • 在设置 mutate 列时,按列引用如何工作? iris %>% head %>% mutate(.[[1]] = .[[1]] + .[[2]]) 给出:错误:“iris %>% head %>% mutate (.[[1]] ="
    • 对于dplyr 1.0.0,有这个解决方法:df %>% group_by(eval(names(.)[1])) %>% ...
    【解决方案2】:

    我玩游戏有点晚了,但在这种情况下,我的个人策略是编写我自己的 tidyverse-compliant 函数,该函数将完全符合我的要求。通过 tidyverse 兼容,我的意思是函数的第一个参数是一个数据帧,输出是一个可以添加到数据帧的向量。

    sum_cols <- function(x, col1, col2){
       x[[col1]] + x[[col2]]
    }
    
    iris %>%
      head %>%
      mutate(sum = sum_cols(x = ., col1 = 1, col2 = 2))
    

    【讨论】:

      【解决方案3】:

      你觉得这个版本怎么样?
      灵感来自@SavedByJesus's answer

      applySum <- function(df, ...) {
        assertthat::assert_that(...length() > 0, msg = "one or more column indexes are required")
        mutate(df, Sum = apply(as.data.frame(df[, c(...)]), 1, sum))
      }
      
      iris %>%
        head(2) %>%
        applySum(1, 2)
      #
      ### output
      #
        Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sum
      1          5.1         3.5          1.4         0.2  setosa 8.6
      2          4.9         3.0          1.4         0.2  setosa 7.9
      #
      ### you can select and sum more then two columns by the same function
      #
      iris %>%
        head(2) %>%
        applySum(1, 2, 3, 4)
      #
      ### output
      #
        Sepal.Length Sepal.Width Petal.Length Petal.Width Species  Sum
      1          5.1         3.5          1.4         0.2  setosa 10.2
      2          4.9         3.0          1.4         0.2  setosa  9.5
      

      【讨论】:

        【解决方案4】:

        为了解决@pluke 在 cmets 中提出的问题,dplyr doesn't really support column index

        不是一个完美的解决方案,但您可以使用 base R 来解决这个问题 iris[1] <- iris[1] + iris[2]

        【讨论】:

        • 关于 dplyr 的链接评论不支持列索引...我想知道的循环解决方案是什么?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-28
        • 1970-01-01
        相关资源
        最近更新 更多