Reputation: 389
Curious: can someone give the explanation as to why df1 and df3 are finally assigned the same attribute even though df3 is the one explicitly modified? I would have assumed that because df1 and df3 have different memory addresses they would not be both modified. Piping issue?--How are objects being bound together?
library(lobstr)
library(dplyr)
library(data.table)
df1 <- data.frame(x = 1:3, y = letters[1:3])
df2<-data.frame(df1)
df3<-df2%>% dplyr::mutate_at(vars(ends_with("x")),
funs(data.table::setattr(.,"label","An x column")))
str(df1)
str(df3)
obj_addr(df1)
obj_addr(df3)
Results
str(df1)
'data.frame': 3 obs. of 2 variables:
$ x: int 1 2 3
..- attr(*, "label")= chr "An x column"
$ y: Factor w/ 3 levels "a","b","c": 1 2 3
str(df3)
'data.frame': 3 obs. of 2 variables:
$ x: int 1 2 3
..- attr(*, "label")= chr "An x column"
$ y: Factor w/ 3 levels "a","b","c": 1 2 3
obj_addr(df1)
[1] "0xafe6a98"
obj_addr(df3)
[1] "0x98deef0"
Upvotes: 1
Views: 85
Reputation: 3726
Per the documentation for setattr
:
In data.table, all set* functions change their input by reference. That is, no copy is made at all, other than temporary working memory which is as large as one column. The only other data.table operator that modifies input by reference is :=. Check out the See Also section below for other set* function that data.table provides.
If you want to specify attributes with the normal copy-on-modify semantics you can use structure
:
df3 <- df2 %>%
dplyr::mutate_at(vars(ends_with("x")), funs(structure(., label = "An x column")))
Upvotes: 1