2012-06-25 7 views
6

Me he dado cuenta de un comportamiento inconsistente (incoherente para mí) en data.table cuando se utilizan diferentes operadores de asignación. Tengo que admitir que nunca conseguí la diferencia entre "=" y copiar(), así que tal vez podamos arrojar algo de luz aquí. Si usa "=" o "< -" en lugar de copiar() a continuación, al cambiar la tabla de datos copiados, la tabla de datos original también cambiará.data.table 1.8.1 .: "DT1 = DT2" no es lo mismo que DT1 = copy (DT2)?

Por favor, ejecute los siguientes comandos y verá lo que quiero decir

library(data.table) 
example(data.table) 

DT 
    x y v 
1: a 1 42 
2: a 3 42 
3: a 6 42 
4: b 1 4 
5: b 3 5 
6: b 6 6 
7: c 1 7 
8: c 3 8 
9: c 6 9 

DT2 = DT 

Ahora voy a cambiar la columna V de la DT2:

DT2[ ,v:=3L] 
    x y v 
1: a 1 3 
2: a 3 3 
3: a 6 3 
4: b 1 3 
5: b 3 3 
6: b 6 3 
7: c 1 3 
8: c 3 3 
9: c 6 3 

pero mira lo que pasó con DT:

DT 
    x y v 
1: a 1 3 
2: a 3 3 
3: a 6 3 
4: b 1 3 
5: b 3 3 
6: b 6 3 
7: c 1 3 
8: c 3 3 
9: c 6 3 

cambió también. así que: al cambiar DT2 se cambió el DT original. no es así si uso copy():

example(data.table) # reset DT 
DT3 <- copy(DT) 
DT3[, v:= 3L] 
    x y v 
1: a 1 3 
2: a 3 3 
3: a 6 3 
4: b 1 3 
5: b 3 3 
6: b 6 3 
7: c 1 3 
8: c 3 3 
9: c 6 3 

DT 
    x y v 
1: a 1 42 
2: a 3 42 
3: a 6 42 
4: b 1 4 
5: b 3 5 
6: b 6 6 
7: c 1 7 
8: c 3 8 
9: c 6 9 

¿Este comportamiento es esperado?

Respuesta

10

Sí. Este es el comportamiento esperado, y está bien documentado.

Dado que data.table utiliza referencias al objeto original para lograr modificar en el lugar, es muy rápido.

Por esta razón, si realmente desea copiar los datos, es necesario utilizar copy(DT)


De la documentación para ?copy:

El data.table es modificado por referencia, y devuelto (invisiblemente) así que se puede utilizar en declaraciones compuestas; por ejemplo, setkey(DT,a)[J("foo")]. Si necesita una copia, primero tome una copia (usando DT2=copy(DT)). copy() también puede ser útil en ocasiones antes de := se utiliza para asignar a una columna por referencia. Ver ?copy.

Ver también esta pregunta: Understanding exactly when a data.table is a reference to vs a copy of another

+0

Gracias @Andrie. Entiendo la asignación por referencia, y por qué evitar copiar en primer lugar. Me parece extraño que '=' cree un vínculo entre la copia y el original, como si fueran el mismo objeto (cuando ese no es el caso en R de lo contrario). –

+0

@FlorianOswald Estoy de acuerdo, esto puede ser una trampa si no se tiene cuidado. – Andrie

+1

+10 si pudiera Andrie. @Florian Imagine una tabla de 20GB + en la memoria. No queremos copiarlo, ni siquiera una vez. Pero si realmente quieres, puedes. No rompe la compatibilidad con otros paquetes, porque solo es ': =' y las funciones 'set *' que se asignan por referencia. Es una de las razones por las que presentamos un nuevo operador (': ='), en lugar de hacer que '<-' funcione de manera diferente. –

Cuestiones relacionadas