使用Dplyr对每一行中列右侧的所有单元格求和

Joh*_*mas 4 row r sum dplyr

因此,我在此问题的通用版本上看到了很多页面,但是在这里我要对特定列之后的一行中的所有值求和。

假设我们有这个df:

id    city      identity   q1   q2   q3
0110  detroit   ella       2    4    3
0111  boston    fitz       0    0    0
0112  philly    gerald     3    1    0
0113  new_york  doowop     8    11   2
0114  ontario   wazaaa     NA   11   NA
Run Code Online (Sandbox Code Playgroud)

现在,我使用的df通常不带有3个“ q”变量,它们会有所不同。因此,我想对每一行进行rowSum运算,但仅求和column后面的行identity

具有NA的行将被忽略。

最终,我想将总和为0的行删除,并以如下所示的df结尾:

id    city      identity   q1   q2   q3
0110  detroit   ella       2    4    3
0112  philly    gerald     3    1    0
0113  new_york  doowop     8    11   2
Run Code Online (Sandbox Code Playgroud)

最好是在dplyr中执行此操作,但这不是必需的。

编辑:

我在下面添加了该解决方案无法使用的数据,对于造成的困惑,我们深表歉意。

df <- structure(list(Program = c("3002", "111", "2455", "2929", "NA", 
"NA", NA), Project_ID = c("299", "11", "271", "780", "207", "222", 
NA), Advance_Identifier = c(14, 24, 12, 15, NA, 11, NA), Sequence = c(6, 
4, 4, 5, 2, 3, 79), Item = c("payment", "hero", "prepayment_2", 
"UPS", "period", "prepayment", "yeet"), q1 = c("500", "12", "-1", 
"0", NA, "0", "0"), q2 = c("500", "12", "-1", "0", NA, "0", "1"
), q3 = c("500", "12", "2", "0", NA, "0", "2"), q4 = c("500", 
"13", "0", "0", NA, "0", "3")), row.names = c(NA, -7L), class = c("tbl_df", 
"tbl", "data.frame"))

Run Code Online (Sandbox Code Playgroud)

Spa*_*man 9

具有零额外依赖项的Base R版本:

[编辑:我总是忘记rowSums存在]

> df1$new = rowSums(
    df1[,(1+which(names(df1)=="identity")):ncol(df1),drop=FALSE]
    )


> df1
   id     city identity q1 q2 q3 new
1 110  detroit     ella  2  4  3   9
2 111   boston     fitz  0  0  0   0
3 112   philly   gerald  3  1  0   4
4 113 new_york   doowop  8 11  2  21
Run Code Online (Sandbox Code Playgroud)

如果需要将字符转换为数字,请apply与结合使用as.numeric

df$new = apply(df[,(1+which(names(df)=="Item")):ncol(df),drop=FALSE], 1, function(col){sum(as.numeric(col))})
Run Code Online (Sandbox Code Playgroud)

但是要弄清楚它们是否真的是因素,因为这会失败,这就是为什么在执行其他任何操作之前将看起来像数字的东西转换为数字是一件好事。

基准测试

如果您担心速度,以下是针对当前接受的解决方案对我的功能进行的基准测试:

akrun = function(df1){df1 %>%
   mutate(new = rowSums(select(., ((match('identity', names(.)) + 
           1):ncol(.))), na.rm = TRUE))}

baz = function(df1){rowSums(
    df1[,(1+which(names(df1)=="identity")):ncol(df1),drop=FALSE]
    )}
Run Code Online (Sandbox Code Playgroud)

样本数据

df = data.frame(id=sample(100,100), city=sample(LETTERS,100,TRUE), identity=sample(letters,100,TRUE), q1=runif(100), q2=runif(100),q3=runif(100))
Run Code Online (Sandbox Code Playgroud)

测试-请注意,我new每次都会从源数据帧中删除该列,否则代码会不断向其中添加其中一列(尽管akrun没有df进行适当的修改,但可以baz通过在基准代码中为其分配新列来对其进行修改后再运行)。

> microbenchmark({df$new=NULL;df2 = akrun(df)},{df$new=NULL;df$new=baz(df)})
Unit: microseconds
                                       expr      min       lq       mean
  {     df$new = NULL     df2 = akrun(df) } 1300.682 1328.941 1396.63477
 {     df$new = NULL     df$new = baz(df) }   63.102   72.721   87.78668
    median        uq      max neval
 1376.9425 1398.5880 2075.894   100
   84.3655   86.7005  685.594   100
Run Code Online (Sandbox Code Playgroud)

tidyverse版本的时间是基本R版本的16倍。