2015-07-06 10 views
10

SfondoR - readRDS() e load() sicuro invia data.tables identiche all'originale

Ho provato a sostituire alcuni file di output CSV con rds file per migliorare l'efficienza. Questi sono file intermedi che serviranno da input per altri script R.

Domanda

ho iniziato a indagare quando i miei script non è riuscito e ha scoperto che readRDS() e load() non tornano identiche data tables come l'originale. Questo dovrebbe succedere? O mi sono perso qualcosa?

codice di esempio

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' 

Sono in esecuzione R ver 3.2.0 su Linux Mint e testato con data.table ver 1.9.4 e 1.9.5 (l'ultima).

La ricerca in SO e Google ha restituito this e this ma non penso che rispondano a questo problema. Sto ancora cercando di capire perché i miei script hanno fallito quando sono passato a rds ma sto iniziando con questo.

Apprezzeremmo molto se i membri SO ben informati possono aiutare. Grazie!

Edit:

Ciao a tutti, mi è capitato di trovare un modo per risolvere il problema - hanno inviato la soluzione qui di seguito. Mi scuso se è piuttosto inelegante. Ora ho altre 2 domande:

(1) Esiste un modo migliore?

(2) È possibile eseguire qualcosa sul codice R e/o data.table per risolvere questo problema? Voglio dire, questo problema causa bug imprevedibili e non è la prima cosa che mi viene in mente. I miei 2 centesimi.

+3

ma poi 'all.equal (ADT, BDT)' #TRUE – user20650

+1

Hmm ... buona punto ... Ho sempre usato solo 'identico'. Andando attraverso? All.equal' mostra che si tratta di un test per 'quasi-uguaglianza', quindi forse la differenza è nei suggerimenti come menzionato dai 2 signori qui sotto? – NoviceProg

risposta

3

Il nuovo carico data.table non conosce il valore del puntatore di quello già caricato. Si potrebbe dire con

attributes(bDT)$.internal.selfref <- attributes(aDT)$.internal.selfref 
identical(aDT, bDT, ignore.environment = T) 
# [1] TRUE 

data.frame non tenere questo attributo, probabilmente perché non fanno in atto la modifica.

+0

Ciao @LegalizeIt, vedo dove stai andando ma cosa succede se lo script che carica bDT non ha accesso ad aDT? Questa è la ragione per i file intermedi ('csv' /' rds'). – NoviceProg

3

Probabilmente, questo ha a che fare con i puntatori:

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" 

Potete strettamente guardare a ciò che sta succedendo con .Internal(inspect(.)) comando:

.Internal(inspect(aDT)) 

.Internal(inspect(bDT)) 
+0

Grazie per la tua risposta, @ user227710. C'è un modo per ristabilire il puntatore per la 'tabella dati' che è stata ricaricata, senza accedere al DT originale? – NoviceProg

+1

@NoviceProg: il problema è più dettagliato nei dettagli [qui] (http://r.789695.n4.nabble.com/What-is-going-on-with-R-3-1-td4689002.html). 'saveRDS' non salva' .internal.selfref' quindi, penso che non sia possibile. – user227710

+0

Ho seguito il link che hai fornito e il thread SO nel link. È interessante notare che hanno menzionato il problema è stato risolto in 'tabella dati' v1.9.3, non sono sicuro se tale OP si trovasse di fronte a un problema simile. – NoviceProg

1

mi capita di trovare un modo che risolve il problema (dichiarazione di non responsabilità : è un modo piuttosto inelegante ma funziona!) - aggiungendo quindi l'eliminazione di una colonna fittizia nel data table caricato conduce a identical in "True". Ho anche sostituito con successo csv con i file intermedi rds nel mio codice.

Per essere onesto, non capisco abbastanza del funzionamento interno di R né di data table per sapere perché funziona, quindi qualsiasi spiegazione e/o soluzioni più eleganti sarebbero benvenute.

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' 
Problemi correlati