创建一个新列,其中包含 R 上 tibble 中某些列的值的总和

Create a new column with the sum of the values from some columns in a tibble on R

提问人:Dani Quinchero 提问时间:11/14/2023 最后编辑:Dani Quinchero 更新时间:11/20/2023 访问量:57

问:

我有一个像 这样的小问题,我想按每行的值之和对一些列进行分组,用结果创建一个新列并替换总和的列,比如 .Table1Table2

Table1
| Col_A | INTER   | Col_B | Col_C | Col_D |
| ----- | ------- | ----- | ----- | ----- |
|   1   | [5-15)  |   2   |   4   |   2   |
|   1   | [15-25) |   1   |   3   |   6   |
|   1   | [25-35) |   1   |   1   |   2   |

在此示例中,我将对 和 的值求和,将结果保存在 中。Col_BCol_DCol_E

Table2  
| Col_A | INTER | Col_C | Col_E |
| ---   | ---   | ---   | ---   |
|   1   |   [5-15)   |   4   |  4    |
|   1   |   [15-25)   |   3   |  7    |
|   1   |   [25-35)   |   1   |  3    |

在我的真实数据中,我有几列(数值变量),它们有 NA。

我试过了:

Table2 <- Table1 %>% mutate(Col_E = rowSums(across(c(Col_B, Col_D))))

我收到此错误:

错误:列 有问题。
我。
x 必须使用有效的下标向量对列进行子集化。
x 下标的类型错误。 i 它必须是数字或字符。 i 组 1 中发生错误:Col_A = 1,INTER = “[5,15)”。
mutate()Col_ECol_E = rowSums(...)logical

r dplyr sum tibble rowsum

评论

0赞 Gregor Thomas 11/14/2023
我想你想要?Table1 |> mutate(Col_E = Col_B + Col_D) |> select(-Col_B, -Col_D)
0赞 Gregor Thomas 11/14/2023
如果您有许多列要求和,则可以使用 ,例如 ,,并且具有允许您使用选择帮助程序的优点,以防您想要以更编程的方式选择要求和的列。rowSumsacross()Table1 |> mutate(Col_E = rowSums(across(c(Col_B, Col_D))))across()
0赞 Dani Quinchero 11/14/2023
非常感谢你,我用了.有没有一种更简单/更简单的方法来选择/删除我想要的列,而无需一一写入(选择剩余的加Col_E或删除总和的列)?因为在我的数据中有很多列,而且名字有点长mutate(Col_E = rowSums(across(c(Col_B, Col_D)), na.rm = TRUE)) %>% select(Col_A, INTER, Col_C, Col_E)
1赞 Mark 11/14/2023
@DaniQuinchero以下几点: 1.有很多选择列的方法,请查看文档: dplyr.tidyverse.org/reference/select.html .我不知道我是否理解你所说的“选择余数加Col_E”是什么意思,但也许可以玩一下或文档中的其他内容,并告诉我你是怎么做的everything()
0赞 Mark 11/14/2023
2. 如果您有答案,请将其作为答案发布!这是一个很好的做法,可以帮助未来的读者:-)

答:

1赞 maike 11/14/2023 #1

结合之前注释中的一些输入,添加一个带有略微修改数据的 reprex 以解决 NA 删除问题,以及整洁的列选择示例以及如何预先指定新列的名称(如果您有几个要聚合的列组,例如,将所有内容保留在列表中以进行迭代,这很有用)。

在这里,我使用 select(- ...) 删除了在最后一步中聚合的列,但如果您只想保留新列,您可能还想研究 transmute(),但从我所读到的内容来看,这里的情况并非如此。

require(dplyr)
#> Loading required package: dplyr
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

df <- tribble(
~Col_A,  ~INTER,   ~ Col_B,~ Col_C,  ~Col_D ,
1     , '[5-15)'  , 2     , 4     , 2     ,
1     , '[15-25)' , 1     , 3     , NA     ,
1     , '[25-35)' , 1     , 1     , 2     
)


# pre-defined vector of column names
cols_add <- c('Col_B', 'Col_C',  'Col_D')
df %>% 
  mutate(!! col_sum := rowSums(across(all_of(cols_add)), na.rm = TRUE)) %>% 
  select(-all_of(cols_add))
#> # A tibble: 3 × 3
#>   Col_A INTER   Col_E
#>   <dbl> <chr>   <dbl>
#> 1     1 [5-15)      8
#> 2     1 [15-25)     4
#> 3     1 [25-35)     4

# you may also predefine the name of the result column, use !! and := in mutate 
col_sum  <- 'Col_E'

# using tidyselect with column index
df %>% 
  mutate(!! col_sum := rowSums(across(3:5), na.rm = TRUE)) %>% 
  select(-all_of(cols_add))
#> # A tibble: 3 × 3
#>   Col_A INTER   Col_E
#>   <dbl> <chr>   <dbl>
#> 1     1 [5-15)      8
#> 2     1 [15-25)     4
#> 3     1 [25-35)     4

# using tidyselect with regular expression
df %>% 
  mutate(!! col_sum := rowSums(across(matches('Col_[BCD]')), na.rm = TRUE)) %>% 
  select(-all_of(cols_add))
#> # A tibble: 3 × 3
#>   Col_A INTER   Col_E
#>   <dbl> <chr>   <dbl>
#> 1     1 [5-15)      8
#> 2     1 [15-25)     4
#> 3     1 [25-35)     4

# for multiple groups of columns to sum up
sum_spec <- list(
  col_E = c('Col_A', 'Col_B'),
  col_F = c('Col_C', 'Col_D')
)
 
df2 <- df 
iwalk(sum_spec, ~{
  df2 <<- df2 %>% 
    mutate( !! .y := rowSums(across(all_of(.x)), na.rm = TRUE)) %>% 
    select(-all_of(.x))
})

df2
#> # A tibble: 3 × 3
#>   INTER   col_E col_F
#>   <chr>   <dbl> <dbl>
#> 1 [5-15)      3     6
#> 2 [15-25)     2     3
#> 3 [25-35)     2     3

创建于 2023-11-14 with reprex v2.0.2

0赞 Dani Quinchero 11/20/2023 #2

我最终使用了创建要求和的变量列表的建议,但后来我只使用了简单的函数,因为我想以特定的方式对列进行排序(与 Table1 不同,示例数据中未说明)。select()

cols_add <- (Col_B, Col_D)

Table2 <- Table1 %>%
 mutate(Col_E = rowSums(across(all_of(cols_add)), na.rm = TRUE)) %>%
 select(Col_A, INTER, Col_C, Col_E)

但是,如果我希望 Table1 中列的默认顺序,我会使用它:

cols_add <- (Col_B, Col_D)

Table2 <- Table1 %>%
 mutate(Col_E = rowSums(across(all_of(cols_add)), na.rm = TRUE)) %>%
 select(!cols_add)

谢谢大家的帮助