Skip to content

Commit

Permalink
Closes #1132. setDF converts list of equal lengths to DF by ref.
Browse files Browse the repository at this point in the history
  • Loading branch information
arunsrinivasan committed Apr 29, 2015
1 parent 765111b commit a94b83d
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
21 changes: 20 additions & 1 deletion R/data.table.R
Original file line number Diff line number Diff line change
Expand Up @@ -2374,13 +2374,32 @@ address <- function(x) .Call(Caddress, eval(substitute(x), parent.frame()))
":=" <- function(...) stop('Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").')

setDF <- function(x) {
if (!is.data.table(x) && !is.data.frame(x)) stop("setDF only accepts data.table or data.frame as input")
if (!is.list(x)) stop("setDF only accepts data.table, data.frame or list of equal length as input")
if (is.data.table(x)) {
# copied from as.data.frame.data.table
setattr(x, "row.names", .set_row_names(nrow(x)))
setattr(x, "class", "data.frame")
setattr(x, "sorted", NULL)
setattr(x, ".internal.selfref", NULL)
} else if (is.data.frame(x)) {
x
} else {
n = vapply(x, length, 0L)
mn = max(n)
if (any(n<mn))
stop("All elements in argument 'x' to 'setDF' must be of same length")
xn = names(x)
if (is.null(xn)) {
setattr(x, "names", paste("V",seq_len(length(x)),sep=""))
} else {
idx = xn %chin% ""
if (any(idx)) {
xn[idx] = paste("V", seq_along(which(idx)), sep="")
setattr(x, "names", xn)
}
}
setattr(x,"row.names",.set_row_names(max(n)))
setattr(x,"class","data.frame")
}
invisible(x)
}
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@

20. `setDT` gains a `key` argument so that `setDT(X, key="a")` would convert `X` to a `data.table` by reference *and* key by the columns specified. Closes [#1121](https:/Rdatatable/data.table/issues/1121).

21. `setDF` also converts `list` of equal length to `data.frame` by reference now. Closes [#1132](https:/Rdatatable/data.table/issues/1132).

#### BUG FIXES

1. `if (TRUE) DT[,LHS:=RHS]` no longer prints, [#869](https:/Rdatatable/data.table/issues/869). Tests added. To get this to work we've had to live with one downside: if a `:=` is used inside a function with no `DT[]` before the end of the function, then the next time `DT` is typed at the prompt, nothing will be printed. A repeated `DT` will print. To avoid this: include a `DT[]` after the last `:=` in your function. If that is not possible (e.g., it's not a function you can change) then `print(DT)` and `DT[]` at the prompt are guaranteed to print. As before, adding an extra `[]` on the end of `:=` query is a recommended idiom to update and then print; e.g. `> DT[,foo:=3L][]`. Thanks to Jureiss for reporting.
Expand Down
7 changes: 7 additions & 0 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -4724,6 +4724,13 @@ test(1305.1, setDF(DT), data.frame(x=1:5, y=6:10))
# setDF should return if input is data.frame, not error.
df <- data.frame(x=1:5, y=6:10)
test(1305.2, setDF(df), df) # setDF works on data.frame
# setDF also works on lists with equal lengths, #1132
df <- list(a=1:5, b=6:10)
test(1305.3, data.frame(df), setDF(df))
df <- list(1:5, 6:10)
test(1305.4, setDF(as.data.table(df)), setDF(df))
test(1305.5, setDF(1:5), error="setDF only accepts")
test(1305.6, setDF(list(1, 2:3)), error="All elements in argument")

# .SD retains as much of head(key) as appropriate.
# by= always keeps data appearance order, so it's which columns are grouped and selected that drive how much of key is retained
Expand Down
8 changes: 6 additions & 2 deletions man/setDF.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
\description{
In \code{data.table} parlance, all \code{set*} functions change their input \emph{by reference}. That is, no copy is made at all, other than temporary working memory, which is as large as one column.. The only other \code{data.table} operator that modifies input by reference is \code{\link{:=}}. Check out the \code{See Also} section below for other \code{set*} function \code{data.table} provides.

A helper function to convert a \code{data.table} to \code{data.frame} by reference. It does not handle lists or lists of data.tables.
A helper function to convert a \code{data.table} or \code{list} of equal length to \code{data.frame} by reference.
}
\usage{
setDF(x)
}
\arguments{
\item{x}{ A \code{data.table}. }
\item{x}{ A \code{data.table}, \code{data.frame} or \code{list} of equal length. }
}

\details{
Expand All @@ -27,6 +27,10 @@ setDF(x)
X = data.table(x=1:5, y=6:10)
## convert 'X' to data.frame, without any copy.
setDF(X)

X = list(x=1:5, y=6:10)
# X is converted to a data.frame without any copy.
setDF(X)
}
\keyword{ data }

0 comments on commit a94b83d

Please sign in to comment.