【问题标题】:Summing across rows of a data.table for specific columns with NA对具有 NA 的特定列的 data.table 行求和
【发布时间】:2020-07-15 23:35:27
【问题描述】:
library(data.table)
TEST <- data.table(Time=c("0","0","0","7","7","7","12"),
             Zone=c("1","1","0","1","0","0","1"),
             quadrat=c(1,2,3,1,2,3,1),
             Sp1=c(NA,4,29,9,1,2,10),
             Sp2=c(NA,NA,11,15,32,15,10),
             Sp3=c(NA,0,1,1,1,1,0))

TEST[, SumAbundance := rowSums(.SD), .SDcols = 4:6]

如果有 3 个 NA,那么我认为 SumAbundance 应该是 NA。如果有 1 或 2 个 NA 值,则仍然计算总和并忽略 NA

【问题讨论】:

标签: r data.table


【解决方案1】:

为此,我们可以有多种选择,即先执行rowSums,然后执行replace 全部为NA 的行,或者在i 中创建一个索引以仅对那些至少具有一个非NA。

library(data.table)
TEST[, SumAbundance := replace(rowSums(.SD, na.rm = TRUE),
           Reduce(`&`, lapply(.SD, is.na)), NA), .SDcols = 4:6]

或者更紧凑的选项

TEST[, SumAbundance :=  (NA^!rowSums(!is.na(.SD))) * 
             rowSums(.SD, na.rm = TRUE), .SDcols = 4:6]

或者构造一个函数并复用

rowSums_new <- function(dat) {
  fifelse(rowSums(is.na(dat)) != ncol(dat), rowSums(dat, na.rm = TRUE),  NA_real_)
    }
TEST[, SumAbundance := rowSums_new(.SD), .SDcols = 4:6]

【讨论】:

  • 非常感谢,如果所有 3 个都是 NA,你能显示 1 个衬垫来替换值吗?
  • @bvowe 我更新了两个选项。第二个比第一个更紧凑
  • 我喜欢这个函数的使用,这样.SDcols就不需要被引用两次了。
【解决方案2】:

另一种选择是在i 中进行子集化,然后在j 中更新:

library(data.table)
dt <- data.table(Time=c("0","0","0","7","7","7","12"),
                   Zone=c("1","1","0","1","0","0","1"),
                   quadrat=c(1,2,3,1,2,3,1),
                   Sp1=c(NA,4,29,9,1,2,10),
                   Sp2=c(NA,NA,11,15,32,15,10),
                   Sp3=c(NA,0,1,1,1,1,0))

dt[!(is.na(Sp1) & is.na(Sp2) &is.na(Sp3)),
     SumAbundance := rowSums(.SD, na.rm = TRUE),
     .SDcols = 4:6]

dt
#>    Time Zone quadrat Sp1 Sp2 Sp3 SumAbundance
#> 1:    0    1       1  NA  NA  NA           NA
#> 2:    0    1       2   4  NA   0            4
#> 3:    0    0       3  29  11   1           41
#> 4:    7    1       1   9  15   1           25
#> 5:    7    0       2   1  32   1           34
#> 6:    7    0       3   2  15   1           18
#> 7:   12    1       1  10  10   0           20

@Akrun 使用Reduce 来减少输入量。我们也可以在 i 声明中使用这种方法。

【讨论】:

  • 也许,可扩展? cols &lt;- 4:6;TEST[rowSums(!is.na(TEST[, ..cols])) != 0, SumAbundance := rowSums(.SD, na.rm = TRUE), .SDcols = cols]
猜你喜欢
  • 2014-03-18
  • 1970-01-01
  • 1970-01-01
  • 2022-06-25
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
相关资源
最近更新 更多