【问题标题】:RowSums NA + NA gives 0 [duplicate]RowSums NA + NA 给出 0 [重复]
【发布时间】:2016-07-24 02:10:46
【问题描述】:

我会理解函数rowSums 的一个(对我而言)奇怪的行为。想象一下我有这个超级简单的数据框:

a = c(NA, NA,3)
b = c(2,NA,2)
df = data.frame(a,b)
df
   a  b
1 NA  2
2 NA NA
3  3  2

现在我想要第三列,它是其他两列的总和。我不能简单地使用+,因为NA

df$c <- df$a + df$b
df
   a  b  c
1 NA  2 NA
2 NA NA NA
3  3  2  5

但如果我使用rowSums,则具有NA 的行计算为0,而如果只有一个NA,则一切正常:

df$d <- rowSums(df, na.rm=T)
df
   a  b  c  d
1 NA  2 NA  2
2 NA NA NA  0
3  3  2  5 10

我错过了什么吗?

谢谢大家

【问题讨论】:

  • 我想知道为什么没有人回答base::psum

标签: r


【解决方案1】:

rowSums 的一个选项是获得rowSumsna.rm=TRUE 并与基于转换后的 NA 值的否定 (!) rowSums 逻辑矩阵相乘将所有 NA 转换为 NA 的行 (NA^)

rowSums(df, na.rm=TRUE) *NA^!rowSums(!is.na(df))
#[1]  2 NA 10

【讨论】:

  • 这是一个有趣的 hack:NA^0 == 1.
  • 您应该将其添加为链接问题的答案
【解决方案2】:

因为

sum(numeric(0))
# 0

rowSums 中使用na.rm = TRUE 后,第二行是numeric(0)。取sum后为0。

如果您想为所有NA 案例保留NA,这将是一个两阶段的工作。我建议为此编写一个小函数:

my_rowSums <- function(x) {
  if (is.data.frame(x)) x <- as.matrix(x)
  z <- base::rowSums(x, na.rm = TRUE)
  z[!base::rowSums(!is.na(x))] <- NA
  z
  }

my_rowSums(df)
# [1]  2 NA 10

如果输入 x 是一个数据框(如您的情况),这可能特别有用。 base::rowSums 将首先检查输入是否为矩阵。如果它得到一个数据框,它会首先将其转换为矩阵。类型转换实际上比实际的行总和计算成本更高。请注意,我们两次调用base::rowSums。为了减少类型转换开销,我们应该事先确保x 是一个矩阵。

对于@akrun 的“黑客”回答,我建议:

akrun_rowSums <- function (x) {
  if (is.data.frame(x)) x <- as.matrix(x)
  rowSums(x, na.rm=TRUE) *NA^!rowSums(!is.na(x))
  }

akrun_rowSums(df)
# [1]  2 NA 10

【讨论】:

  • mm ok.. 但是如果我想在第三列中也保留 NA 怎么办?
  • 这可能是一个两步的过程。例如,df$new &lt;- rowSums(df, na.rm=T); is.na(df$new) &lt;- rowSums(is.na(df)) == length(df)
猜你喜欢
  • 2017-08-03
  • 2021-05-27
  • 2021-07-25
  • 1970-01-01
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多