提问者:小点点

在列子集上使用按行突变


我正在尝试创建一个新列,该列将包含对tibble的列子集进行逐行计算的结果,并将此新列添加到现有tibble。像这样:

df <- tibble(
ID = c("one", "two", "three"),
A1 = c(1, 1, 1),
A2 = c(2, 2, 2),
A3 = c(3, 3, 3)
)

我实际上想从base R中执行此代码的dplyr等效项:

df$SumA <- rowSums(df[,grepl("^A", colnames(df))])

我的问题是这行不通:

df %>% 
select(starts_with("A")) %>% 
mutate(SumA = rowSums(.))
    # some code here

…因为我去掉了“ID”列,以便让mutate在其他(数字)列上运行rowSums。我试图在mutate之后在管道中绑定或bind_cols,但它不起作用。mutate的变体都不起作用,因为它们在原地工作(在tibble的每个单元格内,而不是在列之间,即使是按行)。

这确实有效,但我觉得这不是一个优雅的解决方案:

df %>% 
mutate(SumA = rowSums(.[,grepl("^A", colnames(df))]))

是否有任何基于tidyverse的解决方案不需要grepl或方括号,而只需要更标准的dplyr动词和参数?

我的预期输出是这样的:

df_out <- tibble(
ID = c("one", "two", "three"),
A1 = c(1, 1, 1),
A2 = c(2, 2, 2),
A3 = c(3, 3, 3),
SumA = c(6, 6, 6)
)

最好kJ


共3个答案

匿名用户

这是在tidyverse中使用purrr::pmap进行逐行计算的一种方法。这最好与实际需要逐行运行的函数一起使用;简单的添加可能会以更快的方式完成。基本上,我们使用selectpmap提供输入列表,如果您需要正则表达式,我们可以使用select助手,例如starts_with匹配

library(tidyverse)
df <- tibble(
  ID = c("one", "two", "three"),
  A1 = c(1, 1, 1),
  A2 = c(2, 2, 2),
  A3 = c(3, 3, 3)
)

df %>%
  mutate(
    SumA = pmap_dbl(
      .l = select(., starts_with("A")),
      .f = function(...) sum(...)
    )
  )
#> # A tibble: 3 x 5
#>   ID       A1    A2    A3  SumA
#>   <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 one       1     2     3     6
#> 2 two       1     2     3     6
#> 3 three     1     2     3     6

由reprex包(v0.2.1)于2019-01-30创建

匿名用户

这里有一种不同的方法,它不按行移动,而是利用加法的向量化性质和加法交换。这使得使用重复应用和purrr::减少

library(tidyverse)
df <- tibble(
  ID = c("one", "two", "three"),
  A1 = c(1, 1, 1),
  A2 = c(2, 2, 2),
  A3 = c(3, 3, 3)
)

df %>%
  mutate(
    SumA = reduce(
      .x = select(., starts_with("A")),
      .f = `+`
    )
  )
#> # A tibble: 3 x 5
#>   ID       A1    A2    A3  SumA
#>   <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 one       1     2     3     6
#> 2 two       1     2     3     6
#> 3 three     1     2     3     6

由reprex包(v0.2.1)于2019-01-30创建

匿名用户

1)要使用rowSums尝试在mutate中嵌套第二个管道,如下所示:

library(dplyr)

df %>% mutate(Sum = select(., starts_with("A")) %>% rowSums)

给予:

# A tibble: 3 x 5
  ID       A1    A2    A3   Sum
  <chr> <dbl> <dbl> <dbl> <dbl>
1 one       1     2     3     6
2 two       1     2     3     6
3 three     1     2     3     6

2)另一种方法是将其重塑为长格式,然后总结:

library(dplyr)
library(purrr)
library(tidyr)

df %>%
  mutate(Sum = gather(., key, value, -ID) %>% 
               group_by(., ID) %>%
               summarize(sum = sum(value)) %>%
               ungroup %>%
               pull(sum))

给予:

# A tibble: 3 x 5
  ID       A1    A2    A3   Sum
  <chr> <dbl> <dbl> <dbl> <dbl>
1 one       1     2     3     6
2 two       1     2     3     6
3 three     1     2     3     6