4

I have a data set which has attributes and when I do rbind() with this data, I loose all the attributes.

Is it possible to copy all the attributes as it's when using rbind()? The number of columns in both the data set is same including the column name.

Reproducible Data

> attr(output$column1, "metadata")$DP.SomeNumber1
NULL
> attr(output$column2, "metadata")$DP.SomeNumber2
NULL

> column1 <- rep(-0.01, 8)
> attr(column1, "metadata")$DP.SomeNumber1 <- "6200"
> column2 <- rep(0.05, 8)
> attr(column2, "metadata")$DP.SomeNumber2 <- "7200"
> data <- data.frame(column1, column2)

> attr(data$column1, "metadata")$DP.SomeNumber1
[1] "6200"
> attr(data$column2, "metadata")$DP.SomeNumber2
[1] "7200"

> newdata <- as.data.frame(matrix(0, nrow = 3, ncol = ncol(data)))
> colnames(newdata) <- colnames(data) 
> output <- rbind(newdata,data) 

> attr(output$column1, "metadata")$DP.SomeNumber1
NULL
> attr(output$column2, "metadata")$DP.SomeNumber2
NULL

When using rbindlist() in data.table() library, I still don't the attributes:

> testdata <- rbindlist(list(newdata, data))
> attr(testdata$column1, "metadata")$DP.SomeNumber1
NULL
> attr(testdata$column2, "metadata")$DP.SomeNumber2
NULL

Credits to MarkusN for above attribute example.

Thanks.


Update 1

I tried copy.attributes() as suggested here, but even then attributes didn't get copied to new data frame.

Update 2

Following worked, but I cannot do this when I have 1000+ columns. In below I am specifically copying attributes attached to column.

> column1 <- rep(-0.01, 8)
> attr(column1, "metadata")$DP.SomeNumber1 <- "6200"
> column2 <- rep(0.05, 8)
> attr(column2, "metadata")$DP.SomeNumber2 <- "7200"

> data <- data.frame(column1, column2)

> print(attributes(data$column1))
$metadata
$metadata$DP.SomeNumber1
[1] "6200"
> print(attributes(data$column2))
$metadata
$metadata$DP.SomeNumber2
[1] "7200"

> newdata <- as.data.frame(matrix(0, nrow = 3, ncol = ncol(data)))
> colnames(newdata) <- colnames(data)

> output <- rbind(newdata,data)

> attributes(output$column1) <- attributes(data$column1)
> attributes(output$column2) <- attributes(data$column2)

> attr(output$column1, "metadata")$DP.SomeNumber1
[1] "6200"
> attr(output$column2, "metadata")$DP.SomeNumber2
[1] "7200"

Any suggestions, how I can refer to attributes attached to column recursively?

Update 3

For my problem, following solution worked because I had only three attributes that were of interest to me:

columnNumber <- 1

for (columnNumber in 1:length(data)){
 output[1,columnNumber] <- attr(data[,columnNumber], "metadata")$DP.SomeNumber1
 output[2,columnNumber] <- attr(data[,columnNumber], "metadata")$DP.SomeNumber2
 output[3,columnNumber] <- attr(data[,columnNumber], "metadata")$DP.SomeNumber3
}

Above solution is case specific, but it's possible to extract attributes after rbind() (actually rbind() becomes redundant here) as long as one has access to the original data with attributes. Also, the column alignment should not differ from the new data set, else solution needs to be more adaptive.

Chetan Arvind Patil
  • 854
  • 1
  • 11
  • 31
  • Can you provide a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)? – Samuel Sep 16 '17 at 22:06
  • If you try `rbindlist` from the `data.table` package on your df's does it keep the attributes? – D.sen Sep 16 '17 at 22:06
  • @Samuel - I added an example. Please check. – Chetan Arvind Patil Sep 16 '17 at 22:19
  • @D.sen - No. I also added example in question. As per `rbindlist()` [documentation](https://www.rdocumentation.org/packages/data.table/versions/1.10.4/topics/rbindlist), it says, "*Note that any additional attributes that might exist on individual items of the input list would not be preserved in the result*". Is it not possible with base `R` packages? – Chetan Arvind Patil Sep 16 '17 at 22:46
  • What if you extract the attributes and put them in their own columns in the data frame before you `rbind`? – Samuel Sep 16 '17 at 23:26
  • @Samuel - I think I tried same thing. In *update 2*, I got some success, but can't use this for larger data set. – Chetan Arvind Patil Sep 16 '17 at 23:33

1 Answers1

0

Quite late, but I more or less also wanted to copy attributes. Here is my solution (see also here for some fallacies):

copyAttributes <- function(from, to) {
  fromAttributeNames <- names(attributes(from))
  protectedAttributes <- c("dim", "dimnames", "class", "comment",
                           "names", "row.names", "tsp")
  x <- setdiff(fromAttributeNames, protectedAttributes)
  if (length(x) > 0) {
    ind <- which(!fromAttributeNames %in% protectedAttributes)
    for (i in 1:length(ind)) {
      attr(x = to, which = fromAttributeNames[ind[i]]) <-
        attributes(from)[[ind[i]]]
    }
  }
  return(to)
}

Hope that helps to make your case work...

Christoph
  • 6,841
  • 4
  • 37
  • 89