以布尔值作为列选择器的r data.table行为

以布尔值作为列选择器的r data.table行为,r,data.table,R,Data.table,我对data.table的行为感到有点惊讶。我想从数据表中的一行中选择所有非NA值 使用NA值时,它正在工作: t = data.table(a=1,b=NA) t[, !is.na(t), with=F] 如果没有NA值,它将不工作: t = data.table(a=1, b=2) t[, !is.na(t), with=F] 基本区别在于t[,!c(F,F),with=F]不起作用。有趣的是,t[,c(t,t),with=F]做得很好 我知道有很多方法可以实现所需的输出,但我只对数据的

我对
data.table的行为感到有点惊讶。我想从
数据表中的一行中选择所有非
NA

使用
NA
值时,它正在工作:

t = data.table(a=1,b=NA)
t[, !is.na(t), with=F]
如果没有
NA
值,它将不工作:

t = data.table(a=1, b=2)
t[, !is.na(t), with=F]
基本区别在于
t[,!c(F,F),with=F]
不起作用。有趣的是,
t[,c(t,t),with=F]
做得很好


我知道有很多方法可以实现所需的输出,但我只对
数据的这一行为感兴趣(对我来说很奇怪)。table

正如@Roland已经提到的
is。na(t)
输出是一个矩阵,需要一个向量来选择列

但列选择应该在
OP
给出的示例中起作用,因为它在data.table中只得到一行。我们所需要做的就是将其包装在
()
中,以获得评估结果。e、 g:

library(data.table)
t = data.table(a=1, b=2)

t[,(!c(FALSE,FALSE)),with=FALSE]
#    a b
# 1: 1 2

t[,(!is.na(t)),with=FALSE]
#    a b
# 1: 1 2

我已经调查了
数据表::`[.data.table`


在我看来,它确实像一个bug。基本上发生的是,
!is.na()
调用被分为
is.na()
调用。然后,它对这个向量求和,如果长度为零,它返回
null.data.table()
。问题是,
dt签出
!is.na(t)
,它是矩阵。我不知道data.table用那个矩阵做什么,但是你想要
t[,c(!is.na(t)),with=F]
。我不明白。为什么
t[,!c(FALSE,TRUE),with=FALSE]
起作用?@petres这是个好主意。但我的目的是使用
()
将进行强制计算/强制,以便
!c(FALSE,FALSE)
。也许你应该在GitHub中将其报告为bug。行为肯定不一致。感谢您查看内部信息和资金细节。
sim_dt <- function(...) {

  ## data.table catches the call
  jsub <- substitute(...)
  cat("This is your call:", paste0(jsub, collapse = ""))

  ## data.table separates the `!` from the call and sets notj = TRUE instead
  ## and saves `is.na(t)` into `jsub`
  if (is.call(jsub) && deparse(jsub[[1L]], 500L, backtick=FALSE) %in% c("!", "-")) {  # TODO is deparse avoidable here?
    notj = TRUE
    jsub = jsub[[2L]]
  } else notj = FALSE

  cat("\nnotj:", notj)
  cat("\nThis is the new jsub: ", paste0(jsub, collapse = "("), ")", sep = "")

  ## data.table evaluates just the `jsub` part which obviously return a vector of `FALSE`s (because `!` was removed)
  cat("\nevaluted j:", j <- eval(jsub, setattr(as.list(seq_along(dt)), 'names', names(dt)), parent.frame()))# else j will be evaluated for the first time on next line

  ## data.table checks if `j` is a logical vector and looks if there are any TRUEs and gets an empty vector
  if (is.logical(j)) cat("\nj after `which`:", j <- which(j))

  cat("\njs length:", length(j), "\n\n")

  ## data.table checks if `j` is empty (and it's obviously is) and returns a null.data.table
  if (!length(j)) return(data.table:::null.data.table()) else return(dt[, j, with = FALSE])

}


## Your data.table
dt <- data.table(a = 1, b = 2)
sim_dt(!is.na(dt))
# This is your call: !is.na(dt)
# notj: TRUE
# This is the new jsub: is.na(dt)
# evaluted j: FALSE FALSE
# j after `which`: 
# js length: 0 
# 
# Null data.table (0 rows and 0 cols)


dt <- data.table(a = 1, b = NA)
sim_dt(!is.na(dt))

# This is your call: !is.na(dt)
# notj: TRUE
# This is the new jsub: is.na(dt)
# evaluted j: FALSE TRUE
# j after `which`: 2
# js length: 1 
# 
#     b
# 1: NA