From c03398a95b274c9a52748e6ac0dc19064fed2db5 Mon Sep 17 00:00:00 2001 From: mattdowle Date: Fri, 9 Aug 2019 17:50:25 -0700 Subject: [PATCH 1/3] transpose.R coverage --- R/transpose.R | 5 +++-- inst/tests/tests.Rraw | 20 +++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/R/transpose.R b/R/transpose.R index 2d275e0a84..e4d15bba6a 100644 --- a/R/transpose.R +++ b/R/transpose.R @@ -2,9 +2,10 @@ transpose = function(l, fill=NA, ignore.empty=FALSE, keep.names=NULL, make.names if (!is.null(make.names)) { stopifnot(length(make.names)==1L) if (is.character(make.names)) { - make.names=chmatch(make.names, names(l)) - if (is.na(make.names)) + m = chmatch(make.names, names(l)) + if (is.na(m)) stop("make.names='",make.names,"' not found in names of input") + make.names = m } else { make.names = as.integer(make.names) if (is.na(make.names) || make.names<1L || make.names>length(l)) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 2a7d5d65e7..2076a79093 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -7778,6 +7778,7 @@ test(1571.3, names(tstrsplit(X$a, "", fixed=TRUE, names=letters[1:4])), letters[ test(1571.4, tstrsplit(X$a, "", fixed=TRUE, keep=c(2,4)), list(c("B", "E"), c(NA, "G"))) test(1571.5, tstrsplit(X$a, "", fixed=TRUE, keep=c(2,7)), error="should contain integer") test(1571.6, tstrsplit(X$a, "", fixed=TRUE, keep=c(2,4), names=letters[1:5]), error="is not equal to") +test(1571.7, tstrsplit(X$a, "", fixed=TRUE, names=1), error="'names' must be TRUE/FALSE or a character vector") # fix for #1367, quote="" argument in use. Using embedded quotes in the example below reads the # first two columns as one. I couldn't find a way to avoid introducing quote argument. @@ -15510,17 +15511,18 @@ test(2072.067, fifelse(c(TRUE, NA, TRUE, FALSE, FALSE, FALSE), factor(NA), facto factor(c(NA,NA,NA,NA,NA,NA))) DT = data.table(x=1:5, y=6:10) -test(2073.1, transpose(DT, keep.names="rn"), +test(2073.01, transpose(DT, keep.names="rn"), ans<-data.table(rn=c('x','y'), V1=c(1L, 6L), V2=c(2L, 7L), V3=c(3L, 8L), V4=c(4L, 9L), V5=c(5L, 10L))) -test(2073.2, transpose(DT, keep.names=TRUE), error="either NULL.*name of the first column of the result") -test(2073.3, transpose(ans, make.names="rn"), DT) -test(2073.4, transpose(ans, keep.names="rn", make.names="rn"), data.table(rn=paste0("V",1:5), x=1:5, y=6:10)) +test(2073.02, transpose(DT, keep.names=TRUE), error="either NULL.*name of the first column of the result") +test(2073.03, transpose(ans, make.names="rn"), DT) +test(2073.04, transpose(ans, make.names="notthere"), error="make.names='notthere' not found in names of input") +test(2073.05, transpose(ans, keep.names="rn", make.names="rn"), data.table(rn=paste0("V",1:5), x=1:5, y=6:10)) L = list(a=1:3, rn=LETTERS[1:3], b=4:6) -test(2073.5, transpose(L, make.names=0), error="make.names=0 is out of range [1,ncol=3]") -test(2073.6, transpose(L, make.names=4), error="make.names=4 is out of range [1,ncol=3]") -test(2073.7, transpose(L, make.names=NA), error="make.names=NA is out of range [1,ncol=3]") -test(2073.8, transpose(L, make.names=2), list(A=INT(1,4), B=INT(2,5), C=INT(3,6))) -test(2073.9, transpose(L, make.names=2, keep.names='foo'), list(foo=c("a","b"), A=INT(1,4), B=INT(2,5), C=INT(3,6))) +test(2073.06, transpose(L, make.names=0), error="make.names=0 is out of range [1,ncol=3]") +test(2073.07, transpose(L, make.names=4), error="make.names=4 is out of range [1,ncol=3]") +test(2073.08, transpose(L, make.names=NA), error="make.names=NA is out of range [1,ncol=3]") +test(2073.09, transpose(L, make.names=2), list(A=INT(1,4), B=INT(2,5), C=INT(3,6))) +test(2073.10, transpose(L, make.names=2, keep.names='foo'), list(foo=c("a","b"), A=INT(1,4), B=INT(2,5), C=INT(3,6))) ################################### From 6364d9ed6b80a07e234c8baf0df4f3dbcfdd6cf4 Mon Sep 17 00:00:00 2001 From: mattdowle Date: Fri, 9 Aug 2019 19:09:36 -0700 Subject: [PATCH 2/3] first() coverage in last.R --- NEWS.md | 2 ++ R/last.R | 16 ++++++++-------- R/test.data.table.R | 2 +- inst/tests/tests.Rraw | 1 + man/first.Rd | 36 ++++++++++++++++++++---------------- man/last.Rd | 36 ------------------------------------ 6 files changed, 32 insertions(+), 61 deletions(-) delete mode 100644 man/last.Rd diff --git a/NEWS.md b/NEWS.md index f6a44b54d6..27faee2325 100644 --- a/NEWS.md +++ b/NEWS.md @@ -258,6 +258,8 @@ 14. The warning message when using `keyby=` together with `:=` is clearer, [#2763](https://github.com/Rdatatable/data.table/issues/2763). Thanks to @eliocamp. +15. `first` and `last` gain an explicit `n=1L` argument so that it's clear the default is 1, and their almost identical manual pages have been merged into one. + ### Changes in [v1.12.2](https://github.com/Rdatatable/data.table/milestone/14?closed=1) (07 Apr 2019) diff --git a/R/last.R b/R/last.R index a4b5152ea8..608877e1e9 100644 --- a/R/last.R +++ b/R/last.R @@ -3,35 +3,35 @@ # This last is implemented this way for compatibility with xts::last which is S3 generic taking 'n' and 'keep' arguments # We'd like last() on vectors to be fast, so that's a direct x[NROW(x)] as it was in data.table, otherwise use xts's. # If xts is loaded higher than data.table, xts::last will work but slower. -last = function(x, ...) { +last = function(x, n=1L, ...) { if (nargs()==1L) { if (is.vector(x)) { if (!length(x)) return(x) else return(x[[length(x)]]) # for vectors, [[ works like [ } else if (is.data.frame(x)) return(x[NROW(x),]) } if(!requireNamespace("xts", quietly = TRUE)) { - tail(x, n = 1L, ...) # nocov + tail(x, n=n, ...) # nocov } else { # fix with suggestion from Joshua, #1347 if (!"package:xts" %chin% search()) { - tail(x, n = 1L, ...) # nocov - } else xts::last(x, ...) # UseMethod("last") doesn't find xts's methods, not sure what I did wrong. + tail(x, n=n, ...) # nocov + } else xts::last(x, n=n, ...) # UseMethod("last") doesn't find xts's methods, not sure what I did wrong. } } # first(), similar to last(), not sure why this wasn't exported in the first place... -first = function(x, ...) { +first = function(x, n=1L, ...) { if (nargs()==1L) { if (is.vector(x)) { if (!length(x)) return(x) else return(x[[1L]]) } else if (is.data.frame(x)) return(x[1L,]) } if(!requireNamespace("xts", quietly = TRUE)) { - head(x, n = 1L, ...) # nocov + head(x, n=n, ...) # nocov } else { # fix with suggestion from Joshua, #1347 if (!"package:xts" %chin% search()) { - head(x, n = 1L, ...) # nocov - } else xts::first(x, ...) # nocov + head(x, n=n, ...) # nocov + } else xts::first(x, n=n, ...) # nocov } } diff --git a/R/test.data.table.R b/R/test.data.table.R index c82dbe7449..07e59ba5bd 100644 --- a/R/test.data.table.R +++ b/R/test.data.table.R @@ -58,7 +58,7 @@ test.data.table = function(verbose=FALSE, pkg="pkg", silent=FALSE, with.other.pa # Sys.setlocale("LC_CTYPE", "") # just for CRAN's Mac to get it off C locale (post to r-devel on 16 Jul 2012) cat("getDTthreads(verbose=TRUE):\n") # for tracing on CRAN; output to log before anything is attempted - print(getDTthreads(verbose=TRUE)) # print output of getDTthreads() verbatim as simply as possible; e.g. without depending on data.table for formatting + print(invisible(getDTthreads(verbose=TRUE))) # print output of getDTthreads() verbatim as simply as possible; e.g. without depending on data.table for formatting cat("test.data.table() running:", fn, "\n") # print fn to log before attempting anything on it (in case it is missing); on same line for slightly easier grep env = new.env(parent=.GlobalEnv) assign("testDir", function(x) file.path(fulldir, x), envir=env) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 2076a79093..c934e36a21 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -9896,6 +9896,7 @@ test(1686.2, DT[, .(V1=A,B)], DT[, c(.(get("A")), .SD), .SDcols="B"]) test(1687.1, first(1:5), 1L) test(1687.2, first(data.table(x=1:5, y=6:10)), data.table(x=1L, y=6L)) test(1687.3, first(integer(0L)), integer(0L)) +test(1687.4, first(1:5, 2), 1:2) if (test_bit64) { # fix for #1385 and part of #1459 diff --git a/man/first.Rd b/man/first.Rd index 4355937c09..55e67b3969 100644 --- a/man/first.Rd +++ b/man/first.Rd @@ -1,34 +1,38 @@ \name{first} \alias{first} -\title{ First item of an object } +\alias{last} +\title{ First/last item of an object } \description{ -Returns the first item of a vector or list, or the first row of a data.frame -or data.table. +Returns the first/last item of a vector or list, or the first/last row of a data.frame +or data.table. The main difference to head/tail is that the default for \code{n} is 1 +rather than 6. } \usage{ -first(x, \dots) +first(x, n=1L, \dots) +last(x, n=1L, \dots) } \arguments{ \item{x}{ A vector, list, data.frame or data.table. Otherwise the S3 method of \code{xts::first} is deployed. } -\item{\dots}{ Not applicable for \code{data.table::first}. Any arguments here -are passed through to \code{xts::first}. } +\item{n}{ A numeric vector length 1. How many items to select. } +\item{\dots}{ Not applicable for \code{data.table} first/last. Any arguments here +are passed through to \code{xts}'s first/last. } } \value{ -If no other arguments are supplied it depends on the type of x. The first item -of a vector or list. The first row of a \code{data.frame} or \code{data.table}. -Otherwise, whatever \code{xts::first} returns (if package xts has been loaded, -otherwise a helpful error). - -If any argument is supplied in addition to \code{x} (such as \code{n} or -\code{keep} in \code{xts::first}), regardless of \code{x}'s type, then -\code{xts::first} is called if xts has been loaded, otherwise a helpful error. +If no other arguments are supplied it depends on the type of \code{x}. The first/last item +of a vector or list. The first/last row of a \code{data.frame} or \code{data.table}. +For other types, or if any argument is supplied in addition to \code{x} (such as \code{n}, or +\code{keep} in \code{xts}) regardless of \code{x}'s type, then \code{xts::first}/ +\code{xts::last} is called if \code{xts} has been loaded, otherwise \code{utils::head}/\code{utils::tail}. } -\seealso{ \code{\link{NROW}}, \code{\link{head}}, \code{\link{tail}}, -\code{\link{last}} } +\seealso{ \code{\link{NROW}}, \code{\link{head}}, \code{\link{tail}} } \examples{ first(1:5) # [1] 1 x = data.table(x=1:5, y=6:10) first(x) # same as x[1] + +last(1:5) # [1] 5 +x = data.table(x=1:5, y=6:10) +last(x) # same as x[5] } \keyword{ data } diff --git a/man/last.Rd b/man/last.Rd deleted file mode 100644 index 04f70d0724..0000000000 --- a/man/last.Rd +++ /dev/null @@ -1,36 +0,0 @@ -\name{last} -\alias{last} -\title{ Last item of an object } -\description{ -Returns the last item of a vector or list, or the last row of a data.frame or -data.table. -} -\usage{ -last(x, \dots) -} -\arguments{ -\item{x}{ A vector, list, data.frame or data.table. Otherwise the S3 method of -\code{xts::last} is deployed. } -\item{\dots}{ Not applicable for \code{data.table::last}. Any arguments here are -passed through to \code{xts::last}. } -} -% \details{ -% } -\value{ -If no other arguments are supplied it depends on the type of x. The last item -of a vector or list. The last row of a \code{data.frame} or \code{data.table}. -Otherwise, whatever \code{xts::last} returns (if package xts has been loaded, -otherwise a helpful error). - -If any argument is supplied in addition to \code{x} (such as \code{n} or -\code{keep} in \code{xts::last}), regardless of \code{x}'s type, then -\code{xts::last} is called if xts has been loaded, otherwise a helpful error. -} -\seealso{ \code{\link{NROW}}, \code{\link{head}}, \code{\link{tail}}, -\code{\link{first}} } -\examples{ -last(1:5) # [1] 5 -x = data.table(x=1:5, y=6:10) -last(x) # same as x[5] -} -\keyword{ data } From 05f7236520b622463c613418a832dde6db09c79d Mon Sep 17 00:00:00 2001 From: mattdowle Date: Fri, 9 Aug 2019 19:14:36 -0700 Subject: [PATCH 3/3] picked last.Rd as the one page (with first alias) for consistency with the last.R file --- man/{first.Rd => last.Rd} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename man/{first.Rd => last.Rd} (99%) diff --git a/man/first.Rd b/man/last.Rd similarity index 99% rename from man/first.Rd rename to man/last.Rd index 55e67b3969..d9c84c7897 100644 --- a/man/first.Rd +++ b/man/last.Rd @@ -1,4 +1,4 @@ -\name{first} +\name{last} \alias{first} \alias{last} \title{ First/last item of an object }