Comprendre exactement quand un ensemble de données.le tableau est une référence à (vs une copie) de l'autre des données.table
Je vais avoir un peu de mal à comprendre le passage par référence à des propriétés de data.table
. Certaines opérations semblent à "casser" la référence, et j'aimerais comprendre exactement ce qui se passe.
Sur la création d'un data.table
à partir d'un autre data.table
(via <-
, puis la mise à jour de la nouvelle table en :=
, la table d'origine est également modifié. C'est prévu, comme par:
?data.table::copy
et stackoverflow: passage par référence-la-opérateur-dans-la-table de données-paquet
Voici un exemple:
library(data.table)
DT <- data.table(a=c(1,2), b=c(11,12))
print(DT)
# a b
# [1,] 1 11
# [2,] 2 12
newDT <- DT # reference, not copy
newDT[1, a := 100] # modify new DT
print(DT) # DT is modified too.
# a b
# [1,] 100 11
# [2,] 2 12
Cependant, si j'insère un non-:=
en fonction de modification entre le <-
de cession et de la :=
lignes ci-dessus, DT
n'est plus désormais modifié:
DT = data.table(a=c(1,2), b=c(11,12))
newDT <- DT
newDT$b[2] <- 200 # new operation
newDT[1, a := 100]
print(DT)
# a b
# [1,] 1 11
# [2,] 2 12
Il semble donc que la newDT$b[2] <- 200
ligne en quelque sorte des "pauses" de la référence. Je suppose que cela appelle une copie en quelque sorte, mais je voudrais comprendre pleinement comment R est le traitement de ces opérations, pour m'assurer de ne pas introduire des bugs dans mon code.
Je serais très heureux si quelqu'un pourrait-il m'expliquer cela.
<-
au lieu de =
pour l'affectation de base dans R (par exemple par Google: google.github.io/styleguide/Rguide.xml#affectation). Mais cela signifie que les données.manipulation de la table ne fonctionne pas de la même façon que le bloc de données de manipulation et est donc loin d'une baisse-dans le remplacement de bloc de données.OriginalL'auteur Peter Fine | 2012-04-19
Vous devez vous connecter pour publier un commentaire.
Oui, c'est subassignment dans R à l'aide de
<-
(ou=
ou->
) qui fait une copie de la ensemble objet. Vous pouvez les retrouver que l'utilisation detracemem(DT)
et.Internal(inspect(DT))
, comme ci-dessous. Ledata.table
caractéristiques:=
etset()
assignation par référence à un objet qu'ils sont passés. De sorte que si l'objet a été précédemment copié (par un subassigning<-
ou explicitecopy(DT)
) ensuite c'est la copie qui se modifie par référence.Remarquez comment même les
a
vecteur a été copié (différents hex valeur indique une nouvelle copie de vecteur), même sia
n'a pas été changé. Même l'ensemble deb
a été copié, plutôt que de simplement en changeant les éléments qui doivent être modifiés. C'est important pour éviter de données pour les grandes, et pourquoi:=
etset()
ont été introduits àdata.table
.Maintenant, avec notre copié
newDT
nous pouvons la modifier par la référence :Avis que tous les 3 valeurs en hexadécimal (le vecteur colonne des points, et chacun des 2 colonnes) restent inchangés. Donc c'était vraiment modifié par référence avec aucune copie.
Ou, nous pouvons modifier l'original
DT
par la référence :Ces valeurs hexadécimales sont les mêmes que les valeurs d'origine nous l'avons vu pour
DT
ci-dessus. Typeexample(copy)
pour plus d'exemples sur l'utilisation detracemem
et à la comparaison desdata.frame
.Btw, si vous
tracemem(DT)
puisDT[2,b:=600]
vous verrez un exemplaire signalé. C'est une copie de l'10 premières lignes que leprint
méthode. Lorsque enveloppé avecinvisible()
ou lorsqu'il est appelé à l'intérieur d'une fonction ou d'un script, laprint
méthode n'est pas appelée.Tout cela s'applique à l'intérieur des fonctions trop; c'est à dire,
:=
etset()
n'avez pas de copie sur écriture, même à l'intérieur des fonctions. Si vous avez besoin de modifier une copie locale, puis d'appelerx=copy(x)
au début de la fonction. Mais, rappelez-vousdata.table
est pour des données de grande taille (ainsi que plus rapidement avantages de la programmation pour les petits de données). Nous avons délibérément ne veux pas copier les grands objets (jamais). En conséquence, nous ne devons pas permettre l'habituel 3* la mémoire de travail facteur de règle générale. Nous essayons seulement de la mémoire de travail à une colonne (c'est à dire un travail de mémoire, le facteur 1/ncol plutôt que 3).OriginalL'auteur Matt Dowle
Juste un rapide résumé.
<-
avecdata.table
est juste comme la base; c'est à dire, aucune copie n'est prise jusqu'à ce qu'un subassign est fait par la suite avec<-
(comme changer les noms de colonne ou de la modification d'un élément commeDT[i,j]<-v
). Ensuite, il faut une copie de l'ensemble de l'objet comme base. Connu sous le nom de copie sur écriture. Serait mieux connu sous le nom de copie sur subassign, je pense! Il NE copie PAS lorsque vous utilisez le spécial:=
exploitant, ou de laset*
fonctions fournies pardata.table
. Si vous avez de grandes données, vous souhaiterez probablement de les utiliser à la place.:=
etset*
de ne PAS COPIER ledata.table
, MÊME à l'INTÉRIEUR des FONCTIONS.Donné cet exemple de données :
La suite que "lie" un autre nom
DT2
aux mêmes données de l'objet lié est lié au nom deDT
:Ce ne copie jamais, et jamais des copies de base. Elle marque simplement l'objet de données de sorte que R sait que les deux noms différents (
DT2
etDT
) pointent vers le même objet. Et donc R aurez besoin de copier l'objet, si l'un et l'autre sont subassigned pour la suite.Qui est parfait pour
data.table
, trop. Le:=
n'est pas pour le faire. Donc la suite est une faute intentionnelle comme:=
n'est pas juste pour la liaison des noms d'objets ::=
est pour subassigning par référence. Mais vous ne l'utilisez pas comme vous le feriez dans la base :vous l'utiliser comme ceci :
Qui a changé
DT
par référence. Dites vous ajoutez une nouvelle colonnenew
par référence à l'objet de données, il n'est pas nécessaire pour ce faire :parce que le membre de droite déjà changé
DT
par référence. L'extraDT <-
, c'est mal comprendre ce que:=
. Vous pouvez l'écrire là, mais c'est superflu.DT
est modifié par référence, par:=
, MÊME à l'INTÉRIEUR des FONCTIONS :data.table
est pour les grands ensembles de données, n'oubliez pas. Si vous avez un 20 GOdata.table
dans la mémoire, alors vous besoin d'un moyen pour ce faire. C'est un très délibérée décision de conception dedata.table
.Des Copies peuvent être faites, bien sûr. Vous avez juste besoin de raconter des données.la table que vous êtes sûr que vous voulez copier vos 20 GO jeu de données, à l'aide de la
copy()
fonction :Pour éviter les copies, ne pas utiliser de base de type affectation ou de mise à jour :
Si vous voulez être sûr que vous êtes la mise à jour par l'usage de référence
.Internal(inspect(x))
et de regarder l'adresse de la mémoire de valeurs de composantes (voir Matthieu Dowle de réponse).Écrit
:=
dansj
comme qui vous permet subassign par référence par groupe. Vous pouvez ajouter une nouvelle colonne en référence par le groupe. C'est pourquoi:=
est fait de cette façon à l'intérieur de[...]
:OriginalL'auteur statquant