From 9ae79995b0921c47ef591dbc6abb474025885e26 Mon Sep 17 00:00:00 2001 From: seokhoonj Date: Mon, 19 Feb 2024 22:59:40 +0900 Subject: [PATCH] Massive commits --- .gitignore | 4 + DESCRIPTION | 6 +- NAMESPACE | 22 +++++ R/date.R | 8 +- R/devars.R | 25 ------ R/file.R | 27 ++++++ R/group.R | 84 ++++++++++++------- R/jaid-package.R | 5 +- R/utils.R | 115 +++++++++++++++++++++++++- R/zzz.R | 16 ++-- man/add_mon.Rd | 26 ++++++ man/bmonth.Rd | 30 +++++++ man/combine_overlapping_date_range.Rd | 47 +++++++++++ man/devars.Rd | 2 +- man/loadRDS.Rd | 31 +++++++ man/paste_list.Rd | 25 ++++++ man/set_dt.Rd | 22 +++++ man/set_tibble.Rd | 22 +++++ src/as.c | 2 +- src/group.c | 27 ++++-- src/init.c | 2 +- src/jaid.h | 4 +- src/utils.c | 35 ++++++++ 23 files changed, 504 insertions(+), 83 deletions(-) delete mode 100644 R/devars.R create mode 100644 R/file.R create mode 100644 man/add_mon.Rd create mode 100644 man/bmonth.Rd create mode 100644 man/combine_overlapping_date_range.Rd create mode 100644 man/loadRDS.Rd create mode 100644 man/paste_list.Rd create mode 100644 man/set_dt.Rd create mode 100644 man/set_tibble.Rd diff --git a/.gitignore b/.gitignore index 5b6a065..29b0536 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ .Rhistory .RData .Ruserdata +*.xls +*.xlsb +*.xlsm +*.xlsx diff --git a/DESCRIPTION b/DESCRIPTION index 23cdd85..3c913ef 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -4,14 +4,16 @@ Version: 0.0.0.9000 Authors@R: person(given = "seokhoon", family = "Joo", role = c("aut", "cre"), email = "seokhoonj@gmail.com") -Description: Joo's functional aid toolkit for efficient programming. +Description: Joo's functional aid toolkit for efficient and productive programming. License: MIT + file LICENSE Encoding: UTF-8 Depends: R (>= 3.5.0) Imports: Rcpp (>= 0.12.10), + data.table (>= 1.13.0), openssl (>= 1.4.1), - openxlsx (>= 4.2.3) + openxlsx (>= 4.2.3), + tibble (>= 3.2.1) Roxygen: list(markdown = TRUE) RoxygenNote: 7.2.3 LinkingTo: diff --git a/NAMESPACE b/NAMESPACE index 660cb05..43355db 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,16 +9,21 @@ S3method(sizeof,environment) S3method(type,data.frame) S3method(unlock,default) S3method(unlock,list) +export(add_mon) export(assert_class) export(assert_type) +export(bmonth) export(col_max) export(col_min) export(col_sum) +export(combine_overlapping_date_range) export(devars) export(dolock) export(draw_xlsx) +export(emonth) export(fill_one_before_first_one) export(fill_zero_not_first_pos) +export(loadRDS) export(max_by_colnames) export(max_by_dimnames) export(max_by_rownames) @@ -28,6 +33,7 @@ export(min_by_dimnames) export(min_by_rownames) export(mkdir) export(mostfreq) +export(paste_list) export(reverse) export(rotate) export(row_max) @@ -35,8 +41,10 @@ export(row_min) export(row_sum) export(set_colnames) export(set_dimnames) +export(set_dt) export(set_one_before_first_one) export(set_rownames) +export(set_tibble) export(set_zero_not_first_pos) export(sizeof) export(sum_by_colnames) @@ -48,6 +56,19 @@ export(unilen) export(unlock) export(write_xlsx) importFrom(Rcpp,sourceCpp) +importFrom(data.table,`%chin%`) +importFrom(data.table,`.SD`) +importFrom(data.table,`:=`) +importFrom(data.table,address) +importFrom(data.table,alloc.col) +importFrom(data.table,copy) +importFrom(data.table,set) +importFrom(data.table,setDF) +importFrom(data.table,setDT) +importFrom(data.table,setattr) +importFrom(data.table,setnames) +importFrom(data.table,setorder) +importFrom(data.table,setorderv) importFrom(openssl,aes_cbc_decrypt) importFrom(openssl,aes_cbc_encrypt) importFrom(openssl,sha256) @@ -59,6 +80,7 @@ importFrom(openxlsx,insertPlot) importFrom(openxlsx,saveWorkbook) importFrom(openxlsx,setColWidths) importFrom(openxlsx,writeData) +importFrom(tibble,as_tibble) importFrom(utils,head) importFrom(utils,object.size) importFrom(utils,tail) diff --git a/R/date.R b/R/date.R index d7bd961..f4b70fb 100644 --- a/R/date.R +++ b/R/date.R @@ -38,12 +38,12 @@ add_mon <- function (date, mon) { #' emonth(Sys.Date())} #' #' @export -bmonth <- function(x) { - as.Date(format(as.Date(x), format = "%Y-%m-01")) +bmonth <- function(date) { + as.Date(format(as.Date(date), format = "%Y-%m-01")) } #' @rdname bmonth #' @export -emonth <- function(x) { - add_mon(x, 1L) - 1L +emonth <- function(date) { + add_mon(date, 1L) - 1L } diff --git a/R/devars.R b/R/devars.R deleted file mode 100644 index c5b64ee..0000000 --- a/R/devars.R +++ /dev/null @@ -1,25 +0,0 @@ -#' @title devars -#' -#' @description -#' This function operates like `deparse(substitute(x))` inside the functions. -#' -#' @param x A string, vector or list expression that can be a string vector -#' @return A string vector -#' -#' @examples -#' # deparse(substitute(x)) -#' \donttest{devars(expression) -#' devars(c(expression, string)) -#' devars(list(expression, string)) -#' devars(.(expression, string))} -#' -#' @export -devars <- function(x) { - if (identical(parent.frame(), globalenv())) - n <- sys.nframe() - else n <- 1L - x <- eval(substitute(substitute(x)), envir = parent.frame(n = max(n, 1L))) - if (length(x) == 1L) - return(deparse(x)) - return(vapply(x, deparse, "character")[-1L]) -} diff --git a/R/file.R b/R/file.R new file mode 100644 index 0000000..2c6d2a7 --- /dev/null +++ b/R/file.R @@ -0,0 +1,27 @@ +#' loadRDS +#' +#' loadRDS is almost same as readRDS except for a pointer. +#' +#' @param file a \link{connection} or the name of the file where the R object is saved +#' to or read from. +#' @param refhook a hook function for handling reference objects. +#' +#' @return an \R object +#' +#' @examples +#' # compare pointer values +#' \dontrun{data <- copy(women) +#' data.table::setDT(data) +#' saveRDS(data, "data.rds") +#' df <- readRDS("data.rds") +#' dt <- loadRDS("data.rds") +#' attributes(df)$.internal.selfref # +#' attributes(dt)$.internal.selfref} +#' +#' @export +loadRDS <- function(file, refhook = NULL) { + df <- readRDS(file, refhook) + if (inherits(df, "data.table")) + return(alloc.col(df)) + return(df) +} diff --git a/R/group.R b/R/group.R index 7922ec0..3e03464 100644 --- a/R/group.R +++ b/R/group.R @@ -1,29 +1,55 @@ - -# Calculate unique days in multiple overlapping date ranges -# merge_date_range_overlap <- function(df, id_var, merge_var, from_var, to_var, interval = 0) { -# id_var <- match_cols(df, vapply(substitute(id_var) , deparse, "character")) -# merge_var <- match_cols(df, vapply(substitute(merge_var), deparse, "character")) -# from_var <- match_cols(df, deparse(substitute(from_var))) -# to_var <- match_cols(df, deparse(substitute(to_var))) -# vars <- c(id_var, merge_var, from_var, to_var) -# tmp <- df[, ..vars] -# setnames(tmp, c(id_var, merge_var, "from", "to")) -# setorderv(tmp, c(id_var, "from", "to")) -# set(tmp, j = "sub_stay", value = 0) -# ind <- .Call(IndexDateRangeOverlap, tmp[, ..id_var], -# as_integer(tmp$from), -# as_integer(tmp$to), -# as_integer(interval)) -# set(tmp, j = "loc", value = ind$loc) -# set(tmp, j = "sub", value = ind$sub) -# group <- c(id_var, "loc") -# m <- tmp[, lapply(.SD, glue_code), keyby = group, .SDcols = merge_var] -# s <- tmp[, .(from = min(from), to = max(to), sub_stay = sum(sub_stay) + sum(sub)), -# keyby = group] -# z <- m[s, on = group] -# set(z, j = "loc", value = NULL) -# set(z, j = "stay", value = as.numeric(z$to - z$from + 1 - z$sub_stay)) -# set(z, j = "sub_stay", value = NULL) -# setnames(z, c(vars, "stay")) -# return(z) -# } +#' Combine overlapping date ranges +#' +#' Combine multiple overlapping date ranges. +#' +#' @param df a data.frame with data ranges +#' @param id_var id column names +#' @param merge_var column names to be collapsed +#' @param from_var a column name of start date +#' @param to_var a column name of end date +#' @param interval an interval of previous end date to next start date to be combined +#' @param collapse an optional character string to seperate the result of `merge_var` +#' @return `data.frame` with no overlapping date ranges. +#' +#' @examples +#' # combine overlapping date ranges +#' id <- c("A", "A", "B") +#' work <- c("cleansing", "analysis", "cleansing") +#' sdate <- as.Date(c("2022-03-01", "2022-03-05", "2022-03-08")) +#' edate <- as.Date(c("2022-03-06", "2022-03-09", "2022-03-10")) +#' df <- data.frame(id = id, work = work, sdate = sdate, edate = edate) +#' combine_overlapping_date_range(df, id, work, sdate, edate, interval = 0) +#' +#' @export +combine_overlapping_date_range <- function(df, id_var, merge_var, from_var, to_var, + interval = 0, collapse = "|") { + old_class <- class(df) + set_dt(df) + id_var <- match_cols(df, vapply(substitute(id_var), deparse, "character")) + merge_var <- match_cols(df, vapply(substitute(merge_var), deparse, "character")) + from_var <- deparse(substitute(from_var)) + to_var <- deparse(substitute(to_var)) + all_var <- c(id_var, merge_var, from_var, to_var) + dt <- df[, .SD, .SDcols = all_var] + setnames(dt, c(id_var, merge_var, "from", "to")) + setorderv(dt, c(id_var, "from", "to")) + set(dt, j = "sub_stay", value = 0) + index <- .Call(IndexOverlappingDateRange, dt[, .SD, .SDcols = id_var], + dt$from, dt$to, interval = interval) + set(dt, j = "loc", value = index$loc) # group index to combine + set(dt, j = "sub", value = index$sub) # days to subtract, if the interval is longer than 0 + group_var <- c(id_var, "loc") + m <- dt[, lapply(.SD, function(x) paste0(unique(x[!is.na(x)]), collapse = collapse)), + keyby = group_var, .SDcols = merge_var] + from <- to <- sub_stay <- sub <- NULL + s <- dt[, list(from = min(from), to = max(to), sub_stay = sum(sub_stay) + sum(sub)), + keyby = group_var] + z <- m[s, on = group_var] + set(z, j = "loc", value = NULL) + set(z, j = "stay", value = as.numeric(z$to - z$from + 1 - z$sub_stay)) + set(z, j = "sub_stay", value = NULL) + setnames(z, c(all_var, "stay")) + setattr(z, "class", old_class) + setattr(df, "class", old_class) + return(z) +} diff --git a/R/jaid-package.R b/R/jaid-package.R index 25fce5a..1dc2fc9 100644 --- a/R/jaid-package.R +++ b/R/jaid-package.R @@ -3,8 +3,11 @@ #' @keywords internal #' @useDynLib jaid, .registration = TRUE #' @importFrom Rcpp sourceCpp +#' @importFrom data.table `:=` `.SD` `%chin%` address alloc.col copy set +#' setattr setDF setDT setnames setorder setorderv #' @importFrom openssl aes_cbc_decrypt aes_cbc_encrypt sha256 #' @importFrom openxlsx addStyle addWorksheet createStyle createWorkbook -#' insertPlot saveWorkbook setColWidths writeData +#' insertPlot saveWorkbook setColWidths writeData +#' @importFrom tibble as_tibble #' @importFrom utils head object.size tail "_PACKAGE" diff --git a/R/utils.R b/R/utils.R index fb5db52..96cb493 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,8 +1,119 @@ +#' @title devars +#' +#' @description +#' This function operates like `deparse(substitute(x))` inside the functions. +#' +#' @param x A string, vector or list expression that can be a string vector +#' @return A string vector +#' +#' @examples +#' # deparse(substitute(x)) +#' \donttest{devars(expression) +#' devars(c(expression, string)) +#' devars(list(expression, string)) +#' devars(.(expression, string))} +#' +#' @export +devars <- function(x) { + if (identical(parent.frame(), globalenv())) + n <- sys.nframe() + else n <- 1L + x <- eval(substitute(substitute(x)), envir = parent.frame(n = max(n, 1L))) + if (length(x) == 1L) + return(deparse(x)) + return(vapply(x, deparse, "character")[-1L]) +} + +match_cols <- function(df, cols) names(df)[match(cols, names(df), 0L)] + +has_rows <- function(df) { + df_name <- deparse(substitute(df)) + if (!nrow(df)) { + stop("'", df_name, "' doesn't have row(s): ", + call. = FALSE) + } +} + +has_cols <- function(df, cols) { + df_name <- deparse(substitute(df)) + df_cols <- colnames(df) + diff_cols <- setdiff(cols, df_cols) + if (length(diff_cols) > 0) { + stop("'", df_name, "' doesn't have column(s): ", + paste0(diff_cols, collapse = ", "), ".", + call. = FALSE) + } +} + +has_missing <- function(x) { + column_name <- deparse(substitute(x)) + if (any(is.na(x))) { + stop("'", column_name, "' has missing value(s): ", + call. = FALSE) + } +} sort_group_by <- function(x) { .Call(SortGroupBy, x) } -match_cols <- function(df, cols) { - colnames(df)[match(cols, colnames(df), 0L)] +#' Paste vectors of a list +#' +#' Paste vectors of equal length in a list or data.frame +#' +#' @param x a list with same length vectors or data frame column vectors you want to paste. +#' @param sep a character string to separate the terms. +#' @return a vector pasted +#' +#' @examples +#' # paste length and width of iris +#' iris$size <- paste_list(iris[, c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")]) +#' head(iris) +#' +#' @export +paste_list <- function(x, sep = "|") { + n <- length(x) + if (n == 1L) { + return(x[[1L]]) + } else { + return(do.call(function(...) paste(..., sep = sep), x)) + } +} + +#' Set data frame to tibble +#' +#' Set data frame to tibble class. +#' +#' @param x data.frame +#' @return No return value. +#' +#' @examples +#' # set data.frame to tibble +#' \donttest{set_tibble(iris)} +#' +#' @export +set_tibble <- function(x) { + assert_class(x, "data.frame") + if (!inherits(x, "tbl_df")) + data.table::setattr(x, "class", c("tbl_df", "tbl", "data.frame")) + invisible(x) +} + +#' Set data.frame to data.table +#' +#' Set data.frame to data.table class. +#' +#' @param x data.frame +#' @return No return value. +#' +#' @examples +#' # set data.frame to data.table +#' \donttest{set_dt(iris)} +#' +#' @export +set_dt <- function(x) { + assert_class(x, "data.frame") + if (!inherits(x, "data.table")) + data.table::setattr(x, "class", c("data.table", "data.frame")) + invisible(x) } diff --git a/R/zzz.R b/R/zzz.R index 6b34540..0bff4db 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,17 +1,13 @@ -.onAttach <- function(libname, pkgname) { - packageStartupMessage("Written by Seokhoon Joo. (Note, kcd terms arguments are monthly-basis)") -} - .onLoad <- function(libname, pkgname) { op <- options() - op.vuw <- list( - vuw.eps = 1e-8, - vuw.scipen = 14, - vuw.guess_max = 21474836 + op.jaid <- list( + jaid.eps = 1e-8, + jaid.scipen = 14, + jaid.guess_max = 21474836 ) - toset <- !(names(op.vuw) %in% names(op)) - if (any(toset)) options(op.vuw[toset]) + toset <- !(names(op.jaid) %in% names(op)) + if (any(toset)) options(op.jaid[toset]) invisible() } diff --git a/man/add_mon.Rd b/man/add_mon.Rd new file mode 100644 index 0000000..7e8e32d --- /dev/null +++ b/man/add_mon.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/date.R +\name{add_mon} +\alias{add_mon} +\title{Add months} +\usage{ +add_mon(date, mon) +} +\arguments{ +\item{date}{A date} + +\item{mon}{A number of months to be added} +} +\value{ +A date +} +\description{ +Add months to the date. +} +\examples{ +# add months +\donttest{ +date <- Sys.Date() +add_mon(date, 3)} + +} diff --git a/man/bmonth.Rd b/man/bmonth.Rd new file mode 100644 index 0000000..5781dd9 --- /dev/null +++ b/man/bmonth.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/date.R +\name{bmonth} +\alias{bmonth} +\alias{emonth} +\title{Beginning of the month, End of the month} +\usage{ +bmonth(date) + +emonth(date) +} +\arguments{ +\item{date}{A date} +} +\value{ +A date +} +\description{ +Get the beginning of the month. +} +\examples{ +# the beginning of the month +\donttest{ +bmonth(Sys.Date())} + +# the end of the month +\donttest{ +emonth(Sys.Date())} + +} diff --git a/man/combine_overlapping_date_range.Rd b/man/combine_overlapping_date_range.Rd new file mode 100644 index 0000000..102118b --- /dev/null +++ b/man/combine_overlapping_date_range.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/group.R +\name{combine_overlapping_date_range} +\alias{combine_overlapping_date_range} +\title{Combine overlapping date ranges} +\usage{ +combine_overlapping_date_range( + df, + id_var, + merge_var, + from_var, + to_var, + interval = 0, + collapse = "|" +) +} +\arguments{ +\item{df}{a data.frame with data ranges} + +\item{id_var}{id column names} + +\item{merge_var}{column names to be collapsed} + +\item{from_var}{a column name of start date} + +\item{to_var}{a column name of end date} + +\item{interval}{an interval of previous end date to next start date to be combined} + +\item{collapse}{an optional character string to seperate the result of \code{merge_var}} +} +\value{ +\code{data.frame} with no overlapping date ranges. +} +\description{ +Combine multiple overlapping date ranges. +} +\examples{ +# combine overlapping date ranges +id <- c("A", "A", "B") +work <- c("cleansing", "analysis", "cleansing") +sdate <- as.Date(c("2022-03-01", "2022-03-05", "2022-03-08")) +edate <- as.Date(c("2022-03-06", "2022-03-09", "2022-03-10")) +df <- data.frame(id = id, work = work, sdate = sdate, edate = edate) +combine_overlapping_date_range(df, id, work, sdate, edate, interval = 0) + +} diff --git a/man/devars.Rd b/man/devars.Rd index e9524cf..de105c5 100644 --- a/man/devars.Rd +++ b/man/devars.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/devars.R +% Please edit documentation in R/utils.R \name{devars} \alias{devars} \title{devars} diff --git a/man/loadRDS.Rd b/man/loadRDS.Rd new file mode 100644 index 0000000..de602d9 --- /dev/null +++ b/man/loadRDS.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/file.R +\name{loadRDS} +\alias{loadRDS} +\title{loadRDS} +\usage{ +loadRDS(file, refhook = NULL) +} +\arguments{ +\item{file}{a \link{connection} or the name of the file where the R object is saved +to or read from.} + +\item{refhook}{a hook function for handling reference objects.} +} +\value{ +an \R object +} +\description{ +loadRDS is almost same as readRDS except for a pointer. +} +\examples{ +# compare pointer values +\dontrun{data <- copy(women) +data.table::setDT(data) +saveRDS(data, "data.rds") +df <- readRDS("data.rds") +dt <- loadRDS("data.rds") +attributes(df)$.internal.selfref # +attributes(dt)$.internal.selfref} + +} diff --git a/man/paste_list.Rd b/man/paste_list.Rd new file mode 100644 index 0000000..9695a70 --- /dev/null +++ b/man/paste_list.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{paste_list} +\alias{paste_list} +\title{Paste vectors of a list} +\usage{ +paste_list(x, sep = "|") +} +\arguments{ +\item{x}{a list with same length vectors or data frame column vectors you want to paste.} + +\item{sep}{a character string to separate the terms.} +} +\value{ +a vector pasted +} +\description{ +Paste vectors of equal length in a list or data.frame +} +\examples{ +# paste length and width of iris +iris$size <- paste_list(iris[, c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")]) +head(iris) + +} diff --git a/man/set_dt.Rd b/man/set_dt.Rd new file mode 100644 index 0000000..1a88e43 --- /dev/null +++ b/man/set_dt.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{set_dt} +\alias{set_dt} +\title{Set data.frame to data.table} +\usage{ +set_dt(x) +} +\arguments{ +\item{x}{data.frame} +} +\value{ +No return value. +} +\description{ +Set data.frame to data.table class. +} +\examples{ +# set data.frame to data.table +\donttest{set_dt(iris)} + +} diff --git a/man/set_tibble.Rd b/man/set_tibble.Rd new file mode 100644 index 0000000..bfbbbb9 --- /dev/null +++ b/man/set_tibble.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{set_tibble} +\alias{set_tibble} +\title{Set data frame to tibble} +\usage{ +set_tibble(x) +} +\arguments{ +\item{x}{data.frame} +} +\value{ +No return value. +} +\description{ +Set data frame to tibble class. +} +\examples{ +# set data.frame to tibble +\donttest{set_tibble(iris)} + +} diff --git a/src/as.c b/src/as.c index d9df451..343f41c 100644 --- a/src/as.c +++ b/src/as.c @@ -1,7 +1,7 @@ #include "jaid.h" /* same as `as.logical`, `as.integer`, `as.numeric`, `as.character` - * but don't break the shape. */ + * but these functions don't break the original shape. */ SEXP AsLogical(SEXP x) { return coerceVector(x, LGLSXP); } diff --git a/src/group.c b/src/group.c index 381b648..6fea577 100644 --- a/src/group.c +++ b/src/group.c @@ -96,14 +96,25 @@ SEXP SortGroupBy(SEXP id) { return pos; } -SEXP IndexDateRangeOverlap(SEXP id, SEXP from, SEXP to, SEXP interval) { +/* "loc" means numbers to be grouped. if the loc vector is like + * c(1, 1, 1, 2, 2, 2, 2), we got two groups first 3 rows and second 4 rows. + * "sub" means subtracting number of days when the interval argument is longer + * than 0. if the two date ranges are like "2014-02-03 ~ 2014-02-04" and + * "2014-02-12 ~ 2014-02-13" and the interval is 7, it is combined as 2014-02-03 ~ 2014-02-13 */ +SEXP IndexOverlappingDateRange(SEXP id, SEXP from, SEXP to, SEXP interval) { R_xlen_t m, n, i, j; SEXP loc, sub, v, z; - m = XLENGTH(VECTOR_ELT(id, 0)), n = XLENGTH(id); + if (isVectorList(id)) { + m = XLENGTH(VECTOR_ELT(id, 0)), n = XLENGTH(id); + } else { + m = XLENGTH(id), n = 1; + } - int *ifr = INTEGER(from); - int *ito = INTEGER(to); - int vinterval = asInteger(interval); + // type of date is double + double *ifr = REAL(from); + double *ito = REAL(to); + // interval is integer + double vinterval = asReal(interval); PROTECT(loc = allocVector(INTSXP, m)); PROTECT(sub = allocVector(INTSXP, m)); @@ -117,7 +128,11 @@ SEXP IndexDateRangeOverlap(SEXP id, SEXP from, SEXP to, SEXP interval) { for (i = 1; i < m; ++i) { j = 0, c1 = true; while (j < n) { - v = VECTOR_ELT(id, j); + if (isVectorList(id)) { + v = VECTOR_ELT(id, j); + } else { + v = id; + } switch(TYPEOF(v)){ case LGLSXP:{ int *iv = LOGICAL(v); diff --git a/src/init.c b/src/init.c index 9d79af0..727f05b 100644 --- a/src/init.c +++ b/src/init.c @@ -13,7 +13,7 @@ static const R_CallMethodDef callEntries[] = { CALLDEF(AsCharacter, 1), // Group - CALLDEF(IndexDateRangeOverlap, 4), + CALLDEF(IndexOverlappingDateRange, 4), CALLDEF(SortGroupBy, 1), // Utils diff --git a/src/jaid.h b/src/jaid.h index a2b4fbf..39f2444 100644 --- a/src/jaid.h +++ b/src/jaid.h @@ -68,9 +68,11 @@ void FillCInt(SEXP x, int value); void FillCDouble(SEXP x, double value); void FillCString(SEXP x, const char *value); void FillValue(SEXP x, SEXP value); +void PrintArray(int arr[], int len); +SEXP PrintVector(SEXP x); /* Group */ -SEXP IndexDateRangeOverlap(SEXP id, SEXP from, SEXP to, SEXP interval); +SEXP IndexOverlappingDateRange(SEXP id, SEXP from, SEXP to, SEXP interval); SEXP SortGroupBy(SEXP id); // Mode diff --git a/src/utils.c b/src/utils.c index 5e49092..011fe0f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -193,6 +193,41 @@ void FillCDoublePointer(SEXP x, void **value) { } } +void PrintArray(int arr[], int len) { + for (int i = 0; i < len; ++i) { + Rprintf("%d ", arr[i]); + } +} + +SEXP PrintVector(SEXP x) { + R_xlen_t i = 0, len = xlength(x); + switch(TYPEOF(x)) { + case LGLSXP:{ + int *ix = LOGICAL(x); + for (; i < len; ++i) Rprintf("%d ", ix[i]); + } break; + case INTSXP:{ + int *ix = INTEGER(x); + for (; i < len; ++i) Rprintf("%d ", ix[i]); + } break; + case REALSXP:{ + double *ix = REAL(x); + for (; i < len; ++i) Rprintf("%f ", ix[i]); + } break; + case CPLXSXP:{ + Rcomplex *ix = COMPLEX(x); + for (; i < len; ++i) Rprintf("%f+%f ", ix[i].r, ix[i].i); + } break; + case STRSXP:{ + SEXP *ix = STRING_PTR(x); + for (; i < len; ++i) Rprintf("%s ", CHAR(ix[i])); + } break; + default: + error(_("invalid input")); + } + return R_NilValue; +} + // SEXP ChangeToBiggerType(SEXP x, SEXP minval) { // if (TYPEOF(x) > TYPEOF(minval)) { // minval = coerceVector(minval, TYPEOF(x));