-
Notifications
You must be signed in to change notification settings - Fork 1.1k
keep argument for transpose and tstrsplit
#7883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,8 @@ | ||
| transpose = function(l, fill=NA, ignore.empty=FALSE, keep.names=NULL, make.names=NULL, list.cols=FALSE) { | ||
| transpose = function(l, fill=NA, ignore.empty=FALSE, keep.names=NULL, make.names=NULL, list.cols=FALSE, keep=NULL) { | ||
| if (!is.null(keep)) { | ||
| if (!is.numeric(keep)) stopf("'keep' must be an integer vector.") | ||
| keep = as.integer(keep) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: missing indent |
||
| } | ||
| if (!is.null(make.names)) { | ||
| stopifnot(length(make.names)==1L) | ||
| if (is.character(make.names)) { | ||
|
|
@@ -14,7 +18,7 @@ transpose = function(l, fill=NA, ignore.empty=FALSE, keep.names=NULL, make.names | |
| colnames = as.character(l[[make.names]]) | ||
| l = if (is.data.table(l)) l[,-make.names,with=FALSE] else l[-make.names] | ||
| } | ||
| ans = .Call(Ctranspose, l, fill, ignore.empty, keep.names, list.cols) | ||
| ans = .Call(Ctranspose, l, fill, ignore.empty, keep.names, list.cols, keep) | ||
| if (!is.null(make.names)) setattr(ans, "names", c(keep.names, colnames)) | ||
| else if (is.data.frame(l)) # including data.table but not plain list | ||
| setattr(ans, "names", c(keep.names, paste0("V", seq_len(length(ans)-length(keep.names))))) | ||
|
|
@@ -30,18 +34,22 @@ tstrsplit = function(x, ..., fill=NA, type.convert=FALSE, keep, names=FALSE, rev | |
| stopf("'rev' must be TRUE or FALSE.") | ||
| ans = strsplit(as.character(x), ...) | ||
| if (rev) ans = lapply(ans, base::rev) | ||
| ans = transpose(ans, fill=fill, ignore.empty=FALSE) | ||
|
|
||
| if (!missing(keep)) { | ||
| keep = suppressWarnings(as.integer(keep)) | ||
| chk = min(keep) >= min(1L, length(ans)) & max(keep) <= length(ans) | ||
| if (!isTRUE(chk) || !length(keep)) | ||
| stopf("'keep' should contain integer values between %d and %d.", min(1L, length(ans)), length(ans)) | ||
| maxlen = if (length(ans)) max(lengths(ans)) else 0L | ||
| chk = min(keep, na.rm=TRUE) >= min(1L, maxlen) && max(keep, na.rm=TRUE) <= maxlen | ||
| if (!isTRUE(chk) || !length(keep) || anyNA(keep)) | ||
| stopf("'keep' should contain integer values between %d and %d.", min(1L, maxlen), maxlen) | ||
| can_keep_early = isFALSE(type.convert) | ||
| ans = transpose(ans, fill=fill, ignore.empty=FALSE, keep = if (can_keep_early) keep else NULL) | ||
| } else { | ||
| ans = transpose(ans, fill=fill, ignore.empty=FALSE) | ||
| keep = seq_along(ans) | ||
| } | ||
| if (isFALSE(type.convert)) | ||
| ans = ans[keep] | ||
|
|
||
| if (isFALSE(type.convert)) { | ||
| if (length(ans) != length(keep)) ans = ans[keep] | ||
| } | ||
| # Implementing #1094, but default FALSE | ||
| else if (isTRUE(type.convert)) | ||
| ans = lapply(ans[keep], type.convert, as.is=TRUE) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21985,3 +21985,16 @@ DT3 = data.table(a=c(1,NA), b=c("x",NA), c=c(3,NA)) | |
| test(2387.04, setnafill(copy(DT3), type="locf", cols=sapply(DT3, is.numeric)), data.table(a=c(1,1), b=c("x",NA), c=c(3,3))) | ||
| test(2387.05, setnafill(copy(DT3), type="locf", cols=c(TRUE,NA,FALSE)), error="'cols' contains NA at position 2") | ||
| test(2387.06, setnafill(copy(DT3), type="locf", cols=c(TRUE,FALSE)), error="'cols' is a logical vector of length 2 but there are 3 columns") | ||
|
|
||
| # transpose() supports keep argument, #5250 | ||
| x = list(1:5, 6:10, 11:15) | ||
| test(2388.01, transpose(list(1:5), keep="a"), error="'keep' must be an integer vector.") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are tests .01 and .10 not identical? |
||
| test(2388.02, transpose(x, keep=c(5L,3L,1L)), transpose(x)[c(5,3,1)]) | ||
| test(2388.03, transpose(x, keep=c(1L,1L,3L)), transpose(x)[c(1,1,3)]) | ||
| test(2388.04, transpose(x, keep=NULL), transpose(x)) | ||
| test(2388.05, transpose(x, keep=1:2, fill=NA), transpose(x, fill=NA)[1:2]) | ||
| test(2388.06, transpose(x, keep=integer()), list()) | ||
| test(2388.07, transpose(list(1:5), keep=10L), error="'keep' index 10 is out of bounds [1, 5]") | ||
| test(2388.08, transpose(list(1:5), keep=0L), error="'keep' index 0 is out of bounds") | ||
| test(2388.09, tstrsplit(c("1-a", "2-b"), "-", keep=1L, type.convert=TRUE), list(c(1L, 2L))) | ||
| test(2388.10, transpose(list(1:5), keep="a"), error="'keep' must be an integer vector.") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,7 @@ | |
|
|
||
| \usage{ | ||
| transpose(l, fill=NA, ignore.empty=FALSE, keep.names=NULL, | ||
| make.names=NULL, list.cols=FALSE) | ||
| make.names=NULL, list.cols=FALSE, keep=NULL) | ||
| } | ||
| \arguments{ | ||
| \item{l}{ A list, data.frame or data.table. } | ||
|
|
@@ -16,6 +16,7 @@ transpose(l, fill=NA, ignore.empty=FALSE, keep.names=NULL, | |
| \item{keep.names}{The name of the first column in the result containing the names of the input; e.g. \code{keep.names="rn"}. By default \code{NULL} and the names of the input are discarded.} | ||
| \item{make.names}{The name or number of a column in the input to use as names of the output; e.g. \code{make.names="rn"}. By default \code{NULL} and default names are given to the output columns.} | ||
| \item{list.cols}{Default is \code{FALSE}. \code{TRUE} will avoid promoting types and return columns of type \code{list} instead. \code{factor} will always be cast to \code{character}.} | ||
| \item{keep}{An integer vector of column indices to keep and return. The columns will be returned in the order specified. If \code{NULL} (default), all columns are returned. This is much more memory efficient than transposing the entire list and then subsetting the result.} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
not sure if its necessary to justify this use case here |
||
| } | ||
| \details{ | ||
| The list elements (or columns of \code{data.frame}/\code{data.table}) should be all \code{atomic}. If list elements are of unequal lengths, the value provided in \code{fill} will be used so that the resulting list always has all elements of identical lengths. The class of input object is also preserved in the transposed result. | ||
|
|
@@ -48,8 +49,9 @@ l = list(1:3, c("a", "b", "c")) | |
| lapply(seq(length(l[[1]])), function(x) lapply(l, `[[`, x)) | ||
| transpose(l, list.cols=TRUE) | ||
|
|
||
| ll = list(nm=c('x', 'y'), 1:2, 3:4) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we remove these examples? |
||
| transpose(ll, make.names="nm") | ||
| ll = list(1:5, 6:10) | ||
| transpose(ll, keep=1:2) | ||
| transpose(ll, keep=c(3, 1)) | ||
| } | ||
| \seealso{ | ||
| \code{\link{data.table}}, \code{\link{tstrsplit}} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i didnt look but could there be any regressions from folks using
keepinstead ofkeep.namesexplicitly?