Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
警告:';无效。检测到internal.selfref';向函数返回的data.table中添加列时_R_Data.table - Fatal编程技术网

警告:';无效。检测到internal.selfref';向函数返回的data.table中添加列时

警告:';无效。检测到internal.selfref';向函数返回的data.table中添加列时,r,data.table,R,Data.table,这似乎是freadbug,但我不确定 这个例子再现了我的问题。我有一个函数,读取data.table并在列表中返回它。我使用列表将其他结果分组到相同的结构中。这是我的代码: ff.fread <- function(){ dt = fread("x 1 2 ") list(dt=dt) } DT.f <- ff.fread()$dt 这与fread本身无关,而是调用list()并向其传递一个命名对象。我们可以通过执行以下操作来重新创建: require(data.t

这似乎是
fread
bug,但我不确定

这个例子再现了我的问题。我有一个函数,读取data.table并在列表中返回它。我使用列表将其他结果分组到相同的结构中。这是我的代码:

ff.fread <- function(){
  dt = fread("x
1
2
")
  list(dt=dt)   
}

DT.f <- ff.fread()$dt

这与
fread
本身无关,而是调用
list()
并向其传递一个命名对象。我们可以通过执行以下操作来重新创建:

require(data.table)
DT <- data.table(x=1:2)       # name the object 'DT'
DT.l <- list(DT=DT)           # create a list containing one data.table
y <- DT.l$DT                  # get back the data.table
y[, bla := 1L]                # now add by reference
# works fine but warning message will occur

DT.l = list(DT=data.table(x=1:2))   # DT = a call, not a named object
y = DT.l$DT
y[, bla:=1L]
# works fine and no warning message
R制作的
data.table
的任何副本(不是
data.table
copy()
)的问题在于,R在内部将
truelength
参数设置为0,即使
truelength(.)
函数仍将返回正确的结果。当通过引用
:=
进行更新时,这无意中导致segfault,因为过度分配不再存在(或至少不再被识别)。这发生在<1.7.8版本中。为了克服这个问题,引入了一个名为
.internal.selfref
的属性。您可以通过执行
属性(DT)
来检查此属性

来自新闻(第1.7.8版):


o“克里斯崩溃”已修复。根本原因是,
keyArun的回答是一个很好的解释。R中
list()
的具体功能与
fread
无关,与
list
有关,这里有一个简单的例子:
dt=data.table(a=1);l=列表(dt);dt1=l[[1]];dt1[,b:=2]
注意,警告消息确实指出
list()
复制命名输入。完整的警告消息现在已在中编辑。警告消息包含以下内容:`另外,在RYou're right中。我已经删除了ref.to
标记
(尽管它只起了一小部分作用)。不过,我认为这足以说明问题。我认为这一警告指的是一个经常发生的案例。但只要复制发生(这不是通过实际的
copy
函数),或者无论如何是无意的,那么,
:=
必须正确复制才能通过引用进行更新(因为它的truelength将设置为0)…最后一件事,在您的示例中,如果我删除属性
setattr(y',.internal.selfref',NULL)
,我仍然得到警告。我想这个属性不是真的被删除了,只是被隐藏了。阿伦非常感谢这个伟大的答案+如果我能的话,就给我10英镑!
ff <- function(){
      list(dt=data.table(x=1:2))
    }
DT <- ff()$dt
DT[,y:=1:2]
ff.fread <- function(){
  dt = fread("x
1
2
")
  dt
}
require(data.table)
DT <- data.table(x=1:2)       # name the object 'DT'
DT.l <- list(DT=DT)           # create a list containing one data.table
y <- DT.l$DT                  # get back the data.table
y[, bla := 1L]                # now add by reference
# works fine but warning message will occur

DT.l = list(DT=data.table(x=1:2))   # DT = a call, not a named object
y = DT.l$DT
y[, bla:=1L]
# works fine and no warning message
tracemem(DT)
# [1] "<0x7fe23ac3e6d0>"
DT.list <- list(DT=DT)    # `DT` is the named object on the RHS of = here
# tracemem[0x7fe23ac3e6d0 -> 0x7fe23cd72f48]: 
SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot);
DT <- data.table(x=1:2) # internal selfref set
DT.list <- list(DT=DT)  # copy made, address(DT.list$DT) != address(DT)
                        # and truelength would be affected.

DT.new <- DT.list$DT    # address of DT.new != address of DT
                        # and it's not equal to the address pointed to by
                        # the attribute's 'prot' external pointer

# so a re-over-allocation has to be made by data.table at the next update by
# reference, and it warns so you can fix the root cause by not using list(),
# key<-, names<- etc.
> R.version.string
[1] "R version 3.0.2 (2013-09-25)"
> DT = data.table(a=1:3)
> address(DT)
[1] "0x1d70010"
> address(list(DT)[[1]])
[1] "0x21bc178"    # different address => list() copied the data.table named DT
> data.table:::selfrefok(DT)
[1] 1
> data.table:::selfrefok(list(DT)[[1]])
[1] 0              # i.e. this copied DT is not over-allocated
> ans = list()
> ans$DT = DT    # use $<- instead
> address(DT)
[1] "0x1d70010"
> address(ans$DT)
[1] "0x1d70010"    # good, no copy
> identical(ans, list(DT=DT))
[1] TRUE
> data.table:::selfrefok(ans$DT)
[1] 1              # good, the list()-ed DT is still over-allocated ok