【问题标题】:Mutating column in `dplyr` using `rowSums`使用 `rowSums` 改变`dplyr` 中的列
【发布时间】:2017-01-27 13:46:29
【问题描述】:

最近我偶然发现dplyr 的一个奇怪行为,如果有人能提供一些见解,我会很高兴。

假设我有一个数据,其中 com 列包含一些数值。在一个简单的场景中,我想计算rowSums。虽然有很多方法可以做到,但这里有两个例子:

df <- data.frame(matrix(rnorm(20), 10, 2),
                 ids = paste("i", 1:20, sep = ""),
                 stringsAsFactors = FALSE)

# works
dplyr::select(df, - ids) %>% {rowSums(.)}

# does not work
# Error: invalid argument to unary operator
df %>%
  dplyr::mutate(blubb = dplyr::select(df, - ids) %>% {rowSums(.)})

# does not work
# Error: invalid argument to unary operator
df %>%
  dplyr::mutate(blubb = dplyr::select(., - ids) %>% {rowSums(.)})

# workaround:
tmp <- dplyr::select(df, - ids) %>% {rowSums(.)}
df %>%
  dplyr::mutate(blubb = tmp)

# works
rowSums(dplyr::select(df, - ids))

# does not work
# Error: invalid argument to unary operator
df %>%
  dplyr::mutate(blubb = rowSums(dplyr::select(df, - ids)))

# workaround
tmp <- rowSums(dplyr::select(df, - ids))
df %>%
  dplyr::mutate(blubb = tmp)

首先,我不太了解导致错误的原因,其次我想知道如何以一种整洁的方式实际实现一些(可行的)列的整洁计算。

编辑

mutate and rowSums exclude columns 问题虽然相关,但侧重于使用rowSums 进行计算。在这里,我很想了解为什么上面的示例不起作用。与其说是如何解决(参见解决方法),不如说是了解应用幼稚方法时会发生什么。

【问题讨论】:

  • 为什么不dplyr::select(df, - ids) %&gt;% mutate(foo=rowSums(.))
  • 试试ids = paste("-i", 1:20, sep = "") 我想我在某处读过这篇文章
  • @WeihuangWong 那里的问题虽然相关,但侧重于使用rowSums 进行计算。在这里,我很想了解为什么上面的示例不起作用。与其说是如何解决(见解决方法),不如说是了解应用朴素方法时会发生什么
  • @Haboryme 我想保留 ID 以供以后使用。因此,我想在mutate 函数中进行选择。

标签: r dplyr


【解决方案1】:

这些示例不起作用,因为您将 select 嵌套在 mutate 中并使用裸变量名。在这种情况下,select 正在尝试做类似的事情

> -df$ids
Error in -df$ids : invalid argument to unary operator

失败是因为你不能否定一个字符串(即-"i1"-"i2" 没有意义)。以下任何一种配方都有效:

df %>% mutate(blubb = rowSums(select_(., "X1", "X2")))
df %>% mutate(blubb = rowSums(select(., -3)))

df %>% mutate(blubb = rowSums(select_(., "-ids")))

按照@Haboryme 的建议。

【讨论】:

  • df %&gt;% mutate(blubb = rowSums(select_(., "-ids"))) 使用起来可能更方便一些。
  • 是否可以对要选择的列进行模式匹配?而不是“-ids”之类的starts_with(“X)。&gt; df %&gt;% mutate(blubb = rowSums(select_(., starts_with("X")))) Error in mutate_impl(.data, dots) : Evaluation error: Variable context not set.
  • 使用 select 而不是 select_ 就可以了。
【解决方案2】:

select_deprecated。您可以使用:

library(dplyr)
df <- data.frame(matrix(rnorm(20), 10, 2),
                 ids = paste("i", 1:20, sep = ""),
                 stringsAsFactors = FALSE)
df %>% 
  mutate(blubb = rowSums(select(., .dots = c("X1", "X2"))))

# Or more generally:
desired_columns <- c("X1", "X2")
df %>% 
  mutate(blubb = rowSums(select(., .dots = all_of(desired_columns))))

【讨论】:

    【解决方案3】:

    添加到这个旧线程是因为我搜索了这个问题然后意识到我问错了问题。此外,我在这个和相关问题中发现了一些对正确管道步骤方法的渴望。

    这里的答案有些不直观,因为他们试图将 dplyr 白话与非“整洁”的数据一起使用。如果你想用 dplyr 方式做,先整理数据,使用gather(),然后使用summarise()

    library(tidyverse)
    
    df <- data.frame(matrix(rnorm(20), 10, 2),
                     ids = paste("i", 1:20, sep = ""),
                     stringsAsFactors = FALSE)
    
    df %>% gather(key=Xn,value="value",-ids) %>% 
      group_by(ids) %>% 
      summarise(rowsum=sum(value))
    
    #> # A tibble: 20 x 2
    #>    ids   rowsum
    #>    <chr>       <dbl>
    #>  1 i1          0.942
    #>  2 i10        -0.330
    #>  3 i11         0.942
    #>  4 i12        -0.721
    #>  5 i13         2.50 
    #>  6 i14        -0.611
    #>  7 i15        -0.799
    #>  8 i16         1.84 
    #>  9 i17        -0.629
    #> 10 i18        -1.39 
    #> 11 i19         1.44 
    #> 12 i2         -0.721
    #> 13 i20        -0.330
    #> 14 i3          2.50 
    #> 15 i4         -0.611
    #> 16 i5         -0.799
    #> 17 i6          1.84 
    #> 18 i7         -0.629
    #> 19 i8         -1.39 
    #> 20 i9          1.44
    

    如果您在使用 arrange() 无法对 id 进行排序时关心它们的顺序,请先将该列作为一个因素。

      df %>% 
      mutate(ids=as_factor(ids)) %>% 
      gather(key=Xn,value="value",-ids) %>% 
      group_by(ids) %>% 
      summarise(rowsum=sum(value))
    

    【讨论】:

    • 是的,感谢您指出这一点。事后看来,最初提出的数据似乎并不整洁!
    【解决方案4】:

    为什么要使用管道运算符?只需写一个表达式,例如:

    rowSums(df[,sapply(df, is.numeric)])
    

    即计算所有数字列的行和,优点是不需要指定ids

    【讨论】:

    • 谢谢,但是,这并不能回答第一个问题。我在上面发布了一些解决方案,您肯定适用,但它没有解决其他问题实际上有什么问题的问题。
    • @Drey,它实际上回答了您的第二个问题,“我想知道如何以一种整洁的方式实际实现一些(可行)列的整洁计算”。
    • 但我主要关心的是为什么上述方法不起作用,尽管变通方法可以。
    【解决方案5】:

    如果要将结果保存为数据中的列,可以使用如下 data.table 语法:

    dt <- as.data.table(df)
    dt[, x3 := rowSums(.SD, na.rm=T), .SDcols = which(sapply(dt, is.numeric))]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      • 2018-05-22
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 2019-02-09
      相关资源
      最近更新 更多