23stacks1254
23stacks1254

Reputation: 389

Why does this dataframe variable take an attribute not explicity assigned to it? (dplyr-R)

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

Answers (1)

dave-edison
dave-edison

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

Related Questions