Skip to content

Commit

Permalink
Merge pull request #55 from kevinushey/master
Browse files Browse the repository at this point in the history
Make sure OBJECT bit appropriately set when melting (#50)
  • Loading branch information
hadley committed Jun 30, 2014
2 parents 379036a + 0658e7c commit 28e22a1
Show file tree
Hide file tree
Showing 20 changed files with 39 additions and 23 deletions.
2 changes: 1 addition & 1 deletion NAMESPACE
@@ -1,4 +1,4 @@
# Generated by roxygen2 (4.0.0): do not edit by hand
# Generated by roxygen2 (4.0.1): do not edit by hand

S3method(melt,array)
S3method(melt,data.frame)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
@@ -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
2 changes: 1 addition & 1 deletion man/add_margins.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{add_margins}
\alias{add_margins}
\title{Add margins to a data frame.}
Expand Down
2 changes: 1 addition & 1 deletion man/cast.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{cast}
\alias{acast}
\alias{cast}
Expand Down
2 changes: 1 addition & 1 deletion man/colsplit.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{colsplit}
\alias{colsplit}
\title{Split a vector into multiple columns}
Expand Down
2 changes: 1 addition & 1 deletion man/french_fries.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\docType{data}
\name{french_fries}
\alias{french_fries}
Expand Down
2 changes: 1 addition & 1 deletion man/guess_value.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{guess_value}
\alias{guess_value}
\title{Guess name of value column}
Expand Down
2 changes: 1 addition & 1 deletion man/margins.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{margins}
\alias{margins}
\title{Figure out margining variables.}
Expand Down
2 changes: 1 addition & 1 deletion man/melt.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{melt}
\alias{melt}
\title{Convert an object into a molten data frame.}
Expand Down
2 changes: 1 addition & 1 deletion man/melt.array.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{melt.array}
\alias{melt.array}
\alias{melt.matrix}
Expand Down
2 changes: 1 addition & 1 deletion man/melt.data.frame.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{melt.data.frame}
\alias{melt.data.frame}
\title{Melt a data frame into form suitable for easy casting.}
Expand Down
2 changes: 1 addition & 1 deletion man/melt.default.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{melt.default}
\alias{melt.default}
\title{Melt a vector.
Expand Down
2 changes: 1 addition & 1 deletion man/melt.list.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{melt.list}
\alias{melt.list}
\title{Melt a list by recursively melting each component.}
Expand Down
2 changes: 1 addition & 1 deletion man/melt_check.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{melt_check}
\alias{melt_check}
\title{Check that input variables to melt are appropriate.}
Expand Down
2 changes: 1 addition & 1 deletion man/parse_formula.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{parse_formula}
\alias{parse_formula}
\title{Parse casting formulae.}
Expand Down
2 changes: 1 addition & 1 deletion man/recast.Rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{recast}
\alias{recast}
\title{Recast: melt and cast in a single step}
Expand Down
2 changes: 1 addition & 1 deletion man/smiths.rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\docType{data}
\name{smiths}
\alias{smiths}
Expand Down
2 changes: 1 addition & 1 deletion man/tips.rd
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\docType{data}
\name{tips}
\alias{tips}
Expand Down
11 changes: 5 additions & 6 deletions src/melt.cpp
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
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 28e22a1

Please sign in to comment.