Hinzufügen neuer Spalten zu einer data.table-Referenz innerhalb einer Funktion, die nicht immer funktioniert

Beim Schreiben eines Pakets, das auf @ berudata.table, Ich habe ein merkwürdiges Verhalten entdeckt. Ich habe eine Funktion, die einige Spalten nach Verweis entfernt und neu anordnet, und sie funktioniert einwandfrei, was bedeutet, dass dasdata.table Ich übergeben wurde geändert, ohne die Funktionsausgabe zuzuweisen. Ich habe eine andere Funktion, die @ hinzufüNe -Spalten, aber diese Änderungen bleiben nicht immer im @ erhaltdata.table was übergeben wurde.

Hier ist ein kleines Beispiel:

library(data.table)  # I'm using 1.9.4
test <- data.table(id = letters[1:2], val=1:2)
foobar <- function(dt, col) {
    dt[, (col) := 1]
    invisible(dt)
}

test
#  id val
#1: a   1
#2: b   2
saveRDS(test, "test.rds")
test2 <- readRDS("test.rds")
all.equal(test, test2)
#[1] TRUE
foobar(test, "new")
test
#  id val new
#1: a   1   1
#2: b   2   1
foobar(test2, "new")
test2
#  id val
#1: a   1
#2: b   2

Was ist passiert? Was ist anders antest2? Ich kann vorhandene Spalten in folgenden Fällen direkt ändern:

foobar(test, "val")
test
#  id val new
#1: a   1   1
#2: b   1   1
foobar(test2, "val")
test2
#  id val
#1: a   1
#2: b   1

Aber zu @ hinzufügtest2 funktioniert immer noch nicht:

foobar(test2, "someothercol")
.Last.value
#  id val someothercol
#1: a   1            1
#2: b   1            1
test2
#  id val
#1: a   1
#2: b   1

Ich kann nicht alle Fälle festlegen, in denen ich dieses Verhalten sehe, aber das Speichern und Lesen von RDS ist der erste Fall, den ich zuverlässig replizieren kann. Das Schreiben und Lesen in eine CSV scheint nicht dasselbe Problem zu haben.

Ist dies ein Zeiger Problem aladieses Proble, wie das Serialisieren einer data.table die überbelegten Zeiger zerstört? Gibt es eine einfache Möglichkeit, sie wiederherzustellen? Wie kann ich in meiner Funktion nach ihnen suchen, um die Zeiger oder Fehler wiederherzustellen, wenn der Vorgang nicht funktioniert?

Ich weiß, dass ich die Funktionsausgabe als Problemumgehung zuweisen kann, aber das ist nicht sehrdata.table -y. Würde das nicht auch eine temporäre Kopie im Speicher erstellen?

Antwort auf Aruns Lösung

Arun hat angewiesen, dass es sich in der Tat um ein Zeigerproblem handelt, das mit @ diagnostiziert werden kantruelength und fixiert mitsetDT oderalloc.col. Ich bin auf ein Problem gestoßen, bei dem seine Lösung in einer Funktion zusammengefasst wurde (Fortsetzung von obigem Code):

func <- function(dt) {if (!truelength(dt)) setDT(dt)}
func2 <- function(dt) {if (!truelength(dt)) alloc.col(dt)}
test2 <- readRDS("test.rds")
truelength(test2)
#[1] 0
truelength(func(test2))
#[1] 100
truelength(test2)
#[1] 0
truelength(func2(test2))
#[1] 100
truelength(test2)
#[1] 0

So sieht es so aus, als ob die lokale Kopie in der Funktion ordnungsgemäß geändert wird, die Referenzversion jedoch nicht. Warum nicht

Antworten auf die Frage(2)

Ihre Antwort auf die Frage