Skip to content

Commit

Permalink
Add sep argument to spread.
Browse files Browse the repository at this point in the history
  • Loading branch information
hadley committed May 22, 2016
1 parent 902326b commit 559b732
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 9 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# tidyr 0.4.1.9000

* `spread()` gains a `sep` argument. If not-null, this will name columns
as "key<sep>value". Additionally, if sep is `NULL` missing values will be
converted to `<NA>` (#68).

* `unnest()` now works with non-syntactic names (#190).

* `unnest()` gains `.id` argument that works the same way as `bind_rows()`.
Expand Down
29 changes: 22 additions & 7 deletions R/spread.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
#' value = c(5.1, "setosa", 1, 7.0, "versicolor", 2))
#' df %>% spread(var, value) %>% str
#' df %>% spread(var, value, convert = TRUE) %>% str
spread <- function(data, key, value, fill = NA, convert = FALSE, drop = TRUE) {
spread <- function(data, key, value, fill = NA, convert = FALSE, drop = TRUE,
sep = NULL) {
key_col <- col_name(substitute(key))
value_col <- col_name(substitute(value))

spread_(data, key_col, value_col, fill = fill, convert = convert, drop = drop)
spread_(data, key_col, value_col, fill = fill, convert = convert, drop = drop,
sep = sep)
}

#' Standard-evaluation version of \code{spread}.
Expand All @@ -55,10 +57,13 @@ spread <- function(data, key, value, fill = NA, convert = FALSE, drop = TRUE) {
#' conversion.
#' @param drop If \code{FALSE}, will keep factor levels that don't appear in the
#' data, filling in missing combinations with \code{fill}.
#' @param sep If \code{NULL}, the column names will be taken from the values of
#' \code{key} variable. If non-\code{NULL}, the column names will be given
#' by "<key_name><sep><key_value>".
#' @keywords internal
#' @export
spread_ <- function(data, key_col, value_col, fill = NA, convert = FALSE,
drop = TRUE) {
drop = TRUE, sep = NULL) {
if (!(key_col %in% names(data))) {
stop("Key column '", key_col, "' does not exist in input.", call. = FALSE)
}
Expand All @@ -72,7 +77,7 @@ spread_ <- function(data, key_col, value_col, fill = NA, convert = FALSE,
#' @export
#' @importFrom tibble as_data_frame
spread_.data.frame <- function(data, key_col, value_col, fill = NA,
convert = FALSE, drop = TRUE) {
convert = FALSE, drop = TRUE, sep = NULL) {

col <- data[key_col]
col_id <- id(col, drop = drop)
Expand Down Expand Up @@ -120,7 +125,7 @@ spread_.data.frame <- function(data, key_col, value_col, fill = NA,
ordered <- as.character(ordered)
}
dim(ordered) <- c(attr(row_id, "n"), attr(col_id, "n"))
colnames(ordered) <- as.character(col_labels[[1]])
colnames(ordered) <- col_names(col_labels, sep = sep)

ordered <- as_data_frame_matrix(ordered)

Expand All @@ -131,19 +136,29 @@ spread_.data.frame <- function(data, key_col, value_col, fill = NA,
append_df(row_labels, ordered)
}

col_names <- function(x, sep = NULL) {
names <- as.character(x[[1]])

if (is.null(sep)) {
ifelse(is.na(names), "<NA>", names)
} else {
paste(names(x)[[1]], names, sep = sep)
}
}

as_data_frame_matrix <- function(x) {
utils::getS3method("as_data_frame", "matrix", envir = asNamespace("tibble"))(x)
}

#' @export
spread_.tbl_df <- function(data, key_col, value_col, fill = NA,
convert = FALSE, drop = TRUE) {
convert = FALSE, drop = TRUE, sep = NULL) {
as_data_frame(NextMethod())
}

#' @export
spread_.grouped_df <- function(data, key_col, value_col, fill = NA,
convert = FALSE, drop = TRUE) {
convert = FALSE, drop = TRUE, sep = NULL) {
regroup(NextMethod(), data, c(key_col, value_col))
}

Expand Down
7 changes: 6 additions & 1 deletion man/spread.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion man/spread_.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions tests/testthat/test-spread.R
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,14 @@ test_that("grouping vars are kept where possible", {
out <- df %>% group_by(key) %>% spread(key, value)
expect_equal(out, data_frame(a = 1L, b = 2L))
})


test_that("col names never contains NA", {
df <- data_frame(x = c(1, NA), y = 1:2)
df %>%
spread(x, y) %>%
expect_named(c("1", "<NA>"))
df %>%
spread(x, y, sep = "_") %>%
expect_named(c("x_1", "x_NA"))
})

0 comments on commit 559b732

Please sign in to comment.