Skip to content

Commit

Permalink
Make sure OBJECT bit appropriately set when melting (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinushey committed Jun 30, 2014
1 parent 5f1e0d6 commit 0658e7c
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 6 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Version 1.4.0.99

* `melt.data.frame()` now properly sets the OBJECT bit on `value` variable generated if attributes are copied (for example, when multiple POSIXct columns are concatenated to generate the `value` variable) (#50)

* `melt.data.frame()` no longer errors when `measure.vars` is `NULL` or empty.
(#46)

Expand Down
11 changes: 5 additions & 6 deletions src/melt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,11 @@ List melt_dataframe(const DataFrame& data,
output[n_id + 1] = concatenate(data, measure_ind, factorsAsStrings);
if (!Rf_isNull(measure_attributes)) {
SET_ATTRIB(output[n_id + 1], measure_attributes);
}

// Set the object bit explicitly to make sure that the 'value' is properly
// interpreted as a factor
if (valueAsFactor) {
SET_OBJECT(output[n_id + 1], 1);
// we also need to make sure the OBJECT bit is set for other 'object' types
// see: http://stackoverflow.com/questions/24059460/melt-data-frame-changes-behavior-how-posixct-columns-are-printed
// if we've entered this code block, the measure_attributes has been
// populated because all value variables have identical attributes
SET_OBJECT(output[n_id + 1], OBJECT(data[measure_ind[0]]));
}

// Make the List more data.frame like
Expand Down
15 changes: 15 additions & 0 deletions tests/testthat/test-melt.r
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,18 @@ test_that("melt.data.frame behaves when there are no measure variables", {
expect_identical(df["x"], m)

})

test_that("melt.data.frame preserves OBJECT bit on e.g. POSIXct", {
t.wide <- data.frame(product=letters[1:5],
result=c(2, 4, 0, 0, 1),
t1=as.POSIXct("2014-05-26") + seq(0, 10800, length.out=5),
t2=as.POSIXct("2014-05-27") + seq(0, 10800, length.out=5),
t3=as.POSIXct("2014-05-28") + seq(0, 10800, length.out=5))

library(reshape2)
object_bit_set <- function(x) {
grepl("\\[OBJ", capture.output(.Internal(inspect(x)))[1])
}
t.long <- melt(t.wide, measure.vars=c("t1", "t2", "t3"), value.name="time")
expect_true(object_bit_set(t.long$time))
})

0 comments on commit 0658e7c

Please sign in to comment.