背景
我尝试用CSV
文件替换一些rds
输出文件,以提高效率。这些是中间文件,将作为其他R脚本的输入。
问题
我开始调查我的脚本何时失败,并发现readRDS()
和load()
不会返回与原始版本相同的data tables
。这应该发生吗?或者我错过了什么?
示例代码
library( data.table )
aDT <- data.table( a=1:10, b=LETTERS[1:10] )
saveRDS( aDT, file = "aDT.rds")
bDT <- readRDS( file = "aDT.rds" )
identical( aDT, bDT, ignore.environment = T ) # Gives 'False'
aDF <- data.frame( a=1:10, b=LETTERS[1:10] )
saveRDS( aDF, file = "aDF.rds")
bDF <- readRDS( file = "aDF.rds" )
identical( aDF, bDF, ignore.environment = T ) # Gives 'True'
# Using 'save'& 'load' doesn't help either
aDT2 <- data.table( a=1:10, b=LETTERS[1:10] )
save( aDT2, file = "aDT2.RData")
bDT2 <- aDT2; rm( aDT2 )
load( file = "aDT2.RData" )
identical( aDT2, bDT2, ignore.environment = T ) # Gives 'False'
我在Linux Mint上运行R ver 3.2.0并使用data.table
ver 1.9.4和1.9.5(最新)进行测试。
在SO中搜索并且Google返回this和this,但我认为他们没有回答此问题。我仍然试图弄清楚为什么我的脚本在切换到rds
时失败了,但我从这开始。
如果知识渊博的SO成员可以提供帮助,我将非常感激。谢谢!
修改
大家好,我碰巧找到了解决问题的方法 - 已经发布了以下解决方案。如果它相当不优雅我会道歉。现在,我还有两个问题:
(1)有更好的方法吗?
(2)可以通过R
和/或data.table
代码解决此问题吗?我的意思是,这个问题导致不可预测的错误,并不是第一个浮现在脑海中的东西。我的价值2美分。
答案 0 :(得分:4)
可能这与指针有关:
attributes(aDT)
$names
[1] "a" "b"
$row.names
[1] 1 2 3 4 5 6 7 8 9 10
$class
[1] "data.table" "data.frame"
$.internal.selfref
<pointer: 0x0000000000390788>
> attributes(bDT)
$names
[1] "a" "b"
$row.names
[1] 1 2 3 4 5 6 7 8 9 10
$class
[1] "data.table" "data.frame"
$.internal.selfref
<pointer: (nil)>
> attributes(bDF)
$names
[1] "a" "b"
$row.names
[1] 1 2 3 4 5 6 7 8 9 10
$class
[1] "data.frame"
> attributes(aDF)
$names
[1] "a" "b"
$row.names
[1] 1 2 3 4 5 6 7 8 9 10
$class
[1] "data.frame"
您可以使用.Internal(inspect(.))
命令仔细查看正在发生的事情:
.Internal(inspect(aDT))
.Internal(inspect(bDT))
答案 1 :(得分:3)
新加载的data.table
不知道已加载的attributes(bDT)$.internal.selfref <- attributes(aDT)$.internal.selfref
identical( aDT, bDT, ignore.environment = T )
# [1] TRUE
的指针值。你可以用
data.frame
^
不保留此属性,可能是因为它们没有进行就地修改。
答案 2 :(得分:1)
我碰巧找到了解决问题的方法(免责声明:这是一种相当不优雅的方式,但它有效!) - 添加然后删除加载的data table
中的虚拟列导致identical
成为'真正'。我还成功地将csv
替换为我自己代码中的rds
个中间文件。
老实说,我不了解R的内部运作,也不了解data table
的内部运作方式以了解其工作原理,因此欢迎任何解释和/或更优雅的解决方案。
library( data.table )
aDT <- data.table( a=1:10, b=LETTERS[1:10] )
saveRDS( aDT, file = "aDT.rds")
bDT <- readRDS( file = "aDT.rds" )
identical( aDT, bDT, ignore.environment = T ) # Gives 'False'
bDT[ , aaa := NA ]; bDT[ , aaa := NULL ]
identical( aDT, bDT, ignore.environment = T ) # Now gives 'True'
# Using the add-del-col 'trick' works here too
aDT2 <- data.table( a=1:10, b=LETTERS[1:10] )
save( aDT2, file = "aDT2.RData")
bDT2 <- aDT2; rm( aDT2 )
load( file = "aDT2.RData" )
identical( aDT2, bDT2, ignore.environment = T ) # Gives 'False'
aDT2[ , aaa := NA ]; aDT2[ , aaa := NULL ]
identical( aDT2, bDT2, ignore.environment = T ) # Now gives 'True'
答案 3 :(得分:1)
解决方案是在setDT
或load
readRDS
aDT2 <- readRDS("aDT2.RData")
setDT(aDT2)
来源:Adding new columns to a data.table by-reference within a function not always working