diff --git a/NEWS.md b/NEWS.md index ee33784f7..3a9b63c40 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ * `crossing()` preserves factor levels (#410). +* `spread()` works when the id variable has names (#525). + # tidyr 0.8.2 * `separate()` now accepts `NA` as a column name in the `into` argument to diff --git a/R/id.R b/R/id.R index e4302c0c9..48124e7c3 100644 --- a/R/id.R +++ b/R/id.R @@ -38,7 +38,7 @@ id <- function(.variables, drop = FALSE) { } id_var <- function(x, drop = FALSE) { - if (!is_null(attr(x, "n")) && !drop) return(x) + if (!is_null(attr(x, "n", exact = TRUE)) && !drop) return(x) if (is.factor(x) && !drop) { x_na <- addNA(x, ifany = TRUE) diff --git a/tests/testthat/test-id.R b/tests/testthat/test-id.R index 7eb1356d7..c65e905c2 100644 --- a/tests/testthat/test-id.R +++ b/tests/testthat/test-id.R @@ -1,7 +1,7 @@ context("id") test_that("drop preserves count of factor levels", { - x <- factor(, levels = c("a", "b")) + x <- factor(levels = c("a", "b")) expect_equal(id_var(x), structure(integer(), n = 2)) expect_equal(id(data.frame(x)), structure(integer(), n = 2)) }) @@ -10,3 +10,8 @@ test_that("id works with dimensions beyond integer range", { df <- data.frame(matrix(c(1, 2), nrow = 2, ncol = 32)) expect_equal(id(df), structure(c(1, 2), n = 2 ^ 32)) }) + +test_that("id_var() handles named vectors (#525)", { + res <- id_var(c(a = 5, b = 3, c = 5)) + expect_equal(res, structure(c(2L, 1L, 2L), n = 2L)) +}) diff --git a/tests/testthat/test-spread.R b/tests/testthat/test-spread.R index acf597d65..d0ada651d 100644 --- a/tests/testthat/test-spread.R +++ b/tests/testthat/test-spread.R @@ -278,3 +278,14 @@ test_that("ulevels returns unique elements of a list for a list input", { test_list <- list(a = 1:6, b = 1:6) expect_equal(ulevels(test_list), unique(test_list)) }) + +test_that("spread works when id column has names (#525)", { + df <- tibble( + key = factor(c("a", "b", "c"), levels = letters[1:5]), + out = 1:3, + id = c(a = 1, b = 2, c = 3) + ) + res <- spread(df, key, out, drop = FALSE) + expect_equal(names(res), c("id", letters[1:5])) +}) +