| 1 |
# DATE MODEL |
|
| 2 |
#' @include AllClasses.R AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @rdname event |
|
| 7 |
#' @aliases event,data.frame,numeric-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "event", |
|
| 10 |
signature = c(object = "data.frame", dates = "numeric"), |
|
| 11 |
definition = function(object, dates, rank = NULL, sup_row = NULL, |
|
| 12 |
calendar = CE(), ...) {
|
|
| 13 | 2x |
object <- data.matrix(object) |
| 14 | 2x |
methods::callGeneric(object, dates, rank = rank, sup_row = sup_row, |
| 15 | 2x |
calendar = calendar, ...) |
| 16 |
} |
|
| 17 |
) |
|
| 18 | ||
| 19 |
#' @export |
|
| 20 |
#' @rdname event |
|
| 21 |
#' @aliases event,matrix,numeric-method |
|
| 22 |
setMethod( |
|
| 23 |
f = "event", |
|
| 24 |
signature = c(object = "matrix", dates = "numeric"), |
|
| 25 |
definition = function(object, dates, calendar = CE(), |
|
| 26 |
rank = NULL, sup_row = NULL, total = 5, |
|
| 27 |
verbose = getOption("kairos.verbose"), ...) {
|
|
| 28 |
## Sample |
|
| 29 | 2x |
n <- nrow(object) |
| 30 | ||
| 31 |
## Check dates |
|
| 32 | 2x |
if (arkhe::has_names(dates)) {
|
| 33 | 1x |
i <- match(names(dates), rownames(object)) |
| 34 | 1x |
old_dates <- dates |
| 35 | 1x |
dates <- rep(NA_real_, n) |
| 36 | 1x |
dates[i] <- old_dates |
| 37 |
} |
|
| 38 | 2x |
arkhe::assert_length(dates, nrow(object)) |
| 39 | ||
| 40 |
## Supplementary rows |
|
| 41 | 2x |
sup <- logical(n) |
| 42 | 2x |
sup[sup_row] <- TRUE |
| 43 | ||
| 44 | 2x |
data_ref <- object[!sup, , drop = FALSE] |
| 45 | 2x |
data_sup <- object[sup, , drop = FALSE] |
| 46 | 2x |
dates_ref <- dates[!sup] |
| 47 | 2x |
dates_sup <- dates[sup] |
| 48 | ||
| 49 |
## Cleansing |
|
| 50 | 2x |
data_clean <- clean_total(data_ref, data_sup, dates_ref, dates_sup, |
| 51 | 2x |
total = total, verbose = verbose) |
| 52 | ||
| 53 | 2x |
data <- rbind(data_clean$data_ref, data_clean$data_sup) |
| 54 | 2x |
dates <- c(data_clean$dates_ref, data_clean$dates_sup) |
| 55 | 2x |
sup <- seq_along(data_clean$dates_sup) + length(data_clean$dates_ref) |
| 56 | ||
| 57 |
## Correspondance analysis |
|
| 58 | 2x |
if (is.null(rank)) {
|
| 59 | ! |
tmp <- dimensio::ca(data, rank = NULL, sup_row = sup, ...) |
| 60 | ! |
eig <- dimensio::get_eigenvalues(tmp) |
| 61 | ! |
rank <- which.max(eig$cumulative >= 60) |
| 62 |
} |
|
| 63 | 2x |
rank <- min(rank, dim(data) - 1) |
| 64 | 2x |
results_CA <- dimensio::ca(data, rank = rank, sup_row = sup, ...) |
| 65 | ||
| 66 |
## Get row coordinates |
|
| 67 | 2x |
row_coord <- dimensio::get_coordinates(results_CA, margin = 1) |
| 68 | ||
| 69 |
## Rata die |
|
| 70 | 2x |
if (is.null(calendar)) {
|
| 71 | ! |
rd <- aion::as_fixed(data_clean$dates_ref) |
| 72 |
} else {
|
|
| 73 | 2x |
rd <- aion::fixed(data_clean$dates_ref, calendar = calendar) |
| 74 |
} |
|
| 75 | ||
| 76 |
## Gaussian multiple linear regression model |
|
| 77 | 2x |
contexts <- data.frame( |
| 78 | 2x |
date = rd, |
| 79 | 2x |
row_coord[!row_coord$.sup, -ncol(row_coord), drop = FALSE] |
| 80 |
) |
|
| 81 | 2x |
fit <- stats::lm(date ~ ., data = contexts) |
| 82 | ||
| 83 |
## FIXME: temporary workaround until aion::fixed() can deal with NA |
|
| 84 | 2x |
dates_not_na <- which(!is.na(dates)) |
| 85 | 2x |
rt <- rep(NA_real_, length(dates)) |
| 86 | 2x |
if (is.null(calendar)) {
|
| 87 | ! |
rt[dates_not_na] <- aion::as_fixed(dates[dates_not_na]) |
| 88 |
} else {
|
|
| 89 | 2x |
rt[dates_not_na] <- aion::fixed(dates[dates_not_na], calendar = calendar) |
| 90 |
} |
|
| 91 | 2x |
rt <- aion::as_fixed(rt) |
| 92 | ||
| 93 | 2x |
.EventDate( |
| 94 | 2x |
results_CA, |
| 95 | 2x |
dates = rt, |
| 96 | 2x |
model = fit, |
| 97 | 2x |
keep = seq_len(rank) |
| 98 |
) |
|
| 99 |
} |
|
| 100 |
) |
|
| 101 | ||
| 102 |
clean_total <- function(data_ref, data_sup, dates_ref, dates_sup, |
|
| 103 |
total = 5, verbose = TRUE) {
|
|
| 104 | ||
| 105 | 2x |
clean <- TRUE |
| 106 | 2x |
n_rm_col <- n_rm_ref <- n_rm_sup <- 0 |
| 107 | ||
| 108 | 2x |
while (clean) {
|
| 109 | 2x |
rm_col <- colSums(data_ref) < total |
| 110 | 2x |
n_rm_col <- n_rm_col + sum(rm_col) |
| 111 | 2x |
if (any(rm_col)) {
|
| 112 | ! |
data_ref <- data_ref[, !rm_col, drop = FALSE] |
| 113 | ! |
data_sup <- data_sup[, !rm_col, drop = FALSE] |
| 114 |
} |
|
| 115 | ||
| 116 | 2x |
rm_row_ref <- rowSums(data_ref) < total |
| 117 | 2x |
n_rm_ref <- n_rm_ref + sum(rm_row_ref) |
| 118 | 2x |
if (any(rm_row_ref)) {
|
| 119 | ! |
data_ref <- data_ref[!rm_row_ref, , drop = FALSE] |
| 120 | ! |
dates_ref <- dates_ref[!rm_row_ref] |
| 121 |
} |
|
| 122 | ||
| 123 | 2x |
rm_row_sup <- rowSums(data_sup) < total |
| 124 | 2x |
n_rm_sup <- n_rm_sup + sum(rm_row_sup) |
| 125 | 2x |
if (any(data_sup)) {
|
| 126 | ! |
data_sup <- data_sup[!rm_row_sup, , drop = FALSE] |
| 127 | ! |
dates_sup <- dates_sup[!rm_row_sup] |
| 128 |
} |
|
| 129 | ||
| 130 | 2x |
if (!any(rm_col) & !any(rm_row_ref) & !any(rm_row_sup)) clean <- FALSE |
| 131 |
} |
|
| 132 | ||
| 133 | 2x |
if (isTRUE(verbose)) {
|
| 134 | ! |
if (n_rm_col > 0) {
|
| 135 | ! |
msg <- ngettext(n_rm_col, |
| 136 | ! |
"%d column has a grand total of less than %d.", |
| 137 | ! |
"%d columns have a grand total of less than %d.") |
| 138 | ! |
message(sprintf(msg, n_rm_col, total)) |
| 139 |
} |
|
| 140 | ! |
if (n_rm_ref > 0) {
|
| 141 | ! |
msg <- ngettext(n_rm_ref, |
| 142 | ! |
"%d row has a grand total of less than %d.", |
| 143 | ! |
"%d rows have a grand total of less than %d.") |
| 144 | ! |
message(sprintf(msg, n_rm_ref, total)) |
| 145 |
} |
|
| 146 | ! |
if (n_rm_sup > 0) {
|
| 147 | ! |
msg <- ngettext(n_rm_sup, |
| 148 | ! |
"%d supplementary row has a grand total of less than %d.", |
| 149 | ! |
"%d supplementary rows have a grand total of less than %d.") |
| 150 | ! |
message(sprintf(msg, n_rm_sup, total)) |
| 151 |
} |
|
| 152 | ! |
n_rm <- n_rm_col + n_rm_ref + n_rm_sup |
| 153 | ! |
if (n_rm > 0) {
|
| 154 | ! |
msg <- ngettext(n_rm, "It was omitted from the analysis.", |
| 155 | ! |
"They were omitted from the analysis.") |
| 156 | ! |
message(msg) |
| 157 |
} |
|
| 158 |
} |
|
| 159 | ||
| 160 | 2x |
if (all(is.na(dates_ref))) {
|
| 161 | ! |
stop(tr_("All dates are missing!"), call. = FALSE)
|
| 162 |
} |
|
| 163 | ||
| 164 | 2x |
list( |
| 165 | 2x |
data_ref = data_ref, |
| 166 | 2x |
data_sup = data_sup, |
| 167 | 2x |
dates_ref = dates_ref, |
| 168 | 2x |
dates_sup = dates_sup |
| 169 |
) |
|
| 170 |
} |
|
| 171 | ||
| 172 |
# Event ======================================================================== |
|
| 173 |
#' @export |
|
| 174 |
#' @rdname predict_event |
|
| 175 |
#' @aliases predict_event,EventDate,missing-method |
|
| 176 |
setMethod( |
|
| 177 |
f = "predict_event", |
|
| 178 |
signature = c(object = "EventDate", data = "missing"), |
|
| 179 |
definition = function(object, margin = 1, level = 0.95, |
|
| 180 |
calendar = get_calendar()) {
|
|
| 181 | 3x |
data <- dimensio::get_coordinates(object, margin = margin) |
| 182 | 3x |
data <- as.matrix(data[, -ncol(data), drop = FALSE]) |
| 183 | ||
| 184 | 3x |
.predict_event(object, data, level = level, calendar = calendar) |
| 185 |
} |
|
| 186 |
) |
|
| 187 | ||
| 188 |
#' @export |
|
| 189 |
#' @rdname predict_event |
|
| 190 |
#' @aliases predict_event,EventDate,matrix-method |
|
| 191 |
setMethod( |
|
| 192 |
f = "predict_event", |
|
| 193 |
signature = c(object = "EventDate", data = "matrix"), |
|
| 194 |
definition = function(object, data, margin = 1, level = 0.95, |
|
| 195 |
calendar = get_calendar()) {
|
|
| 196 |
## Correspondence analysis |
|
| 197 | ! |
data <- dimensio::predict(object, data, margin = margin) |
| 198 | ||
| 199 | ! |
.predict_event(object, data, level = level, calendar = calendar) |
| 200 |
} |
|
| 201 |
) |
|
| 202 | ||
| 203 |
.predict_event <- function(object, data, level = 0.95, |
|
| 204 |
calendar = get_calendar()) {
|
|
| 205 |
## Predict event date |
|
| 206 | 3x |
fit_model <- object@model |
| 207 | 3x |
ca_event <- compute_event(fit_model, data, level = level) |
| 208 | ||
| 209 |
# TODO: check predicted dates consistency |
|
| 210 | ||
| 211 |
## Convert |
|
| 212 | 3x |
ca_event <- as.data.frame(ca_event) |
| 213 | 3x |
if (is.null(calendar)) return(ca_event) |
| 214 | ||
| 215 | ! |
ca_event[] <- lapply( |
| 216 | ! |
X = ca_event, |
| 217 | ! |
FUN = aion::as_year, |
| 218 | ! |
calendar = calendar, |
| 219 | ! |
decimal = TRUE |
| 220 |
) |
|
| 221 | ! |
ca_event |
| 222 |
} |
|
| 223 | ||
| 224 |
#' @export |
|
| 225 |
#' @rdname density_event |
|
| 226 |
#' @aliases density_event,EventDate-method |
|
| 227 |
setMethod( |
|
| 228 |
f = "density_event", |
|
| 229 |
signature = c(object = "EventDate"), |
|
| 230 |
definition = function(object, dates = NULL, calendar = NULL, n = 500, ...) {
|
|
| 231 |
## Get data |
|
| 232 | ! |
rows <- predict_event(object, margin = 1, calendar = NULL) |
| 233 | ! |
row_dates <- rows$date |
| 234 | ! |
row_errors <- rows$error |
| 235 | ||
| 236 | ! |
if (is.null(dates)) {
|
| 237 | ! |
dates <- seq( |
| 238 | ! |
from = min(rows$lower, na.rm = TRUE) * 0.96, |
| 239 | ! |
to = max(rows$upper, na.rm = TRUE) * 1.04, |
| 240 | ! |
length.out = n |
| 241 |
) |
|
| 242 |
} |
|
| 243 | ! |
if (is.null(calendar)) {
|
| 244 | ! |
dates <- aion::as_fixed(dates) |
| 245 |
} else {
|
|
| 246 | ! |
dates <- aion::fixed(dates, calendar = calendar) |
| 247 |
} |
|
| 248 | ||
| 249 |
## Density estimation |
|
| 250 | ! |
date_event <- mapply( |
| 251 | ! |
FUN = stats::dnorm, |
| 252 | ! |
mean = row_dates, |
| 253 | ! |
sd = row_errors, |
| 254 | ! |
MoreArgs = list(x = dates), |
| 255 | ! |
SIMPLIFY = TRUE |
| 256 |
) |
|
| 257 | ||
| 258 | ! |
colnames(date_event) <- rownames(rows) |
| 259 | ! |
aion::series(object = date_event, time = dates) |
| 260 |
} |
|
| 261 |
) |
|
| 262 | ||
| 263 |
# Accumulation ================================================================= |
|
| 264 |
#' @export |
|
| 265 |
#' @rdname predict_event |
|
| 266 |
#' @aliases predict_accumulation,EventDate,missing-method |
|
| 267 |
setMethod( |
|
| 268 |
f = "predict_accumulation", |
|
| 269 |
signature = c(object = "EventDate", data = "missing"), |
|
| 270 |
definition = function(object, level = 0.95, |
|
| 271 |
calendar = get_calendar()) {
|
|
| 272 | 1x |
data <- object@data |
| 273 | 1x |
methods::callGeneric(object, data = data, level = level, calendar = calendar) |
| 274 |
} |
|
| 275 |
) |
|
| 276 | ||
| 277 |
#' @export |
|
| 278 |
#' @rdname predict_event |
|
| 279 |
#' @aliases predict_accumulation,EventDate,matrix-method |
|
| 280 |
setMethod( |
|
| 281 |
f = "predict_accumulation", |
|
| 282 |
signature = c(object = "EventDate", data = "matrix"), |
|
| 283 |
definition = function(object, data, level = 0.95, |
|
| 284 |
calendar = get_calendar()) {
|
|
| 285 |
## Predict event date |
|
| 286 | 1x |
col_event <- predict_event(object, margin = 2, calendar = NULL) |
| 287 | ||
| 288 |
## Accumulation time point estimate |
|
| 289 | 1x |
date_range <- seq( |
| 290 | 1x |
from = min(col_event$lower, na.rm = TRUE), |
| 291 | 1x |
to = max(col_event$upper, na.rm = TRUE), |
| 292 | 1x |
length.out = 1000 |
| 293 |
) |
|
| 294 | 1x |
dens <- mapply( |
| 295 | 1x |
FUN = stats::dnorm, |
| 296 | 1x |
mean = col_event$date, |
| 297 | 1x |
sd = col_event$error, |
| 298 | 1x |
MoreArgs = list(date_range), |
| 299 | 1x |
SIMPLIFY = TRUE |
| 300 |
) |
|
| 301 | 1x |
acc <- apply( |
| 302 | 1x |
X = data, |
| 303 | 1x |
MARGIN = 1, |
| 304 | 1x |
FUN = function(x, density) {
|
| 305 | 420x |
colSums(t(density) * as.numeric(x)) |
| 306 |
}, |
|
| 307 | 1x |
density = dens |
| 308 |
) |
|
| 309 | ||
| 310 | 1x |
alpha <- (1 - level) / 2 |
| 311 | 1x |
probs <- c(0.5, alpha, 1 - alpha) |
| 312 | 1x |
quant <- quantile_density(x = date_range, y = acc, probs = probs) |
| 313 | ||
| 314 |
## Convert |
|
| 315 | 1x |
quant <- as.data.frame(quant) |
| 316 | 1x |
colnames(quant) <- c("date", "lower", "upper")
|
| 317 | 1x |
if (is.null(calendar)) return(quant) |
| 318 | ||
| 319 | ! |
quant[] <- lapply( |
| 320 | ! |
X = quant, |
| 321 | ! |
FUN = aion::as_year, |
| 322 | ! |
calendar = calendar, |
| 323 | ! |
decimal = TRUE |
| 324 |
) |
|
| 325 | ! |
quant |
| 326 |
} |
|
| 327 |
) |
|
| 328 | ||
| 329 |
#' @export |
|
| 330 |
#' @rdname density_event |
|
| 331 |
#' @aliases density_accumulation,EventDate-method |
|
| 332 |
setMethod( |
|
| 333 |
f = "density_accumulation", |
|
| 334 |
signature = c(object = "EventDate"), |
|
| 335 |
definition = function(object, dates = NULL, calendar = NULL, |
|
| 336 |
type = c("activity", "tempo"), n = 500, ...) {
|
|
| 337 |
## Validation |
|
| 338 | ! |
type <- match.arg(type, several.ok = FALSE) |
| 339 | ||
| 340 |
## Get data |
|
| 341 | ! |
columns <- predict_event(object, margin = 2, calendar = NULL) |
| 342 | ! |
col_dates <- columns$date |
| 343 | ! |
col_errors <- columns$error |
| 344 | ||
| 345 | ! |
if (is.null(dates)) {
|
| 346 | ! |
dates <- seq( |
| 347 | ! |
from = min(columns$lower, na.rm = TRUE) * 0.96, |
| 348 | ! |
to = max(columns$upper, na.rm = TRUE) * 1.04, |
| 349 | ! |
length.out = n |
| 350 |
) |
|
| 351 |
} |
|
| 352 | ! |
if (is.null(calendar)) {
|
| 353 | ! |
dates <- aion::as_fixed(dates) |
| 354 |
} else {
|
|
| 355 | ! |
dates <- aion::fixed(dates, calendar = calendar) |
| 356 |
} |
|
| 357 | ||
| 358 |
## Weighted sum of the fabric dates |
|
| 359 | ! |
counts <- dimensio::get_data(object) |
| 360 | ! |
freq <- counts / rowSums(counts) |
| 361 | ||
| 362 |
## Tempo vs activity plot |
|
| 363 | ! |
fun <- switch( |
| 364 | ! |
type, |
| 365 | ! |
activity = stats::dnorm, |
| 366 | ! |
tempo = stats::pnorm |
| 367 |
) |
|
| 368 | ||
| 369 |
## Density estimation |
|
| 370 | ! |
col_density <- mapply( |
| 371 | ! |
FUN = fun, |
| 372 | ! |
mean = col_dates, |
| 373 | ! |
sd = col_errors, |
| 374 | ! |
MoreArgs = list(dates), |
| 375 | ! |
SIMPLIFY = TRUE |
| 376 |
) |
|
| 377 | ||
| 378 | ! |
date_acc <- apply( |
| 379 | ! |
X = freq, |
| 380 | ! |
MARGIN = 1, |
| 381 | ! |
FUN = function(x, density) {
|
| 382 | ! |
colSums(t(density) * as.numeric(x)) |
| 383 |
}, |
|
| 384 | ! |
density = col_density |
| 385 |
) |
|
| 386 | ||
| 387 | ! |
aion::series(object = date_acc, time = dates) |
| 388 |
} |
|
| 389 |
) |
|
| 390 | ||
| 391 |
# Helpers ====================================================================== |
|
| 392 |
#' Predict event dates |
|
| 393 |
#' |
|
| 394 |
#' @param fit A \code{\link[stats:lm]{multiple linear model}}.
|
|
| 395 |
#' @param data A [`numeric`] matrix giving the coordinates in CA space. |
|
| 396 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 397 |
#' @return |
|
| 398 |
#' A four columns [`numeric`] matrix giving the predicted event dates, |
|
| 399 |
#' the corresponding confidence interval boundaries and the standard error of |
|
| 400 |
#' the predicted dates. |
|
| 401 |
#' @author N. Frerebeau |
|
| 402 |
#' @keywords internal |
|
| 403 |
#' @noRd |
|
| 404 |
compute_event <- function(fit, data, level, error = TRUE) {
|
|
| 405 | 3x |
data <- as.data.frame(data) |
| 406 | ||
| 407 | 3x |
date_predict <- stats::predict.lm( |
| 408 | 3x |
object = fit, |
| 409 | 3x |
newdata = data, |
| 410 | 3x |
se.fit = TRUE, |
| 411 | 3x |
interval = "confidence", |
| 412 | 3x |
level = level |
| 413 |
) |
|
| 414 | ||
| 415 |
# Three columns matrix: predicted value + CI boundaries |
|
| 416 | 3x |
results <- as.data.frame(date_predict$fit) |
| 417 | 3x |
rownames(results) <- rownames(data) |
| 418 | 3x |
colnames(results) <- c("date", "lower", "upper")
|
| 419 | 3x |
if (error) results$error <- date_predict$se.fit |
| 420 | ||
| 421 | 3x |
results |
| 422 |
} |
| 1 |
# AORISTIC ANALYSIS |
|
| 2 |
#' @include AllClasses.R AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Aoristic sum ================================================================= |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname aoristic |
|
| 8 |
#' @aliases aoristic,numeric,numeric-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "aoristic", |
|
| 11 |
signature = c(x = "numeric", y = "numeric"), |
|
| 12 |
definition = function(x, y, step = 1, start = min(x), end = max(y), |
|
| 13 |
calendar = CE(), weight = TRUE, groups = NULL) {
|
|
| 14 |
## Validation |
|
| 15 | 6x |
n <- length(x) |
| 16 | 6x |
arkhe::assert_length(y, n) |
| 17 | 4x |
if (is.null(groups)) groups <- rep(NA, n) |
| 18 | 6x |
groups <- as.character(groups) |
| 19 | 6x |
arkhe::assert_length(groups, n) |
| 20 | ||
| 21 |
## Grouping |
|
| 22 | 5x |
lvl <- unique(groups) |
| 23 | 5x |
grp <- factor(groups, levels = lvl, exclude = NULL) |
| 24 | 5x |
spl <- split(seq_along(x), f = grp) |
| 25 | 5x |
m <- length(spl) |
| 26 | ||
| 27 |
## Convert to rata die |
|
| 28 |
## NB: argument are not evaluated until they are used. |
|
| 29 |
## ('start' and 'end' must go first)
|
|
| 30 | 5x |
breaks <- seq(from = start, to = end, by = step) |
| 31 | 5x |
breaks <- aion::fixed(breaks, calendar = calendar) |
| 32 | 5x |
x <- aion::fixed(x, calendar = calendar) |
| 33 | 5x |
y <- aion::fixed(y, calendar = calendar) |
| 34 | ||
| 35 |
## Set up breaks |
|
| 36 | 5x |
block_start <- utils::head(breaks, -1) |
| 37 | 5x |
block_end <- utils::tail(breaks, -1) |
| 38 | 5x |
block_mid <- (block_start + block_end) / 2 |
| 39 | ||
| 40 |
## Number of time blocks |
|
| 41 | 5x |
n_blocks <- length(breaks) - 1 |
| 42 | 5x |
ao_probs <- array(data = 0, dim = c(n, n_blocks, m)) |
| 43 | ||
| 44 |
## Aoristic probability |
|
| 45 | 5x |
span <- abs(y - x) |
| 46 | 5x |
for (k in seq_len(m)) {
|
| 47 | 6x |
s <- spl[[k]] |
| 48 | 6x |
for (j in seq_len(n_blocks)) {
|
| 49 | 24x |
a <- block_start[[j]] |
| 50 | 24x |
b <- block_end[[j]] |
| 51 | ||
| 52 | 24x |
max_start <- pmax(x[s], a) |
| 53 | 24x |
min_end <- pmin(y[s], b) |
| 54 | 24x |
overlap <- (min_end - max_start) / span[s] |
| 55 | 24x |
overlap[overlap <= 0] <- 0 |
| 56 | 4x |
if (!weight) overlap[overlap > 0] <- 1 |
| 57 | 24x |
ao_probs[s, j, k] <- overlap |
| 58 |
} |
|
| 59 |
} |
|
| 60 | ||
| 61 |
## Aoristic sum |
|
| 62 | 5x |
ao_sum <- apply(X = ao_probs, MARGIN = c(2, 3), FUN = sum) |
| 63 | ||
| 64 | 5x |
if (!anyNA(groups)) {
|
| 65 | 1x |
dimnames(ao_probs)[[3]] <- colnames(ao_sum) <- lvl |
| 66 |
} |
|
| 67 | ||
| 68 | 5x |
ts <- aion::series( |
| 69 | 5x |
ao_sum, |
| 70 | 5x |
time = block_mid |
| 71 |
) |
|
| 72 | 5x |
.AoristicSum( |
| 73 | 5x |
ts, |
| 74 | 5x |
breaks = breaks, |
| 75 | 5x |
span = span, |
| 76 | 5x |
groups = groups, |
| 77 | 5x |
p = ao_probs |
| 78 |
) |
|
| 79 |
} |
|
| 80 |
) |
|
| 81 | ||
| 82 |
#' @export |
|
| 83 |
#' @rdname aoristic |
|
| 84 |
#' @aliases aoristic,ANY,missing-method |
|
| 85 |
setMethod( |
|
| 86 |
f = "aoristic", |
|
| 87 |
signature = c(x = "ANY", y = "missing"), |
|
| 88 |
definition = function(x, step = 1, start = NULL, end = NULL, |
|
| 89 |
calendar = CE(), weight = TRUE, groups = NULL) {
|
|
| 90 | 7x |
xy <- grDevices::xy.coords(x) |
| 91 | 7x |
g <- groups |
| 92 | 7x |
if (is.list(x) && !is.null(g) && length(g) == 1) {
|
| 93 | 1x |
g <- x[[g]] |
| 94 | 1x |
if (is.null(g)) {
|
| 95 | 1x |
txt <- tr_("%s is a list, but does not have component %s.")
|
| 96 | 1x |
msg <- sprintf(txt, sQuote("x"), sQuote(groups))
|
| 97 | 1x |
stop(msg, call. = FALSE) |
| 98 |
} |
|
| 99 |
} |
|
| 100 | ||
| 101 |
## Start/end |
|
| 102 | 6x |
if (is.null(start)) start <- min(xy$x, na.rm = TRUE) |
| 103 | 6x |
if (is.null(end)) end <- max(xy$y, na.rm = TRUE) |
| 104 | ||
| 105 | 6x |
methods::callGeneric(x = xy$x, y = xy$y, step = step, start = start, |
| 106 | 6x |
end = end, calendar = calendar, weight = weight, |
| 107 | 6x |
groups = g) |
| 108 |
} |
|
| 109 |
) |
|
| 110 | ||
| 111 |
# Rate of change =============================================================== |
|
| 112 |
#' @export |
|
| 113 |
#' @rdname roc |
|
| 114 |
#' @aliases roc,AoristicSum-method |
|
| 115 |
setMethod( |
|
| 116 |
f = "roc", |
|
| 117 |
signature = c(object = "AoristicSum"), |
|
| 118 |
definition = function(object, n = 100) {
|
|
| 119 |
## Get time span of the blocks |
|
| 120 | 1x |
mid <- aion::time(object, calendar = NULL) |
| 121 | 1x |
step <- mean(diff(mid)) |
| 122 | 1x |
end <- utils::tail(mid, -1) + step / 2 |
| 123 | ||
| 124 |
## Get aoristic weights |
|
| 125 | 1x |
w <- object@p |
| 126 | ||
| 127 | 1x |
n <- as.integer(n) |
| 128 | 1x |
m <- dim(w)[[1]] |
| 129 | 1x |
p <- dim(w)[[2]] |
| 130 | 1x |
q <- dim(w)[[3]] |
| 131 | ||
| 132 |
## Monte Carlo simulation |
|
| 133 | 1x |
roc <- array(data = 0, dim = c(p-1, n, q)) |
| 134 | 1x |
for (j in seq_len(q)) {
|
| 135 | 2x |
sim <- array(data = 0, dim = c(m, p, n)) |
| 136 | 2x |
for (i in seq_len(m)) {
|
| 137 | 20x |
probs <- w[i, , j] |
| 138 | 10x |
if (sum(probs) == 0) next |
| 139 | 10x |
counts <- replicate(n, {
|
| 140 | 1000x |
tmp <- numeric(p) |
| 141 | 1000x |
k <- sample(seq_len(p), size = 1, prob = probs) |
| 142 | 1000x |
tmp[k] <- 1 |
| 143 | 1000x |
tmp |
| 144 |
}) |
|
| 145 | 10x |
sim[i, , ] <- counts |
| 146 |
} |
|
| 147 | 2x |
total <- apply(X = sim, MARGIN = c(2, 3), FUN = sum) |
| 148 | 2x |
roc[, , j] <- apply(X = total, MARGIN = 2, FUN = diff, lag = 1) |
| 149 |
} |
|
| 150 | ||
| 151 | 1x |
dimnames(roc)[[3]] <- dimnames(w)[[3]] |
| 152 | ||
| 153 | 1x |
ts <- aion::series( |
| 154 | 1x |
object = roc / step, |
| 155 | 1x |
time = end |
| 156 |
) |
|
| 157 | 1x |
.RateOfChange( |
| 158 | 1x |
ts, |
| 159 | 1x |
replicates = n, |
| 160 | 1x |
groups = unique(object@groups) |
| 161 |
) |
|
| 162 |
} |
|
| 163 |
) |
|
| 164 | ||
| 165 |
# Plot ========================================================================= |
|
| 166 |
## AoristicSum ----------------------------------------------------------------- |
|
| 167 |
#' @export |
|
| 168 |
#' @method plot AoristicSum |
|
| 169 |
plot.AoristicSum <- function(x, calendar = get_calendar(), |
|
| 170 |
type = c("bar"),
|
|
| 171 |
flip = FALSE, ncol = NULL, |
|
| 172 |
main = NULL, sub = NULL, |
|
| 173 |
ann = graphics::par("ann"), axes = TRUE,
|
|
| 174 |
frame.plot = axes, |
|
| 175 |
panel.first = NULL, panel.last = NULL, ...) {
|
|
| 176 |
## Validation |
|
| 177 | 3x |
type <- match.arg(type, several.ok = FALSE) |
| 178 | ||
| 179 |
## Plot |
|
| 180 | 3x |
panel_bar <- function(x, y, ...) {
|
| 181 | 4x |
step <- mean(diff(x)) |
| 182 | 4x |
start <- x - step / 2 |
| 183 | 4x |
end <- x + step / 2 |
| 184 | 4x |
graphics::rect(xleft = start, xright = end, ybottom = 0, ytop = y, ...) |
| 185 |
} |
|
| 186 | 3x |
panel_density <- function(x, y, ...) {
|
| 187 | ! |
step <- mean(diff(x)) |
| 188 | ! |
s <- sample(x = x, size = 10^5, replace = TRUE, prob = y) |
| 189 | ! |
d <- stats::density(x = s, bw = step) |
| 190 | ! |
x <- d$x |
| 191 | ! |
y <- d$y |
| 192 | ! |
graphics::polygon(x = c(x, rev(x)), y = c(y, numeric(length(y))), |
| 193 | ! |
border = NA, ...) |
| 194 | ! |
graphics::lines(x = x, y = y) |
| 195 |
} |
|
| 196 | ||
| 197 | 3x |
panel_fun <- switch ( |
| 198 | 3x |
type, |
| 199 | 3x |
bar = panel_bar, |
| 200 | 3x |
density = panel_density |
| 201 |
) |
|
| 202 | ||
| 203 |
## Method for TimeSeries |
|
| 204 | 3x |
methods::callNextMethod(x, facet = "multiple", calendar = calendar, |
| 205 | 3x |
panel = panel_fun, flip = flip, ncol = ncol, |
| 206 | 3x |
xlab = NULL, ylab = NULL, |
| 207 | 3x |
main = main, sub = sub, |
| 208 | 3x |
ann = ann, axes = axes, |
| 209 | 3x |
frame.plot = frame.plot, |
| 210 | 3x |
panel.first = panel.first, |
| 211 | 3x |
panel.last = panel.last, ...) |
| 212 | ||
| 213 | ||
| 214 | 3x |
invisible(x) |
| 215 |
} |
|
| 216 | ||
| 217 |
#' @export |
|
| 218 |
#' @rdname plot.AoristicSum |
|
| 219 |
#' @aliases plot,AoristicSum,missing-method |
|
| 220 |
setMethod("plot", c(x = "AoristicSum", y = "missing"), plot.AoristicSum)
|
|
| 221 | ||
| 222 |
#' @export |
|
| 223 |
#' @method image AoristicSum |
|
| 224 |
image.AoristicSum <- function(x, calendar = get_calendar(), ...) {
|
|
| 225 | ! |
methods::callNextMethod() |
| 226 | ! |
invisible(x) |
| 227 |
} |
|
| 228 | ||
| 229 |
#' @export |
|
| 230 |
#' @rdname plot.AoristicSum |
|
| 231 |
#' @aliases image,AoristicSum-method |
|
| 232 |
setMethod("image", c(x = "AoristicSum"), image.AoristicSum)
|
|
| 233 | ||
| 234 |
## RateOfChange ---------------------------------------------------------------- |
|
| 235 |
#' @export |
|
| 236 |
#' @method plot RateOfChange |
|
| 237 |
plot.RateOfChange <- function(x, calendar = get_calendar(), |
|
| 238 |
level = 0.95, flip = FALSE, ncol = NULL, |
|
| 239 |
main = NULL, sub = NULL, |
|
| 240 |
ann = graphics::par("ann"), axes = TRUE,
|
|
| 241 |
frame.plot = axes, |
|
| 242 |
panel.first = NULL, panel.last = NULL, ...) {
|
|
| 243 |
## Validation |
|
| 244 | 1x |
n <- dim(x)[[3L]] |
| 245 | 1x |
n_seq <- seq_len(n) |
| 246 | 1x |
if (is.null(ncol)) ncol <- if (n > 4) 2 else 1 |
| 247 | 1x |
n_row <- ceiling(n / ncol) |
| 248 | 1x |
ylabs <- dimnames(x)[[3L]] %||% c(tr_("Rate of Change"))
|
| 249 | ||
| 250 |
## Compute mean and confidence interval |
|
| 251 | 1x |
ci <- apply( |
| 252 | 1x |
X = x, |
| 253 | 1x |
MARGIN = c(1, 3), |
| 254 | 1x |
FUN = function(x, level) {
|
| 255 | 6x |
ci <- arkhe::confidence_mean(x, level = level) |
| 256 | 6x |
c(mean = mean(x), ci) |
| 257 |
}, |
|
| 258 | 1x |
level = level |
| 259 |
) |
|
| 260 | ||
| 261 |
## Graphical parameters |
|
| 262 |
## Save and restore |
|
| 263 | 1x |
old_par <- graphics::par( |
| 264 | 1x |
mar = c(0, 5.1, 0, if (flip) 5.1 else 2.1), |
| 265 | 1x |
oma = c(6, 0, 5, 0), |
| 266 | 1x |
mfcol = c(n_row, ncol) |
| 267 |
) |
|
| 268 | 1x |
on.exit(graphics::par(old_par)) |
| 269 | ||
| 270 | 1x |
cex.lab <- list(...)$cex.lab %||% graphics::par("cex.lab")
|
| 271 | 1x |
col.lab <- list(...)$col.lab %||% graphics::par("col.lab")
|
| 272 | 1x |
font.lab <- list(...)$font.lab %||% graphics::par("font.lab")
|
| 273 | 1x |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis")
|
| 274 | 1x |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis")
|
| 275 | 1x |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis")
|
| 276 | 1x |
cex.main <- list(...)$cex.main %||% graphics::par("cex.main")
|
| 277 | 1x |
font.main <- list(...)$font.main %||% graphics::par("font.main")
|
| 278 | 1x |
col.main <- list(...)$col.main %||% graphics::par("col.main")
|
| 279 | 1x |
col <- list(...)$col %||% c("grey")
|
| 280 | 1x |
if (length(col) != n) col <- rep(col, n) |
| 281 | ||
| 282 | 1x |
years <- aion::time(x, calendar = calendar) |
| 283 | 1x |
xlim <- range(years) |
| 284 | 1x |
for (i in n_seq) {
|
| 285 | 2x |
xi <- ci[, , i, drop = TRUE] |
| 286 | ||
| 287 |
## Open new window |
|
| 288 | 2x |
grDevices::dev.hold() |
| 289 | 2x |
on.exit(grDevices::dev.flush(), add = TRUE) |
| 290 | 2x |
graphics::plot.new() |
| 291 | ||
| 292 |
## Set plotting coordinates |
|
| 293 | 2x |
ylim <- range(xi, na.rm = TRUE) |
| 294 | 2x |
graphics::plot.window(xlim = xlim, ylim = ylim) |
| 295 | ||
| 296 |
## Evaluate pre-plot expressions |
|
| 297 | 2x |
panel.first |
| 298 | ||
| 299 |
## Plot |
|
| 300 | 2x |
graphics::abline(h = 0, lty = "dotted", lwd = 1) |
| 301 | 2x |
graphics::polygon(x = c(years, rev(years)), |
| 302 | 2x |
y = c(xi[2, ], rev(xi[3, ])), |
| 303 | 2x |
col = col[i], border = NA) |
| 304 | 2x |
graphics::lines(x = years, y = xi[1, ]) |
| 305 | 2x |
graphics::points(x = years, y = xi[1, ], pch = 16) |
| 306 | ||
| 307 |
## Evaluate post-plot and pre-axis expressions |
|
| 308 | 2x |
panel.last |
| 309 | ||
| 310 |
## Construct Axis |
|
| 311 | 2x |
do_x <- i %% n_row == 0 || i == n |
| 312 | 2x |
y_side <- if (i %% 2 || !flip) 2 else 4 |
| 313 | 2x |
if (axes) {
|
| 314 | 2x |
if (do_x) {
|
| 315 | 1x |
year_axis(side = 1, format = TRUE, calendar = calendar, |
| 316 | 1x |
current_calendar = calendar, cex.axis = cex.axis, |
| 317 | 1x |
col.axis = col.axis, font.axis = font.axis) |
| 318 |
} |
|
| 319 | 2x |
graphics::axis(side = y_side, xpd = NA, cex.axis = cex.axis, |
| 320 | 2x |
col.axis = col.axis, font.axis = font.axis, las = 1) |
| 321 |
} |
|
| 322 | ||
| 323 |
## Plot frame |
|
| 324 | 2x |
if (frame.plot) {
|
| 325 | 2x |
graphics::box() |
| 326 |
} |
|
| 327 | ||
| 328 |
## Add annotation |
|
| 329 | 2x |
if (ann) {
|
| 330 | 2x |
if (do_x) {
|
| 331 | 1x |
xlab <- format(calendar) |
| 332 | 1x |
graphics::mtext(xlab, side = 1, line = 3, cex = cex.lab, col = col.lab, |
| 333 | 1x |
font = font.lab) |
| 334 |
} |
|
| 335 | 2x |
graphics::mtext(ylabs[[i]], side = y_side, line = 4, cex = cex.lab, |
| 336 | 2x |
col = col.lab, font = font.lab) |
| 337 |
} |
|
| 338 |
} |
|
| 339 | ||
| 340 |
## Add annotation |
|
| 341 | 1x |
if (ann) {
|
| 342 | 1x |
graphics::par(mfcol = c(1, 1)) |
| 343 | 1x |
graphics::mtext(main, side = 3, line = 3, cex = cex.main, font = font.main, |
| 344 | 1x |
col = col.main) |
| 345 |
} |
|
| 346 | ||
| 347 | 1x |
invisible(x) |
| 348 |
} |
|
| 349 | ||
| 350 |
#' @export |
|
| 351 |
#' @rdname plot.AoristicSum |
|
| 352 |
#' @aliases plot,RateOfChange,missing-method |
|
| 353 |
setMethod("plot", c(x = "RateOfChange", y = "missing"), plot.RateOfChange)
|
| 1 |
# PLOT DATES |
|
| 2 |
#' @include AllClasses.R AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @method plot EventDate |
|
| 7 |
plot.EventDate <- function(x, type = c("activity", "tempo"), event = FALSE,
|
|
| 8 |
calendar = get_calendar(), |
|
| 9 |
select = 1, n = 500, eps = 1e-09, |
|
| 10 |
col.accumulation = "black", col.event = "red", |
|
| 11 |
flip = FALSE, ncol = NULL, |
|
| 12 |
xlab = NULL, ylab = NULL, |
|
| 13 |
main = NULL, sub = NULL, |
|
| 14 |
ann = graphics::par("ann"), axes = TRUE,
|
|
| 15 |
frame.plot = axes, ...) {
|
|
| 16 |
## Validation |
|
| 17 | ! |
type <- match.arg(type, several.ok = FALSE) |
| 18 | ||
| 19 |
## Event date |
|
| 20 | ! |
date_event <- density_event(x, n = n) |
| 21 | ! |
date_range <- aion::time(date_event) |
| 22 | ! |
cases <- colnames(date_event) |
| 23 | ||
| 24 |
## Accumulation time |
|
| 25 | ! |
date_acc <- density_accumulation(x, dates = date_range, type = type, n = n) |
| 26 | ||
| 27 |
## Selection |
|
| 28 | ! |
if (is.null(select)) index <- seq_along(cases) |
| 29 | ! |
else if (is.character(select)) index <- which(cases %in% select) |
| 30 | ! |
else index <- as.numeric(select) |
| 31 | ||
| 32 | ! |
k <- length(index) |
| 33 | ! |
if (k == 0) stop(tr_("Wrong selection."), call. = FALSE)
|
| 34 | ||
| 35 | ! |
if (type != "activity" || !event) {
|
| 36 | ! |
date_event <- array(data = NA, dim = list(n, k, 1)) |
| 37 |
} |
|
| 38 | ||
| 39 | ! |
date_event <- date_event[, index, , drop = FALSE] |
| 40 | ! |
date_acc <- date_acc[, index, , drop = FALSE] |
| 41 | ||
| 42 |
## Cleaning |
|
| 43 |
# date_acc[date_acc < eps] <- NA |
|
| 44 | ! |
date_event[date_event < eps] <- NA |
| 45 | ! |
na_event <- apply(date_event, 1, function(x) all(is.na(x))) |
| 46 | ! |
na_acc <- apply(date_acc, 1, function(x) all(is.na(x))) |
| 47 | ! |
date_drop <- na_event & na_acc |
| 48 | ||
| 49 |
## Time series |
|
| 50 | ! |
ts <- array(data = c(date_acc, date_event), dim = c(n, k, 2)) |
| 51 | ! |
dimnames(ts) <- list(NULL, cases[index], c("accumulation", "event"))
|
| 52 | ! |
ts <- aion::series(object = ts[!date_drop, , , drop = FALSE], |
| 53 | ! |
time = aion::as_fixed(date_range[!date_drop])) |
| 54 | ||
| 55 | ! |
panel <- switch( |
| 56 | ! |
type, |
| 57 | ! |
activity = function(x, y, ...) {
|
| 58 | ! |
graphics::polygon(x = c(x, rev(x)), y = c(y, rep(0, length(y))), |
| 59 | ! |
border = NA, ...) |
| 60 | ! |
graphics::lines(x, y, col = "black", lty = list(...)$lty) |
| 61 |
}, |
|
| 62 | ! |
tempo = function(x, y, ...) graphics::lines(x, y, col = "black", lty = 1) |
| 63 |
) |
|
| 64 | ||
| 65 | ! |
col <- c(col.accumulation, grDevices::adjustcolor(col.event, alpha = 0.5)) |
| 66 | ! |
aion::plot(ts, panel = panel, calendar = calendar, |
| 67 | ! |
flip = flip, ncol = ncol, xlab = xlab, ylab = ylab, |
| 68 | ! |
main = main, sub = sub, ann = ann, axes = axes, |
| 69 | ! |
frame.plot = frame.plot, |
| 70 | ! |
col = col, lty = c(0, 0)) |
| 71 | ||
| 72 | ! |
invisible(x) |
| 73 |
} |
|
| 74 | ||
| 75 |
#' @export |
|
| 76 |
#' @rdname plot.EventDate |
|
| 77 |
#' @aliases plot,EventDate,missing-method |
|
| 78 |
setMethod("plot", c(x = "EventDate", y = "missing"), plot.EventDate)
|
| 1 |
# SUBSET |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Extract ====================================================================== |
|
| 6 |
## [ --------------------------------------------------------------------------- |
|
| 7 |
#' @export |
|
| 8 |
#' @rdname subset |
|
| 9 |
#' @aliases [,MeanDate-method |
|
| 10 |
setMethod( |
|
| 11 |
f = "[", |
|
| 12 |
signature = c(x = "MeanDate"), |
|
| 13 |
function(x, i, j, k, drop = FALSE) {
|
|
| 14 | ! |
z <- x@.Data |
| 15 | ! |
time <- x@.Time |
| 16 | ! |
dates <- x@dates |
| 17 | ||
| 18 | ! |
z <- z[i, j, k, drop = drop] |
| 19 | ! |
if (!missing(i)) {
|
| 20 | ! |
if (is.character(i)) i <- match(i, dimnames(x)[1L]) |
| 21 | ! |
time <- time[i] |
| 22 |
} |
|
| 23 | ! |
if (!missing(j)) {
|
| 24 | ! |
if (is.character(j)) j <- match(j, dimnames(x)[2L]) |
| 25 | ! |
dates <- dates[j] |
| 26 |
} |
|
| 27 | ||
| 28 | ! |
if (isTRUE(drop)) return(z) |
| 29 | ! |
methods::initialize(x, z, .Time = time, dates = dates) |
| 30 |
} |
|
| 31 |
) |
|
| 32 | ||
| 33 |
#' @export |
|
| 34 |
#' @rdname subset |
|
| 35 |
#' @aliases [,IncrementTest-method |
|
| 36 |
setMethod( |
|
| 37 |
f = "[", |
|
| 38 |
signature = c(x = "IncrementTest"), |
|
| 39 |
function(x, i, j, k, drop = FALSE) {
|
|
| 40 | 72x |
z <- x@.Data |
| 41 | 72x |
time <- x@.Time |
| 42 | 72x |
statistic <- x@statistic |
| 43 | 72x |
p_value <- x@p_value |
| 44 | ||
| 45 | 72x |
z <- z[i, j, k, drop = drop] |
| 46 | 72x |
if (!missing(i)) {
|
| 47 | ! |
if (is.character(i)) i <- match(i, dimnames(x)[1L]) |
| 48 | ! |
time <- time[i] |
| 49 |
} |
|
| 50 | 72x |
if (!missing(j)) {
|
| 51 | ! |
if (is.character(j)) j <- match(j, dimnames(x)[2L]) |
| 52 | 72x |
statistic <- statistic[j] |
| 53 | 72x |
p_value <- p_value[j] |
| 54 |
} |
|
| 55 | ||
| 56 | 54x |
if (isTRUE(drop)) return(z) |
| 57 | 18x |
methods::initialize(x, z, .Time = time, statistic = statistic, p_value = p_value) |
| 58 |
} |
|
| 59 |
) |
|
| 60 | ||
| 61 |
## [[ -------------------------------------------------------------------------- |
|
| 62 |
#' Extract Parts of an Object |
|
| 63 |
#' |
|
| 64 |
#' @inheritParams [[ |
|
| 65 |
#' @author N. Frerebeau |
|
| 66 |
#' @keywords internal |
|
| 67 |
#' @noRd |
|
| 68 |
extract_slot <- function(x, i) {
|
|
| 69 | ! |
class_name <- class(x) |
| 70 | ! |
i <- match.arg(i, choices = methods::slotNames(class_name), |
| 71 | ! |
several.ok = FALSE) |
| 72 | ! |
data <- methods::slot(x, i) |
| 73 | ! |
data |
| 74 |
} |
|
| 75 | ||
| 76 |
#' @export |
|
| 77 |
#' @rdname subset |
|
| 78 |
#' @aliases [[,PermutationOrder,ANY,missing-method |
|
| 79 |
setMethod( |
|
| 80 |
f = "[[", |
|
| 81 |
signature = c(x = "PermutationOrder", i = "ANY", j = "missing"), |
|
| 82 |
definition = extract_slot |
|
| 83 |
) |
| 1 |
# MEAN CERAMIC DATE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# MCD ========================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname mcd |
|
| 8 |
#' @aliases mcd,numeric,numeric-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "mcd", |
|
| 11 |
signature = c(object = "numeric", dates = "numeric"), |
|
| 12 |
definition = function(object, dates, calendar = CE()) {
|
|
| 13 | ! |
object <- matrix(object, nrow = 1) |
| 14 | ! |
methods::callGeneric(object, dates = dates, calendar = calendar) |
| 15 |
} |
|
| 16 |
) |
|
| 17 | ||
| 18 |
#' @export |
|
| 19 |
#' @rdname mcd |
|
| 20 |
#' @aliases mcd,data.frame,numeric-method |
|
| 21 |
setMethod( |
|
| 22 |
f = "mcd", |
|
| 23 |
signature = c(object = "data.frame", dates = "numeric"), |
|
| 24 |
definition = function(object, dates, calendar = CE()) {
|
|
| 25 | 2x |
object <- data.matrix(object) |
| 26 | 2x |
methods::callGeneric(object, dates = dates, calendar = calendar) |
| 27 |
} |
|
| 28 |
) |
|
| 29 | ||
| 30 |
#' @export |
|
| 31 |
#' @rdname mcd |
|
| 32 |
#' @aliases mcd,matrix,numeric-method |
|
| 33 |
setMethod( |
|
| 34 |
f = "mcd", |
|
| 35 |
signature = c(object = "matrix", dates = "numeric"), |
|
| 36 |
definition = function(object, dates, calendar = CE()) {
|
|
| 37 |
## Validation |
|
| 38 | 2x |
arkhe::assert_length(dates, NCOL(object)) |
| 39 | ||
| 40 | 1x |
if (is.null(calendar)) {
|
| 41 | ! |
dates <- aion::as_fixed(dates) # Assume rata die |
| 42 |
} else {
|
|
| 43 | 1x |
dates <- aion::fixed(dates, calendar = calendar) |
| 44 |
} |
|
| 45 | ||
| 46 |
## Calculate MCD |
|
| 47 | 1x |
mcd_dates <- apply(X = object, MARGIN = 1, FUN = .mcd, dates = dates) |
| 48 | 1x |
mcd_dates <- aion::as_fixed(mcd_dates) |
| 49 | ||
| 50 | 1x |
ts <- aion::series(object, time = mcd_dates) |
| 51 | 1x |
rownames(ts) <- rownames(object) |
| 52 | 1x |
.MeanDate(ts, dates = dates) |
| 53 |
} |
|
| 54 |
) |
|
| 55 | ||
| 56 |
.mcd <- function(x, dates) {
|
|
| 57 | 12x |
stats::weighted.mean(x = dates, w = x) |
| 58 |
} |
|
| 59 | ||
| 60 |
# Plot ========================================================================= |
|
| 61 |
#' @export |
|
| 62 |
#' @method plot MeanDate |
|
| 63 |
plot.MeanDate <- function(x, calendar = get_calendar(), |
|
| 64 |
decreasing = TRUE, |
|
| 65 |
main = NULL, sub = NULL, |
|
| 66 |
ann = graphics::par("ann"), axes = TRUE,
|
|
| 67 |
frame.plot = axes, |
|
| 68 |
panel.first = NULL, panel.last = NULL, ...) {
|
|
| 69 |
## Get data |
|
| 70 | 2x |
n <- NROW(x) |
| 71 | 2x |
n_seq <- seq_len(n) |
| 72 | 2x |
sites <- rownames(x) %||% paste0("S", n_seq)
|
| 73 | ||
| 74 |
## Graphical parameters |
|
| 75 | 2x |
col <- list(...)$col %||% graphics::par("col")
|
| 76 | 2x |
bg <- list(...)$bg %||% graphics::par("bg")
|
| 77 | 2x |
pch <- list(...)$pch %||% c(16) |
| 78 | 2x |
cex <- list(...)$cex %||% graphics::par("cex")
|
| 79 | 2x |
lwd <- list(...)$lwd %||% graphics::par("lwd")
|
| 80 | 2x |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis")
|
| 81 | 2x |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis")
|
| 82 | 2x |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis")
|
| 83 | 2x |
if (length(col) != n) col <- rep(col, length.out = n) |
| 84 | 2x |
if (length(bg) != n) bg <- rep(bg, length.out = n) |
| 85 | 2x |
if (length(pch) != n) pch <- rep(pch, length.out = n) |
| 86 | 2x |
if (length(cex) != n) cex <- rep(cex, length.out = n) |
| 87 | 2x |
if (length(lwd) != n) lwd <- rep(lwd, length.out = n) |
| 88 | ||
| 89 |
## Save and restore |
|
| 90 | 2x |
mar <- graphics::par("mar")
|
| 91 | 2x |
mar[2] <- inch2line(sites, cex = cex.axis) + 0.5 |
| 92 | 2x |
old_par <- graphics::par(mar = mar) |
| 93 | 2x |
on.exit(graphics::par(old_par)) |
| 94 | ||
| 95 |
## Open new window |
|
| 96 | 2x |
grDevices::dev.hold() |
| 97 | 2x |
on.exit(grDevices::dev.flush(), add = TRUE) |
| 98 | 2x |
graphics::plot.new() |
| 99 | ||
| 100 |
## Set plotting coordinates |
|
| 101 | 2x |
years <- time(x, calendar = calendar) |
| 102 | 2x |
xlim <- range(years) |
| 103 | 2x |
ylim <- c(1, n) |
| 104 | 2x |
graphics::plot.window(xlim = xlim, ylim = ylim) |
| 105 | ||
| 106 |
## Evaluate pre-plot expressions |
|
| 107 | 2x |
panel.first |
| 108 | ||
| 109 |
## Order data |
|
| 110 | 2x |
k <- order(years, decreasing = decreasing) |
| 111 | ||
| 112 |
## Plot |
|
| 113 | 2x |
graphics::points(x = years[k], y = n_seq, col = col[k], |
| 114 | 2x |
bg = bg[k], pch = pch[k], cex = cex[k], lwd = lwd[k]) |
| 115 | ||
| 116 |
## Evaluate post-plot and pre-axis expressions |
|
| 117 | 2x |
panel.last |
| 118 | ||
| 119 |
## Construct Axis |
|
| 120 | 2x |
if (axes) {
|
| 121 | 2x |
aion::year_axis(side = 1, format = TRUE, calendar = calendar, |
| 122 | 2x |
current_calendar = calendar, cex.axis = cex.axis, |
| 123 | 2x |
col.axis = col.axis, font.axis = font.axis) |
| 124 | 2x |
graphics::axis(side = 2, at = n_seq, labels = sites[k], |
| 125 | 2x |
xpd = NA, cex.axis = cex.axis, las = 1, |
| 126 | 2x |
col.axis = col.axis, font.axis = font.axis) |
| 127 |
} |
|
| 128 | ||
| 129 |
## Plot frame |
|
| 130 | 2x |
if (frame.plot) {
|
| 131 | 2x |
graphics::box() |
| 132 |
} |
|
| 133 | ||
| 134 |
## Add annotation |
|
| 135 | 2x |
if (ann) {
|
| 136 | 2x |
xlab <- format(calendar) |
| 137 | 2x |
ylab <- NULL |
| 138 | 2x |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = ylab, ...) |
| 139 |
} |
|
| 140 | ||
| 141 | 2x |
invisible(x) |
| 142 |
} |
|
| 143 | ||
| 144 |
#' @export |
|
| 145 |
#' @rdname plot.MeanDate |
|
| 146 |
#' @aliases plot,MeanDate,missing-method |
|
| 147 |
setMethod("plot", c(x = "MeanDate", y = "missing"), plot.MeanDate)
|
|
| 148 | ||
| 149 |
#' @export |
|
| 150 |
#' @method plot SimulationMeanDate |
|
| 151 |
plot.SimulationMeanDate <- function(x, calendar = get_calendar(), |
|
| 152 |
interval = "student", level = 0.80, |
|
| 153 |
decreasing = TRUE, |
|
| 154 |
main = NULL, sub = NULL, |
|
| 155 |
ann = graphics::par("ann"), axes = TRUE,
|
|
| 156 |
frame.plot = axes, |
|
| 157 |
panel.first = NULL, panel.last = NULL, ...) {
|
|
| 158 |
## Get data |
|
| 159 | ! |
n <- NROW(x) |
| 160 | ! |
n_seq <- seq_len(n) |
| 161 | ! |
sites <- rownames(x) %||% paste0("S1", n_seq)
|
| 162 | ||
| 163 |
## Compute confidence interval |
|
| 164 | ! |
fun <- function(x) conf(x, level = level, type = interval) |
| 165 | ! |
inter <- apply(X = x@replications, MARGIN = 1, FUN = fun) |
| 166 | ! |
inter <- apply(X = inter, MARGIN = 1, FUN = as_year, calendar = calendar) |
| 167 | ||
| 168 |
## Graphical parameters |
|
| 169 | ! |
col <- list(...)$col %||% graphics::par("col")
|
| 170 | ! |
bg <- list(...)$bg %||% graphics::par("bg")
|
| 171 | ! |
pch <- list(...)$pch %||% c(16) |
| 172 | ! |
cex <- list(...)$cex %||% graphics::par("cex")
|
| 173 | ! |
lty <- list(...)$lty %||% graphics::par("lty")
|
| 174 | ! |
lwd <- list(...)$lwd %||% graphics::par("lwd")
|
| 175 | ! |
if (length(col) != n) col <- rep(col, length.out = n) |
| 176 | ! |
if (length(bg) != n) bg <- rep(bg, length.out = n) |
| 177 | ! |
if (length(pch) != n) pch <- rep(pch, length.out = n) |
| 178 | ! |
if (length(cex) != n) cex <- rep(cex, length.out = n) |
| 179 | ! |
if (length(lty) != n) lty <- rep(lty, length.out = n) |
| 180 | ! |
if (length(lwd) != n) lwd <- rep(lwd, length.out = n) |
| 181 | ! |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis")
|
| 182 | ! |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis")
|
| 183 | ! |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis")
|
| 184 | ||
| 185 |
## Save and restore |
|
| 186 | ! |
mar <- graphics::par("mar")
|
| 187 | ! |
mar[2] <- inch2line(sites, cex = cex.axis) + 0.5 |
| 188 | ! |
old_par <- graphics::par(mar = mar) |
| 189 | ! |
on.exit(graphics::par(old_par)) |
| 190 | ||
| 191 |
## Open new window |
|
| 192 | ! |
grDevices::dev.hold() |
| 193 | ! |
on.exit(grDevices::dev.flush(), add = TRUE) |
| 194 | ! |
graphics::plot.new() |
| 195 | ||
| 196 |
## Set plotting coordinates |
|
| 197 | ! |
years <- time(x, calendar = calendar) |
| 198 | ! |
xlim <- range(inter) |
| 199 | ! |
ylim <- c(1, n) |
| 200 | ! |
graphics::plot.window(xlim = xlim, ylim = ylim) |
| 201 | ||
| 202 |
## Evaluate pre-plot expressions |
|
| 203 | ! |
panel.first |
| 204 | ||
| 205 |
## Order data |
|
| 206 | ! |
k <- order(years, decreasing = decreasing) |
| 207 | ||
| 208 |
## Plot |
|
| 209 | ! |
graphics::segments(x0 = inter[k, 2], y0 = n_seq, |
| 210 | ! |
x1 = inter[k, 3], y1 = n_seq, |
| 211 | ! |
col = col[k], lty = lty[k], lwd = lwd[k]) |
| 212 | ! |
graphics::points(x = years[k], y = n_seq, col = col[k], |
| 213 | ! |
bg = bg[k], pch = pch[k], cex = cex[k], lwd = lwd[k]) |
| 214 | ||
| 215 |
## Evaluate post-plot and pre-axis expressions |
|
| 216 | ! |
panel.last |
| 217 | ||
| 218 |
## Construct Axis |
|
| 219 | ! |
if (axes) {
|
| 220 | ! |
aion::year_axis(side = 1, format = TRUE, calendar = calendar, |
| 221 | ! |
current_calendar = calendar, cex.axis = cex.axis, |
| 222 | ! |
col.axis = col.axis, font.axis = font.axis) |
| 223 | ! |
graphics::axis(side = 2, at = n_seq, labels = sites[k], |
| 224 | ! |
xpd = NA, cex.axis = cex.axis, las = 1, |
| 225 | ! |
col.axis = col.axis, font.axis = font.axis) |
| 226 |
} |
|
| 227 | ||
| 228 |
## Plot frame |
|
| 229 | ! |
if (frame.plot) {
|
| 230 | ! |
graphics::box() |
| 231 |
} |
|
| 232 | ||
| 233 |
## Add annotation |
|
| 234 | ! |
if (ann) {
|
| 235 |
## Caption |
|
| 236 | ! |
cap <- sprintf(tr_("Simulated assemblages, %d replications."), NCOL(x@replications))
|
| 237 | ! |
xlab <- format(calendar) |
| 238 | ! |
ylab <- NULL |
| 239 | ! |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = ylab, ...) |
| 240 |
} |
|
| 241 | ||
| 242 | ! |
invisible(x) |
| 243 |
} |
|
| 244 | ||
| 245 |
#' @export |
|
| 246 |
#' @rdname plot.MeanDate |
|
| 247 |
#' @aliases plot,SimulationMeanDate,missing-method |
|
| 248 |
setMethod("plot", c(x = "SimulationMeanDate", y = "missing"),
|
|
| 249 |
plot.SimulationMeanDate) |
|
| 250 | ||
| 251 |
conf <- function(x, type = c("percentiles", "student", "normal", "range"),
|
|
| 252 |
level = 0.80) {
|
|
| 253 | ! |
type <- match.arg(type, several.ok = FALSE) |
| 254 | ! |
if (type == "range") {
|
| 255 | ! |
conf <- range(x, na.rm = FALSE) |
| 256 | ! |
} else if (type == "percentiles") {
|
| 257 |
## Confidence interval as described in Kintigh 1989 |
|
| 258 | ! |
k <- (1 - level) / 2 |
| 259 | ! |
conf <- stats::quantile(x, probs = c(k, 1 - k), names = FALSE) |
| 260 |
} else {
|
|
| 261 |
## Confidence interval |
|
| 262 | ! |
conf <- arkhe::confidence_mean(x, level = level, type = type) |
| 263 |
} |
|
| 264 | ||
| 265 | ! |
result <- c(mean(x), conf) |
| 266 | ! |
names(result) <- c("mean", "lower", "upper")
|
| 267 | ! |
result |
| 268 |
} |
| 1 |
# SHOW METHODS |
|
| 2 |
#' @include AllClasses.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# EventDate ==================================================================== |
|
| 6 |
setMethod( |
|
| 7 |
f = "show", |
|
| 8 |
signature = "EventDate", |
|
| 9 |
definition = function(object) {
|
|
| 10 | ! |
show_ca <- utils::capture.output(methods::callNextMethod(object)) |
| 11 | ! |
summary_lm <- summary(object) |
| 12 | ! |
sig <- sigma(object, calendar = get_calendar()) |
| 13 | ||
| 14 | ! |
cat( |
| 15 | ! |
show_ca, |
| 16 |
"", |
|
| 17 | ! |
paste0(tr_("Multiple Linear Regression"), ":"),
|
| 18 | ! |
sprintf(tr_("* R-squared: %s"), round(summary_lm$r.squared, 3)),
|
| 19 | ! |
sprintf(tr_("* Adjusted R-squared: %s"), round(summary_lm$adj.r.squared, 3)),
|
| 20 | ! |
sprintf(tr_("* Residual standard error: %s"), round(sig, 2)),
|
| 21 | ! |
sep = "\n" |
| 22 |
) |
|
| 23 |
} |
|
| 24 |
) |
|
| 25 | ||
| 26 |
# PermutationOrder ============================================================= |
|
| 27 |
setMethod( |
|
| 28 |
f = "show", |
|
| 29 |
signature = "PermutationOrder", |
|
| 30 |
definition = function(object) {
|
|
| 31 | ! |
k <- 50 |
| 32 | ! |
rows <- strtrim(paste0(object@rows_order, collapse = " "), k) |
| 33 | ! |
columns <- strtrim(paste0(object@columns_order, collapse = " "), k) |
| 34 | ! |
cat( |
| 35 | ! |
paste0(tr_("Permutation order for matrix seriation"), ":"),
|
| 36 | ! |
sprintf(tr_("* Row order: %s"), paste0(rows, "...")),
|
| 37 | ! |
sprintf(tr_("* Column order: %s"), paste0(columns, "...")),
|
| 38 | ! |
sep = "\n" |
| 39 |
) |
|
| 40 |
} |
|
| 41 |
) |
|
| 42 | ||
| 43 |
# RefineCA ===================================================================== |
|
| 44 |
setMethod( |
|
| 45 |
f = "show", |
|
| 46 |
signature = "RefinePermutationOrder", |
|
| 47 |
definition = function(object) {
|
|
| 48 | ! |
value <- switch (object@margin, `1` = "Rows", `2` = "Columns") |
| 49 | ! |
keep <- length(object@keep) |
| 50 | ! |
total <- length(object@length) |
| 51 | ! |
pc <- round(keep * 100 / total) |
| 52 | ! |
methods::callNextMethod(object) |
| 53 | ! |
cat( |
| 54 | ! |
paste0("Partial bootstrap refinement", ":"),
|
| 55 | ! |
sprintf("* Cutoff value: %s", round(object@cutoff, digits = 2)),
|
| 56 | ! |
sprintf("* %s to keep: %d of %d (%g%%)", value, keep, total, pc),
|
| 57 | ! |
sep = "\n") |
| 58 |
} |
|
| 59 |
) |
| 1 |
# REFINE MATRIX SERIATION |
|
| 2 |
#' @include AllClasses.R AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @rdname refine |
|
| 7 |
#' @aliases refine,AveragePermutationOrder-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "refine", |
|
| 10 |
signature = c(object = "AveragePermutationOrder"), |
|
| 11 |
definition = function(object, cutoff, margin = 1, axes = 1, n = 30, ...) {
|
|
| 12 |
## Partial bootstrap CA |
|
| 13 |
## /!\ Be careful: AveragePermutationOrder inherits from CA |
|
| 14 | ! |
object <- dimensio::bootstrap(object, n = n) |
| 15 | ! |
methods::callGeneric(object, cutoff = cutoff, margin = margin, axes = axes, ...) |
| 16 |
} |
|
| 17 |
) |
|
| 18 | ||
| 19 |
#' @export |
|
| 20 |
#' @rdname refine |
|
| 21 |
#' @aliases refine,BootstrapCA-method |
|
| 22 |
setMethod( |
|
| 23 |
f = "refine", |
|
| 24 |
signature = c(object = "BootstrapCA"), |
|
| 25 |
definition = function(object, cutoff, margin = 1, axes = 1, ...) {
|
|
| 26 |
## Validation |
|
| 27 | ! |
arkhe::assert_function(cutoff) |
| 28 | ! |
arkhe::assert_length(margin, 1) |
| 29 | ! |
arkhe::assert_length(axes, 1) |
| 30 | ||
| 31 |
## Get data |
|
| 32 | ! |
ca_rep <- dimensio::get_replications(object, margin = margin) |
| 33 | ||
| 34 |
## Compute convex hull |
|
| 35 | ! |
hull <- apply( |
| 36 | ! |
X = ca_rep, |
| 37 | ! |
MARGIN = 1, |
| 38 | ! |
FUN = function(x, axes) compute_chull(t(x), c(1, 2)), |
| 39 | ! |
axes = axes |
| 40 |
) |
|
| 41 | ||
| 42 |
## Get convex hull maximal dimension length for each sample |
|
| 43 | ! |
len <- vapply( |
| 44 | ! |
X = hull, |
| 45 | ! |
FUN = function(x) max(stats::dist(x, method = "euclidean")), |
| 46 | ! |
FUN.VALUE = double(1) |
| 47 |
) |
|
| 48 | ||
| 49 |
## Get cutoff values |
|
| 50 | ! |
limit <- cutoff(len) |
| 51 | ||
| 52 |
## Samples to be excluded |
|
| 53 | ! |
sup <- which(len >= limit) |
| 54 | ||
| 55 | ! |
list( |
| 56 | ! |
length = len, |
| 57 | ! |
cutoff = limit, |
| 58 | ! |
exclude = which(len >= limit), |
| 59 | ! |
margin = as.integer(margin) |
| 60 |
) |
|
| 61 |
} |
|
| 62 |
) |
|
| 63 | ||
| 64 |
#' Convex Hull of CA Coordinates |
|
| 65 |
#' |
|
| 66 |
#' Compute convex hull area for each replicated sample |
|
| 67 |
#' @param x A [`numeric`] matrix of bootstrap replicates. |
|
| 68 |
#' @param axes A length-two [`numeric`] vector giving the subscripts |
|
| 69 |
#' of the CA components to use. |
|
| 70 |
#' @return A [`matrix`]. |
|
| 71 |
#' @author N. Frerebeau |
|
| 72 |
#' @keywords internal |
|
| 73 |
#' @noRd |
|
| 74 |
compute_chull <- function(x, axes) {
|
|
| 75 |
# Remove missing values |
|
| 76 | ! |
clean <- stats::na.omit(x[, axes]) |
| 77 |
# Get convex hull coordinates |
|
| 78 | ! |
points <- grDevices::chull(clean) |
| 79 |
# Repeat first point |
|
| 80 | ! |
hull <- clean[c(points, points[1]), axes] |
| 81 | ! |
colnames(hull) <- c("x", "y")
|
| 82 | ||
| 83 | ! |
return(hull) |
| 84 |
} |
| 1 |
# COERCE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# To data.frame ================================================================ |
|
| 6 |
#' @export |
|
| 7 |
#' @method as.data.frame MeanDate |
|
| 8 |
as.data.frame.MeanDate <- function(x, ..., calendar = get_calendar()) {
|
|
| 9 | 1x |
data.frame( |
| 10 | 1x |
sample = rownames(x) %||% paste0("S", seq_len(nrow(x))),
|
| 11 | 1x |
time = aion::time(x, calendar = calendar) |
| 12 |
) |
|
| 13 |
} |
|
| 14 | ||
| 15 |
#' @export |
|
| 16 |
#' @rdname data.frame |
|
| 17 |
#' @aliases as.data.frame,MeanDate-method |
|
| 18 |
setMethod("as.data.frame", "MeanDate", as.data.frame.MeanDate)
|
|
| 19 | ||
| 20 |
#' @export |
|
| 21 |
#' @method as.data.frame AoristicSum |
|
| 22 |
as.data.frame.AoristicSum <- function(x, ..., calendar = get_calendar()) {
|
|
| 23 | 1x |
block_start <- utils::head(x@breaks, -1) |
| 24 | 1x |
block_end <- utils::tail(x@breaks, -1) |
| 25 | ||
| 26 | 1x |
aorist <- x[, , 1, drop = TRUE] |
| 27 | 1x |
dim(aorist) <- c(nrow(x), ncol(x)) |
| 28 | 1x |
colnames(aorist) <- colnames(x) %||% paste0("S", seq_len(ncol(x)))
|
| 29 | ||
| 30 | 1x |
data.frame( |
| 31 | 1x |
start = aion::as_year(block_start, calendar = calendar), |
| 32 | 1x |
end = aion::as_year(block_end, calendar = calendar), |
| 33 | 1x |
aorist |
| 34 |
) |
|
| 35 |
} |
|
| 36 | ||
| 37 |
#' @export |
|
| 38 |
#' @rdname data.frame |
|
| 39 |
#' @aliases as.data.frame,AoristicSum-method |
|
| 40 |
setMethod("as.data.frame", "AoristicSum", as.data.frame.AoristicSum)
|
|
| 41 | ||
| 42 |
#' @method as.data.frame IncrementTest |
|
| 43 |
#' @export |
|
| 44 |
as.data.frame.IncrementTest <- function(x, row.names = NULL, optional = FALSE, ...) {
|
|
| 45 | 1x |
data.frame( |
| 46 | 1x |
t = x@statistic, |
| 47 | 1x |
p.value = x@p_value, |
| 48 | 1x |
row.names = colnames(x), |
| 49 |
... |
|
| 50 |
) |
|
| 51 |
} |
|
| 52 | ||
| 53 |
#' @export |
|
| 54 |
#' @rdname data.frame |
|
| 55 |
#' @aliases as.data.frame,IncrementTest-method |
|
| 56 |
setMethod("as.data.frame", "IncrementTest", as.data.frame.IncrementTest)
|
| 1 |
# CHRONOLOGICAL APPORTIONING |
|
| 2 |
#' @include AllGenerics.R AllClasses.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @rdname apportion |
|
| 7 |
#' @aliases apportion,data.frame-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "apportion", |
|
| 10 |
signature = c(object = "data.frame"), |
|
| 11 |
definition = function(object, s0, s1, t0, t1, from = min(s0), to = max(s1), |
|
| 12 |
step = 25, method = c("uniform", "truncated"), z = 2,
|
|
| 13 |
progress = getOption("kairos.progress")) {
|
|
| 14 | ! |
object <- data.matrix(object) |
| 15 | ! |
methods::callGeneric(object, s0, s1, t0, t1, from = from, to = to, |
| 16 | ! |
step = step, method = method, z = z, |
| 17 | ! |
progress = progress) |
| 18 |
} |
|
| 19 |
) |
|
| 20 | ||
| 21 |
#' @export |
|
| 22 |
#' @rdname apportion |
|
| 23 |
#' @aliases apportion,matrix-method |
|
| 24 |
setMethod( |
|
| 25 |
f = "apportion", |
|
| 26 |
signature = c(object = "matrix"), |
|
| 27 |
definition = function(object, s0, s1, t0, t1, from = min(s0), to = max(s1), |
|
| 28 |
step = 25, method = c("uniform", "truncated"), z = 2,
|
|
| 29 |
progress = getOption("kairos.progress")) {
|
|
| 30 |
## Validation |
|
| 31 | 2x |
method <- match.arg(method, several.ok = FALSE) |
| 32 | 2x |
arkhe::assert_lower(s0, s1, strict = FALSE) |
| 33 | 2x |
arkhe::assert_lower(t0, t1, strict = FALSE) |
| 34 | 2x |
arkhe::assert_lower(from, to, strict = TRUE) |
| 35 | ||
| 36 |
## Get data |
|
| 37 | 2x |
n_site <- nrow(object) |
| 38 | 2x |
n_type <- ncol(object) |
| 39 | 2x |
span <- to - from |
| 40 | ||
| 41 |
## Number of periods (rounded toward the smallest integer) |
|
| 42 | 2x |
n_periode <- ceiling(span / step) |
| 43 | 2x |
t <- seq_len(n_periode) |
| 44 | 2x |
periode <- paste(from + (t - 1) * step, from + t * step, sep = "_") |
| 45 | ||
| 46 |
## Empty array to store apportioning probabilities |
|
| 47 | 2x |
p <- array(data = NA_real_, dim = c(nrow(object), ncol(object), n_periode)) |
| 48 | 2x |
dimnames(p) <- c(dimnames(object), list(periode)) |
| 49 | 2x |
a <- p |
| 50 | ||
| 51 |
## Round the site dates to be multiples of the step size |
|
| 52 |
## (rounded toward the smallest/largest multiple) |
|
| 53 | 2x |
s0[s0 %% step != 0] <- floor(s0[s0 %% step != 0] / step) * step |
| 54 | 2x |
s1[s1 %% step != 0] <- ceiling(s1[s1 %% step != 0] / step) * step |
| 55 | ||
| 56 |
## Type midpoints and life spans |
|
| 57 | 2x |
m <- (t1 + t0) / 2 |
| 58 | 2x |
g <- t1 - t0 |
| 59 | ||
| 60 |
## Distribution function |
|
| 61 | 2x |
fun <- switch ( |
| 62 | 2x |
method, |
| 63 | 2x |
uniform = dist_uniform, |
| 64 | 2x |
truncated = dist_truncated |
| 65 |
) |
|
| 66 | ||
| 67 |
## Apportion |
|
| 68 | 2x |
k_site <- seq_len(n_site) |
| 69 | 2x |
k_type <- seq_len(n_type) |
| 70 | ||
| 71 | 2x |
progress_bar <- interactive() && isTRUE(progress) |
| 72 | ! |
if (progress_bar) pbar <- utils::txtProgressBar(max = n_site, style = 3) |
| 73 | ||
| 74 | 2x |
for (i in k_site) {
|
| 75 | 2x |
for (j in k_type) {
|
| 76 |
## If the type lies outside the known site occupation or study interval |
|
| 77 | ! |
if (t1[j] <= s0[i] | t0[j] >= s1[i]) next # Do not apportion |
| 78 | ||
| 79 |
## Earliest and latest overlaps between the ware and site |
|
| 80 | 18x |
vj0 <- max(s0[i], t0[j]) |
| 81 | 18x |
vj1 <- min(s1[i], t1[j]) |
| 82 | ||
| 83 |
## Get the apportioning probability for any period |
|
| 84 | 18x |
qjt0 <- vapply(X = s0[i] + (t - 1) * step, FUN = max, |
| 85 | 18x |
FUN.VALUE = numeric(1), t0[j]) |
| 86 | 18x |
qjt1 <- vapply(X = s0[i] + t * step, FUN = min, |
| 87 | 18x |
FUN.VALUE = numeric(1), t1[j]) |
| 88 | ||
| 89 | 18x |
p[i, j, ] <- fun(vj0, vj1, qjt0, qjt1, g[j], m[j], z) |
| 90 |
} |
|
| 91 | ||
| 92 | ! |
if (progress_bar) utils::setTxtProgressBar(pbar, i) |
| 93 |
} |
|
| 94 | ||
| 95 | ! |
if (progress_bar) close(pbar) |
| 96 | ||
| 97 |
## Remove negative values |
|
| 98 | 2x |
p[p < 0] <- 0 |
| 99 | ||
| 100 |
## Apportion |
|
| 101 | 2x |
a[] <- apply(X = p, MARGIN = 3, FUN = function(x, counts) x * counts, |
| 102 | 2x |
counts = object) |
| 103 | ||
| 104 | 2x |
.CountApportion( |
| 105 | 2x |
a, |
| 106 | 2x |
p = p, |
| 107 | 2x |
method = method, |
| 108 | 2x |
from = from, |
| 109 | 2x |
to = to, |
| 110 | 2x |
step = step |
| 111 |
) |
|
| 112 |
} |
|
| 113 |
) |
|
| 114 | ||
| 115 |
dist_uniform <- function(v_j0, v_j1, q_jt0, q_jt1, ...) {
|
|
| 116 | 9x |
(q_jt1 - q_jt0) / (v_j1 - v_j0) |
| 117 |
} |
|
| 118 |
dist_truncated <- function(v_j0, v_j1, q_jt0, q_jt1, g, m, z) {
|
|
| 119 | 9x |
z_j0 <- (v_j0 - m) / (g / (2 * z)) |
| 120 | 9x |
z_j1 <- (v_j1 - m) / (g / (2 * z)) |
| 121 | ||
| 122 | 9x |
z_jt0 <- (q_jt0 - m) / (g / (2 * z)) |
| 123 | 9x |
z_jt1 <- (q_jt1 - m) / (g / (2 * z)) |
| 124 | ||
| 125 | 9x |
(phi(z_jt1, z) - phi(z_jt0, z)) / (phi(z_j1, z) - phi(z_j0, z)) |
| 126 |
} |
|
| 127 |
phi <- function(x, z) {
|
|
| 128 | 36x |
extraDistr::ptnorm(x, mean = 0, sd = 1, a = -z, b = z) |
| 129 |
} |
| 1 |
# FREQUENCY INCREMENT TEST |
|
| 2 |
#' @include AllGenerics.R AllClasses.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# FIT ========================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname fit |
|
| 8 |
#' @aliases fit,data.frame,numeric-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "fit", |
|
| 11 |
signature = c(object = "data.frame", dates = "numeric"), |
|
| 12 |
definition = function(object, dates, calendar = CE(), |
|
| 13 |
level = 0.95, roll = FALSE, window = 3) {
|
|
| 14 | 2x |
object <- data.matrix(object) |
| 15 | 2x |
methods::callGeneric(object, dates = dates, calendar = calendar, |
| 16 | 2x |
level = level, roll = roll, window = window) |
| 17 |
} |
|
| 18 |
) |
|
| 19 | ||
| 20 |
#' @export |
|
| 21 |
#' @rdname fit |
|
| 22 |
#' @aliases fit,matrix,numeric-method |
|
| 23 |
setMethod( |
|
| 24 |
f = "fit", |
|
| 25 |
signature = c(object = "matrix", dates = "numeric"), |
|
| 26 |
definition = function(object, dates, calendar = CE(), |
|
| 27 |
level = 0.95, roll = FALSE, window = 3) {
|
|
| 28 |
## Validation |
|
| 29 | 2x |
alpha <- 1 - level |
| 30 | 2x |
half_window <- (window - 1) / 2 |
| 31 | 2x |
arkhe::assert_length(dates, nrow(object)) |
| 32 | ||
| 33 |
## Convert to rata die |
|
| 34 | 2x |
if (is.null(calendar)) {
|
| 35 | 2x |
dates <- aion::as_fixed(dates) |
| 36 |
} else {
|
|
| 37 | ! |
dates <- aion::fixed(dates, calendar = calendar) |
| 38 |
} |
|
| 39 | ||
| 40 |
## Compute test |
|
| 41 | 2x |
results <- test_FIT(object, dates, roll = FALSE) |
| 42 | 2x |
results <- results[[1L]] |
| 43 | ||
| 44 |
## Check results |
|
| 45 | 2x |
failed <- is.na(results$p.value) |
| 46 | 2x |
if (any(failed)) {
|
| 47 | ! |
txt <- ngettext(sum(failed), "%d element was skipped: %s.", |
| 48 | ! |
"%d elements were skipped: %s.") |
| 49 | ! |
msg <- sprintf(txt, sum(failed), |
| 50 | ! |
paste0(rownames(results)[failed], collapse = ", ")) |
| 51 | ! |
warning(msg, call. = FALSE) |
| 52 |
} |
|
| 53 | ||
| 54 |
## Rolling window |
|
| 55 | 2x |
fit_roll <- matrix(FALSE, nrow = nrow(object), ncol = ncol(object)) |
| 56 | 2x |
if (roll) {
|
| 57 | 1x |
results_roll <- test_FIT(object, dates, roll = roll, window = window) |
| 58 | 1x |
results_roll <- lapply( |
| 59 | 1x |
X = results_roll, |
| 60 | 4x |
FUN = function(x, alpha) { x$p.value <= alpha },
|
| 61 | 1x |
alpha = alpha |
| 62 |
) |
|
| 63 | 1x |
fit_row <- seq(from = half_window + 1, to = nrow(fit_roll) - half_window) |
| 64 | 1x |
fit_roll[fit_row, ] <- do.call(rbind, results_roll) |
| 65 | ||
| 66 | 1x |
fit_roll <- apply( |
| 67 | 1x |
X = fit_roll, |
| 68 | 1x |
MARGIN = 2, |
| 69 | 1x |
FUN = function(x, half_window) {
|
| 70 | 9x |
vapply( |
| 71 | 9x |
X = seq_along(x), |
| 72 | 9x |
FUN = function(x, y, k) {
|
| 73 | 72x |
max <- length(y) |
| 74 | 72x |
lower <- x - k |
| 75 | 72x |
lower[lower < 1] <- 1 |
| 76 | 72x |
upper <- x + k |
| 77 | 72x |
upper[upper > max] <- max |
| 78 | 72x |
any(y[lower:upper], na.rm = TRUE) |
| 79 |
}, |
|
| 80 | 9x |
FUN.VALUE = logical(1), |
| 81 | 9x |
y = x, |
| 82 | 9x |
k = half_window |
| 83 |
) |
|
| 84 |
}, |
|
| 85 | 1x |
half_window = half_window |
| 86 |
) |
|
| 87 |
} |
|
| 88 | ||
| 89 |
## Build array |
|
| 90 | 2x |
select <- results$p.value <= alpha |
| 91 | 2x |
x <- y <- z <- object |
| 92 | 2x |
x[, !select] <- NA |
| 93 | 2x |
y[, select] <- NA |
| 94 | 2x |
z[!fit_roll] <- NA |
| 95 | ||
| 96 | 2x |
res <- array( |
| 97 | 2x |
data = c(z, x, y), |
| 98 | 2x |
dim = c(dim(object), 3), |
| 99 | 2x |
dimnames = c(dimnames(object), list(c("roll", "selection", "neutral")))
|
| 100 |
) |
|
| 101 | ||
| 102 | 2x |
ts <- aion::series(object = res, time = dates) |
| 103 | 2x |
.IncrementTest( |
| 104 | 2x |
ts, |
| 105 | 2x |
statistic = results$t, |
| 106 | 2x |
parameter = 1L, |
| 107 | 2x |
p_value = results$p.value |
| 108 |
) |
|
| 109 |
} |
|
| 110 |
) |
|
| 111 | ||
| 112 |
#' @param x A \eqn{m x p} [`numeric`] matrix.
|
|
| 113 |
#' @param time A length-\eqn{m} [`numeric`] vector.
|
|
| 114 |
#' @param roll A [`logical`] scalar. |
|
| 115 |
#' @param window An [`integer`]. |
|
| 116 |
#' @return A list of \eqn{p x 3} [`data.frame`].
|
|
| 117 |
#' @author N. Frerebeau |
|
| 118 |
#' @keywords internal |
|
| 119 |
#' @noRd |
|
| 120 |
test_FIT <- function(x, time, roll = FALSE, window = 3, ...) {
|
|
| 121 |
## Prepare data |
|
| 122 | 3x |
time <- as.numeric(time) |
| 123 | ||
| 124 |
## Compute frequency as ratio of count of type of interest to all other types |
|
| 125 | 3x |
count_others <- lapply( |
| 126 | 3x |
X = seq_len(ncol(x)), |
| 127 | 27x |
FUN = function(i, data) { rowSums(data[, -i]) },
|
| 128 | 3x |
data = x |
| 129 |
) |
|
| 130 | 3x |
freq <- x / do.call(cbind, count_others) |
| 131 | ||
| 132 |
## Compute test |
|
| 133 | 3x |
if (!roll) {
|
| 134 | 2x |
roll_list <- list(seq_len(nrow(freq))) |
| 135 |
} else {
|
|
| 136 | 1x |
roll_index <- roll(freq, window = window) |
| 137 | 1x |
roll_list <- split(x = roll_index[["i"]], f = roll_index[["w"]]) |
| 138 |
} |
|
| 139 | ||
| 140 | 3x |
k <- 1 |
| 141 | 3x |
results <- vector(mode = "list", length = length(roll_list)) |
| 142 | 3x |
for (i in roll_list) {
|
| 143 | 6x |
roll_freq <- freq[i, ] |
| 144 | 6x |
roll_time <- time[i] |
| 145 | 6x |
roll_date <- roll_time[ceiling(window / 2)] |
| 146 | ||
| 147 | 6x |
fit <- apply( |
| 148 | 6x |
X = roll_freq, |
| 149 | 6x |
MARGIN = 2, |
| 150 | 6x |
FUN = function(v, t, ...) {
|
| 151 | 54x |
tryCatch( |
| 152 | 54x |
error = function(cnd) c(t = NA, p.value = NA), |
| 153 | 54x |
{ FIT(v, t, ...) }
|
| 154 |
) |
|
| 155 |
}, |
|
| 156 | 6x |
t = roll_time, |
| 157 |
... |
|
| 158 |
) |
|
| 159 | ||
| 160 | 6x |
results[[k]] <- data.frame( |
| 161 | 6x |
column = colnames(fit), |
| 162 | 6x |
time = roll_date, |
| 163 | 6x |
t(fit), |
| 164 | 6x |
row.names = NULL |
| 165 |
) |
|
| 166 | 6x |
k <- k + 1 |
| 167 |
} |
|
| 168 | ||
| 169 | 3x |
return(results) |
| 170 |
} |
|
| 171 | ||
| 172 |
#' Frequency Increment Test (FIT) |
|
| 173 |
#' |
|
| 174 |
#' @param v A [`numeric`] vector of frequencies. |
|
| 175 |
#' @param t A [`numeric`] vector of time coordinates. |
|
| 176 |
#' @param ... Extra parameter passed to [stats::t.test()]. |
|
| 177 |
#' @return A [`numeric`] vector containing the following components: |
|
| 178 |
#' \describe{
|
|
| 179 |
#' \item{`t`}{the value of the test statistic.}
|
|
| 180 |
#' \item{`p.value`}{the p-value for the test.}
|
|
| 181 |
#' } |
|
| 182 |
#' @author N. Frerebeau |
|
| 183 |
#' @references |
|
| 184 |
#' Feder, A. F., Kryazhimskiy, S. & Plotkin, J. B. (2014). Identifying |
|
| 185 |
#' Signatures of Selection in Genetic Time Series. *Genetics*, 196(2), |
|
| 186 |
#' 509-522. \doi{10.1534/genetics.113.158220}.
|
|
| 187 |
#' @keywords internal |
|
| 188 |
#' @noRd |
|
| 189 |
FIT <- function(v, t, ...) {
|
|
| 190 |
## Validation |
|
| 191 | 54x |
arkhe::assert_type(v, "numeric") |
| 192 | 54x |
arkhe::assert_type(t, "numeric") |
| 193 | 54x |
arkhe::assert_length(t, length(v)) |
| 194 | ||
| 195 |
## Remove zeros |
|
| 196 | 54x |
index <- v > 0 |
| 197 | 54x |
v <- v[index] |
| 198 | 54x |
t <- t[index] |
| 199 | 54x |
if (length(t) < 3) {
|
| 200 | ! |
stop(tr_("A minimum of three time points is needed."), call. = FALSE)
|
| 201 |
} |
|
| 202 | ||
| 203 |
## Rescaled allele-frequency increments |
|
| 204 | 54x |
Y <- diff(v, lag = 1) / |
| 205 | 54x |
sqrt(2 * utils::head(v, -1) * (1 - utils::head(v, -1)) * diff(t, lag = 1)) |
| 206 | ||
| 207 |
## Statistics |
|
| 208 | 54x |
t_test <- stats::t.test(Y, ...) |
| 209 | 54x |
c(t = as.numeric(t_test$statistic), p.value = t_test$p.value) |
| 210 |
} |
|
| 211 | ||
| 212 |
# Plot ========================================================================= |
|
| 213 |
#' @export |
|
| 214 |
#' @method plot IncrementTest |
|
| 215 |
plot.IncrementTest <- function(x, calendar = get_calendar(), |
|
| 216 |
col.neutral = "#004488", col.selection = "#BB5566", |
|
| 217 |
col.roll = "grey", flip = FALSE, ncol = NULL, |
|
| 218 |
xlab = NULL, ylab = NULL, |
|
| 219 |
main = NULL, sub = NULL, |
|
| 220 |
ann = graphics::par("ann"), axes = TRUE,
|
|
| 221 |
frame.plot = axes, ...) {
|
|
| 222 |
## Panel |
|
| 223 | 2x |
panel_fit <- function(x, y, ...) {
|
| 224 | 54x |
graphics::lines(x, y, ...) |
| 225 | 54x |
graphics::points(x, y, ...) |
| 226 |
} |
|
| 227 | ||
| 228 |
## Method for TimeSeries |
|
| 229 | 2x |
methods::callNextMethod(x = x, calendar = calendar, panel = panel_fit, |
| 230 | 2x |
flip = flip, ncol = ncol, |
| 231 | 2x |
xlab = xlab, ylab = ylab, |
| 232 | 2x |
main = main, sub = sub, |
| 233 | 2x |
ann = ann, axes = axes, |
| 234 | 2x |
frame.plot = frame.plot, |
| 235 | 2x |
col = c(col.roll, col.selection, col.neutral), |
| 236 | 2x |
lwd = c(10, 1, 1), pch = 16, cex = 1, ...) |
| 237 |
} |
|
| 238 | ||
| 239 |
#' @export |
|
| 240 |
#' @rdname plot.IncrementTest |
|
| 241 |
#' @aliases plot,IncrementTest,missing-method |
|
| 242 |
setMethod("plot", c(x = "IncrementTest", y = "missing"), plot.IncrementTest)
|
| 1 |
# GENERIC METHODS |
|
| 2 |
#' @include AllClasses.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Import S4 generics =========================================================== |
|
| 6 |
#' @importMethodsFrom arkhe jackknife |
|
| 7 |
#' @importMethodsFrom arkhe bootstrap |
|
| 8 |
NULL |
|
| 9 | ||
| 10 |
# Mutators ===================================================================== |
|
| 11 |
## Subset ---------------------------------------------------------------------- |
|
| 12 |
#' Extract or Replace Parts of an Object |
|
| 13 |
#' |
|
| 14 |
#' Operators acting on objects to extract or replace parts. |
|
| 15 |
#' @param x An object from which to extract element(s) or in which to replace |
|
| 16 |
#' element(s). |
|
| 17 |
#' @param i,j,k Indices specifying elements to extract or replace. |
|
| 18 |
#' @param drop A [`logical`] scalar: should the result be coerced to |
|
| 19 |
#' the lowest possible dimension? This only works for extracting elements, |
|
| 20 |
#' not for the replacement. |
|
| 21 |
# @param value A possible value for the element(s) of `x`. |
|
| 22 |
# @param ... Currently not used. |
|
| 23 |
#' @return |
|
| 24 |
#' A subsetted object. |
|
| 25 |
# @example inst/examples/ex-subset.R |
|
| 26 |
#' @author N. Frerebeau |
|
| 27 |
#' @docType methods |
|
| 28 |
#' @family mutators |
|
| 29 |
#' @name subset |
|
| 30 |
#' @rdname subset |
|
| 31 |
NULL |
|
| 32 | ||
| 33 |
## Extract --------------------------------------------------------------------- |
|
| 34 |
#' Get or Set Parts of an Object |
|
| 35 |
#' |
|
| 36 |
#' Getters and setters to retrieve or set parts of an object. |
|
| 37 |
#' @param object An object from which to get or set element(s). |
|
| 38 |
# @param value A possible value for the element(s) of `x`. |
|
| 39 |
#' @param ... Currently not used. |
|
| 40 |
# @return |
|
| 41 |
# * `set_*()` returns an object of the same sort as `x` with the new values |
|
| 42 |
# assigned. |
|
| 43 |
# * `get_*()` returns the part of `x`. |
|
| 44 |
# @example inst/examples/ex-mutators.R |
|
| 45 |
#' @author N. Frerebeau |
|
| 46 |
#' @docType methods |
|
| 47 |
#' @family mutators |
|
| 48 |
#' @name mutators |
|
| 49 |
#' @rdname mutators |
|
| 50 |
#' @aliases get set |
|
| 51 |
NULL |
|
| 52 | ||
| 53 |
## Time series ----------------------------------------------------------------- |
|
| 54 |
#' Sampling Times |
|
| 55 |
#' |
|
| 56 |
#' Get the times at which a time series was sampled. |
|
| 57 |
#' @param x An \R object. |
|
| 58 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 59 |
#' calendar (see [aion::calendar()]). If `NULL` (the default), *rata die* are |
|
| 60 |
#' returned. |
|
| 61 |
#' @return |
|
| 62 |
#' A [`numeric`] vector. |
|
| 63 |
#' @author N. Frerebeau |
|
| 64 |
#' @docType methods |
|
| 65 |
#' @family mutators |
|
| 66 |
#' @name series |
|
| 67 |
#' @rdname series |
|
| 68 |
NULL |
|
| 69 | ||
| 70 |
## Coerce ---------------------------------------------------------------------- |
|
| 71 |
#' Coerce to a Data Frame |
|
| 72 |
#' |
|
| 73 |
#' @param x An object. |
|
| 74 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 75 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
| 76 |
#' @param row.names,optional Currently not used. |
|
| 77 |
#' @param ... Further parameters to be passed to [data.frame()]. |
|
| 78 |
#' @return |
|
| 79 |
#' A [`data.frame`] with an extra `time` column giving the (decimal) years at |
|
| 80 |
#' which the time series was sampled. |
|
| 81 |
#' @author N. Frerebeau |
|
| 82 |
#' @docType methods |
|
| 83 |
#' @family mutators |
|
| 84 |
#' @name data.frame |
|
| 85 |
#' @rdname data.frame |
|
| 86 |
NULL |
|
| 87 | ||
| 88 |
# Mean Ceramic Dates =========================================================== |
|
| 89 |
#' Mean Ceramic Date |
|
| 90 |
#' |
|
| 91 |
#' Estimates the Mean Ceramic Date of an assemblage. |
|
| 92 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 93 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 94 |
#' individuals for each category, i.e. a contingency table). A [`data.frame`] |
|
| 95 |
#' will be coerced to a `numeric` `matrix` via [data.matrix()]. |
|
| 96 |
#' @param dates A length-\eqn{p} [`numeric`] vector of dates expressed in years.
|
|
| 97 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the calendar |
|
| 98 |
#' of `dates` (see [aion::calendar()]). Defaults to Gregorian Common Era. |
|
| 99 |
#' @param ... Currently not used. |
|
| 100 |
#' @details |
|
| 101 |
#' The Mean Ceramic Date (MCD) is a point estimate of the occupation of an |
|
| 102 |
#' archaeological site (South 1977). The MCD is estimated as the weighted mean |
|
| 103 |
#' of the date midpoints of the ceramic types (based on absolute dates or the |
|
| 104 |
#' known production interval) found in a given assemblage. The weights are the |
|
| 105 |
#' relative frequencies of the respective types in the assemblage. |
|
| 106 |
#' @return |
|
| 107 |
#' A [`MeanDate-class`] object. |
|
| 108 |
#' @seealso [`plot()`][plot.MeanDate], [`bootstrap()`][bootstrap.MeanDate], |
|
| 109 |
#' [`jackknife()`][jackknife.MeanDate] |
|
| 110 |
#' @references |
|
| 111 |
#' South, S. A. (1977). *Method and Theory in Historical Archaeology*. |
|
| 112 |
#' New York: Academic Press. |
|
| 113 |
#' @example inst/examples/ex-mcd.R |
|
| 114 |
#' @author N. Frerebeau |
|
| 115 |
#' @family mean ceramic date tools |
|
| 116 |
#' @family dating methods |
|
| 117 |
#' @docType methods |
|
| 118 |
#' @rdname mcd |
|
| 119 |
#' @aliases mcd-method |
|
| 120 |
setGeneric( |
|
| 121 |
name = "mcd", |
|
| 122 | 4x |
def = function(object, dates, ...) standardGeneric("mcd")
|
| 123 |
) |
|
| 124 | ||
| 125 |
# Event Dates ================================================================== |
|
| 126 |
#' Event and Accumulation Dates |
|
| 127 |
#' |
|
| 128 |
#' Fits a date event model. |
|
| 129 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 130 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 131 |
#' individuals for each category, i.e. a contingency table). A [`data.frame`] |
|
| 132 |
#' will be coerced to a `numeric` `matrix` via [data.matrix()]. |
|
| 133 |
#' @param dates A [`numeric`] vector of dates. If named, the names must match |
|
| 134 |
#' the row names of `object`. |
|
| 135 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the calendar |
|
| 136 |
#' of `dates` (see [aion::calendar()]). Defaults to Gregorian Common Era. |
|
| 137 |
#' @param rank An [`integer`] specifying the number of CA factorial components |
|
| 138 |
#' to be use for linear model fitting (see details). If `NULL` (the default), |
|
| 139 |
#' axes corresponding to at least 60% of the inertia will be used. |
|
| 140 |
#' @param sup_row A [`numeric`] or [`logical`] vector specifying the indices of |
|
| 141 |
#' the supplementary rows. |
|
| 142 |
#' @param total A length-one [`numeric`] vector specifying the minimum total of |
|
| 143 |
#' a row/column. Rows/columns whose total is less than this value will be |
|
| 144 |
#' omitted from the analysis. |
|
| 145 |
#' @param verbose A [`logical`] scalar: should \R report extra information |
|
| 146 |
#' on progress? |
|
| 147 |
#' @param ... Further arguments to be passed to internal methods. |
|
| 148 |
#' @details |
|
| 149 |
#' This is an implementation of the chronological modeling method proposed by |
|
| 150 |
#' Bellanger and Husi (2012, 2013). |
|
| 151 |
#' |
|
| 152 |
#' Event and accumulation dates are density estimates of the occupation and |
|
| 153 |
#' duration of an archaeological site (Bellanger and Husi 2012, 2013). |
|
| 154 |
#' The event date is an estimation of the *terminus post-quem* of an |
|
| 155 |
#' archaeological assemblage. The accumulation date represents the |
|
| 156 |
#' "chronological profile" of the assemblage. According to Bellanger and Husi |
|
| 157 |
#' (2012), accumulation date can be interpreted "at best \[...\] as a formation |
|
| 158 |
#' process reflecting the duration or succession of events on the scale of |
|
| 159 |
#' archaeological time, and at worst, as imprecise dating due to contamination |
|
| 160 |
#' of the context by residual or intrusive material." In other words, |
|
| 161 |
#' accumulation dates estimate occurrence of archaeological events and rhythms |
|
| 162 |
#' of the long term. |
|
| 163 |
#' |
|
| 164 |
#' Dates are converted to *[rata die][aion::RataDie-class]* before any |
|
| 165 |
#' computation. |
|
| 166 |
#' |
|
| 167 |
#' This method relies on strong archaeological and statistical assumptions |
|
| 168 |
#' (see `vignette("event")`).
|
|
| 169 |
#' @return |
|
| 170 |
#' An [`EventDate-class`] object. |
|
| 171 |
#' @seealso [`plot()`][plot.EventDate], [`bootstrap()`][bootstrap.EventDate], |
|
| 172 |
#' [`jackknife()`][jackknife.EventDate] |
|
| 173 |
#' @references |
|
| 174 |
#' Bellanger, L. & Husi, P. (2013). Mesurer et modéliser le temps inscrit dans |
|
| 175 |
#' la matière à partir d'une source matérielle : la céramique médiévale. |
|
| 176 |
#' In *Mesure et Histoire Médiévale*. Histoire ancienne et médiévale. |
|
| 177 |
#' Paris: Publication de la Sorbonne, p. 119-134. |
|
| 178 |
#' |
|
| 179 |
#' Bellanger, L. & Husi, P. (2012). Statistical Tool for Dating and |
|
| 180 |
#' Interpreting Archaeological Contexts Using Pottery. *Journal of |
|
| 181 |
#' Archaeological Science*, 39(4), 777-790. \doi{10.1016/j.jas.2011.06.031}.
|
|
| 182 |
#' |
|
| 183 |
#' Bellanger, L., Tomassone, R. & Husi, P. (2008). A Statistical Approach for |
|
| 184 |
#' Dating Archaeological Contexts. *Journal of Data Science*, 6, 135-154. |
|
| 185 |
#' |
|
| 186 |
#' Bellanger, L., Husi, P. & Tomassone, R. (2006). Une approche statistique |
|
| 187 |
#' pour la datation de contextes archéologiques. *Revue de Statistique |
|
| 188 |
#' Appliquée*, 54(2), 65-81. |
|
| 189 |
#' |
|
| 190 |
#' Bellanger, L., Husi, P. & Tomassone, R. (2006). Statistical Aspects of |
|
| 191 |
#' Pottery Quantification for the Dating of Some Archaeological Contexts. |
|
| 192 |
#' *Archaeometry*, 48(1), 169-183. \doi{10.1111/j.1475-4754.2006.00249.x}.
|
|
| 193 |
#' |
|
| 194 |
#' Poblome, J. & Groenen, P. J. F. (2003). Constrained Correspondence Analysis |
|
| 195 |
#' for Seriation of Sagalassos Tablewares. In Doerr, M. & Apostolis, S. (eds.), |
|
| 196 |
#' *The Digital Heritage of Archaeology*. Athens: Hellenic Ministry of Culture. |
|
| 197 |
#' @example inst/examples/ex-event.R |
|
| 198 |
#' @author N. Frerebeau |
|
| 199 |
#' @family event date tools |
|
| 200 |
#' @family dating methods |
|
| 201 |
#' @docType methods |
|
| 202 |
#' @aliases event-method |
|
| 203 |
setGeneric( |
|
| 204 |
name = "event", |
|
| 205 |
def = function(object, dates, ...) standardGeneric("event"),
|
|
| 206 |
valueClass = "EventDate" |
|
| 207 |
) |
|
| 208 | ||
| 209 |
#' Predict Event and Accumulation Dates |
|
| 210 |
#' |
|
| 211 |
#' Estimates the event and accumulation dates of an assemblage. |
|
| 212 |
#' @param object An [`EventDate-class`] object. |
|
| 213 |
#' @param data A `numeric` [`matrix`] or a [`data.frame`] of count data |
|
| 214 |
#' (absolute frequencies) for which to predict event and accumulation dates. |
|
| 215 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 216 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
| 217 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 218 |
#' @param margin A [`numeric`] vector giving the subscripts which the prediction |
|
| 219 |
#' will be applied over: `1` indicates rows, `2` indicates columns. |
|
| 220 |
#' @param ... Further arguments to be passed to internal methods. |
|
| 221 |
#' @return |
|
| 222 |
#' A [`data.frame`]. |
|
| 223 |
#' @references |
|
| 224 |
#' Bellanger, L. & Husi, P. (2013). Mesurer et modéliser le temps inscrit dans |
|
| 225 |
#' la matière à partir d'une source matérielle : la céramique médiévale. |
|
| 226 |
#' In *Mesure et Histoire Médiévale*. Histoire ancienne et médiévale. |
|
| 227 |
#' Paris: Publication de la Sorbonne, p. 119-134. |
|
| 228 |
#' |
|
| 229 |
#' Bellanger, L. & Husi, P. (2012). Statistical Tool for Dating and |
|
| 230 |
#' Interpreting Archaeological Contexts Using Pottery. *Journal of |
|
| 231 |
#' Archaeological Science*, 39(4), 777-790. \doi{10.1016/j.jas.2011.06.031}.
|
|
| 232 |
#' |
|
| 233 |
#' Bellanger, L., Tomassone, R. & Husi, P. (2008). A Statistical Approach for |
|
| 234 |
#' Dating Archaeological Contexts. *Journal of Data Science*, 6, 135-154. |
|
| 235 |
#' |
|
| 236 |
#' Bellanger, L., Husi, P. & Tomassone, R. (2006). Une approche statistique |
|
| 237 |
#' pour la datation de contextes archéologiques. *Revue de Statistique |
|
| 238 |
#' Appliquée*, 54(2), 65-81. |
|
| 239 |
#' |
|
| 240 |
#' Bellanger, L., Husi, P. & Tomassone, R. (2006). Statistical Aspects of |
|
| 241 |
#' Pottery Quantification for the Dating of Some Archaeological Contexts. |
|
| 242 |
#' *Archaeometry*, 48(1), 169-183. \doi{10.1111/j.1475-4754.2006.00249.x}.
|
|
| 243 |
#' @example inst/examples/ex-event.R |
|
| 244 |
#' @author N. Frerebeau |
|
| 245 |
#' @family event date tools |
|
| 246 |
#' @docType methods |
|
| 247 |
#' @aliases predict_event-method |
|
| 248 |
setGeneric( |
|
| 249 |
name = "predict_event", |
|
| 250 |
def = function(object, data, ...) standardGeneric("predict_event"),
|
|
| 251 |
valueClass = "data.frame" |
|
| 252 |
) |
|
| 253 | ||
| 254 |
#' @rdname predict_event |
|
| 255 |
#' @aliases predict_accumulation-method |
|
| 256 |
setGeneric( |
|
| 257 |
name = "predict_accumulation", |
|
| 258 |
def = function(object, data, ...) standardGeneric("predict_accumulation"),
|
|
| 259 |
valueClass = "data.frame" |
|
| 260 |
) |
|
| 261 | ||
| 262 |
#' Density of Event and Accumulation Dates |
|
| 263 |
#' |
|
| 264 |
#' Estimates the event and accumulation density. |
|
| 265 |
#' @param object An [`EventDate-class`] object. |
|
| 266 |
#' @param dates A [`numeric`] vector of dates expressed as `calendar` years or |
|
| 267 |
#' *rata die* (if `calendar` is `NULL`). |
|
| 268 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the calendar |
|
| 269 |
#' of `dates` (see [aion::calendar()]). If `NULL` (the default), *rata die* are |
|
| 270 |
#' expected. |
|
| 271 |
#' @param type A [`character`] string indicating the type of plot. |
|
| 272 |
#' It must be one of "`activity`" (default) or "`tempo`" (see details). |
|
| 273 |
#' Any unambiguous substring can be given. |
|
| 274 |
#' @param n A length-one non-negative [`numeric`] vector giving the desired |
|
| 275 |
#' length of the vector of quantiles for density computation. |
|
| 276 |
#' @param ... Currently not used. |
|
| 277 |
#' @return |
|
| 278 |
#' An [`aion::TimeSeries-class`] object. |
|
| 279 |
#' @example inst/examples/ex-event.R |
|
| 280 |
#' @author N. Frerebeau |
|
| 281 |
#' @family event date tools |
|
| 282 |
#' @docType methods |
|
| 283 |
#' @aliases density_event-method |
|
| 284 |
setGeneric( |
|
| 285 |
name = "density_event", |
|
| 286 | ! |
def = function(object, ...) standardGeneric("density_event")
|
| 287 |
) |
|
| 288 | ||
| 289 |
#' @rdname density_event |
|
| 290 |
#' @aliases density_accumulation-method |
|
| 291 |
setGeneric( |
|
| 292 |
name = "density_accumulation", |
|
| 293 | ! |
def = function(object, ...) standardGeneric("density_accumulation")
|
| 294 |
) |
|
| 295 | ||
| 296 |
#' Extract Event Date Model Results |
|
| 297 |
#' |
|
| 298 |
#' @description |
|
| 299 |
#' * `summary()` summarizes linear model fit. |
|
| 300 |
#' * `coef()` extracts model coefficients (see [stats::coef()]). |
|
| 301 |
#' * `fitted()` extracts model fitted values (see [stats::fitted()]). |
|
| 302 |
#' * `residuals()` extracts model residuals (see [stats::residuals()]). |
|
| 303 |
#' * `sigma()` extracts the residual standard deviation (see [stats::sigma()]). |
|
| 304 |
#' * `terms()` extracts model terms (see [stats::terms()]). |
|
| 305 |
#' @param x,object An [`EventDate-class`] object. |
|
| 306 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 307 |
#' calendar (see [aion::calendar()]). If `NULL` (the default), *rata die* are |
|
| 308 |
#' returned. |
|
| 309 |
#' @param ... Currently not used. |
|
| 310 |
#' @example inst/examples/ex-event.R |
|
| 311 |
#' @author N. Frerebeau |
|
| 312 |
#' @family event date tools |
|
| 313 |
#' @docType methods |
|
| 314 |
#' @name model_event |
|
| 315 |
#' @rdname model_event |
|
| 316 |
NULL |
|
| 317 | ||
| 318 |
# Aoristic Analysis ============================================================ |
|
| 319 |
#' Aoristic Analysis |
|
| 320 |
#' |
|
| 321 |
#' Computes the aoristic sum. |
|
| 322 |
#' @param x,y A [`numeric`] vector giving the lower and upper boundaries of the |
|
| 323 |
#' time intervals, respectively. If `y` is missing, an attempt is made to |
|
| 324 |
#' interpret `x` in a suitable way (see [grDevices::xy.coords()]). |
|
| 325 |
#' @param step A length-one [`integer`] vector giving the step size, i.e. the |
|
| 326 |
#' width of each time step in the time series (defaults to \eqn{1},
|
|
| 327 |
#' i.e. annual level). |
|
| 328 |
#' @param start A length-one [`numeric`] vector giving the beginning of the time |
|
| 329 |
#' window. |
|
| 330 |
#' @param end A length-one [`numeric`] vector giving the end of the time |
|
| 331 |
#' window. |
|
| 332 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the calendar |
|
| 333 |
#' of `x` and `y` (see [aion::calendar()]). Defaults to Gregorian Common Era. |
|
| 334 |
#' @param weight A [`logical`] scalar: should the aoristic sum be weighted by |
|
| 335 |
#' the length of periods (default). If `FALSE` the aoristic sum is the number |
|
| 336 |
#' of elements within a time block. |
|
| 337 |
#' @param groups A [`factor`] vector in the sense that `as.factor(groups)` |
|
| 338 |
#' defines the grouping. If `x` is a `list` (or a `data.frame`), `groups` can |
|
| 339 |
#' be a length-one vector giving the index of the grouping component (column) |
|
| 340 |
#' of `x`. |
|
| 341 |
#' @param ... Currently not used. |
|
| 342 |
#' @details |
|
| 343 |
#' Aoristic analysis is used to determine the probability of contemporaneity of |
|
| 344 |
#' archaeological sites or assemblages. The aoristic analysis distributes the |
|
| 345 |
#' probability of an event uniformly over each temporal fraction of the period |
|
| 346 |
#' considered. The aoristic sum is then the distribution of the total number of |
|
| 347 |
#' events to be assumed within this period. |
|
| 348 |
#' |
|
| 349 |
#' Muller and Hinz (2018) pointed out that the overlapping of temporal |
|
| 350 |
#' intervals related to period categorization and dating accuracy is likely to |
|
| 351 |
#' bias the analysis. They proposed a weighting method to overcome this |
|
| 352 |
#' problem. This method is not implemented here (for the moment), see the |
|
| 353 |
#' [\pkg{aoristAAR} package](https://github.com/ISAAKiel/aoristAAR).
|
|
| 354 |
#' @return |
|
| 355 |
#' An [`AoristicSum-class`] object. |
|
| 356 |
#' @seealso [`plot()`][plot.AoristicSum] |
|
| 357 |
#' @references |
|
| 358 |
#' Crema, E. R. (2012). Modelling Temporal Uncertainty in Archaeological |
|
| 359 |
#' Analysis. *Journal of Archaeological Method and Theory*, 19(3): 440-61. |
|
| 360 |
#' \doi{10.1007/s10816-011-9122-3}.
|
|
| 361 |
#' |
|
| 362 |
#' Johnson, I. (2004). Aoristic Analysis: Seeds of a New Approach to Mapping |
|
| 363 |
#' Archaeological Distributions through Time. *In* Ausserer, K. F., Börner, W., |
|
| 364 |
#' Goriany, M. & Karlhuber-Vöckl, L. (ed.), *Enter the Past - The E-Way into |
|
| 365 |
#' the Four Dimensions of Cultural Heritage*, Oxford: Archaeopress, p. 448-52. |
|
| 366 |
#' BAR International Series 1227. |
|
| 367 |
#' \doi{10.15496/publikation-2085}
|
|
| 368 |
#' |
|
| 369 |
#' Müller-Scheeßel, N. & Hinz, M. (2018). *Aoristic Research in R: Correcting |
|
| 370 |
#' Temporal Categorizations in Archaeology*. Presented at the Human History and |
|
| 371 |
#' Digital Future (CAA 2018), Tubingen, March 21. |
|
| 372 |
#' <https://www.youtube.com/watch?v=bUBukex30QI>. |
|
| 373 |
#' |
|
| 374 |
#' Palmisano, A., Bevan, A. & Shennan, S. (2017). Comparing Archaeological |
|
| 375 |
#' Proxies for Long-Term Population Patterns: An Example from Central Italy. |
|
| 376 |
#' *Journal of Archaeological Science*, 87: 59-72. |
|
| 377 |
#' \doi{10.1016/j.jas.2017.10.001}.
|
|
| 378 |
#' |
|
| 379 |
#' Ratcliffe, J. H. (2000). Aoristic Analysis: The Spatial Interpretation of |
|
| 380 |
#' Unspecific Temporal Events. *International Journal of Geographical |
|
| 381 |
#' Information Science*, 14(7): 669-79. \doi{10.1080/136588100424963}.
|
|
| 382 |
#' |
|
| 383 |
#' Ratcliffe, J. H. (2002). Aoristic Signatures and the Spatio-Temporal |
|
| 384 |
#' Analysis of High Volume Crime Patterns. *Journal of Quantitative |
|
| 385 |
#' Criminology*, 18(1): 23-43. \doi{10.1023/A:1013240828824}.
|
|
| 386 |
#' @example inst/examples/ex-aoristic.R |
|
| 387 |
#' @author N. Frerebeau |
|
| 388 |
#' @family aoristic analysis |
|
| 389 |
#' @docType methods |
|
| 390 |
#' @aliases aoristic-method |
|
| 391 |
setGeneric( |
|
| 392 |
name = "aoristic", |
|
| 393 |
def = function(x, y, ...) standardGeneric("aoristic"),
|
|
| 394 |
valueClass = "AoristicSum" |
|
| 395 |
) |
|
| 396 | ||
| 397 |
#' Rate of Change |
|
| 398 |
#' |
|
| 399 |
#' Computes the rate of change from an aoristic analysis. |
|
| 400 |
#' @param object An [`AoristicSum-class`] object. |
|
| 401 |
#' @param n A non-negative [`integer`] giving the number of replications (see |
|
| 402 |
#' details). |
|
| 403 |
#' @param ... Currently not used. |
|
| 404 |
#' @return |
|
| 405 |
#' A [`RateOfChange-class`] object. |
|
| 406 |
#' @seealso [`plot()`][plot.AoristicSum] |
|
| 407 |
#' @references |
|
| 408 |
#' Baxter, M. J. & Cool, H. E. M. (2016). Reinventing the Wheel? Modelling |
|
| 409 |
#' Temporal Uncertainty with Applications to Brooch Distributions in Roman |
|
| 410 |
#' Britain. *Journal of Archaeological Science*, 66: 120-27. |
|
| 411 |
#' \doi{10.1016/j.jas.2015.12.007}.
|
|
| 412 |
#' |
|
| 413 |
#' Crema, E. R. (2012). Modelling Temporal Uncertainty in Archaeological |
|
| 414 |
#' Analysis. *Journal of Archaeological Method and Theory*, 19(3): 440-61. |
|
| 415 |
#' \doi{10.1007/s10816-011-9122-3}.
|
|
| 416 |
#' @example inst/examples/ex-aoristic.R |
|
| 417 |
#' @author N. Frerebeau |
|
| 418 |
#' @family aoristic analysis |
|
| 419 |
#' @docType methods |
|
| 420 |
#' @aliases roc-method |
|
| 421 |
setGeneric( |
|
| 422 |
name = "roc", |
|
| 423 |
def = function(object, ...) standardGeneric("roc"),
|
|
| 424 |
valueClass = "RateOfChange" |
|
| 425 |
) |
|
| 426 | ||
| 427 |
# Chronological Apportioning =================================================== |
|
| 428 |
#' Chronological Apportioning |
|
| 429 |
#' |
|
| 430 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 431 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 432 |
#' individuals for each category, i.e. a contingency table). A [`data.frame`] |
|
| 433 |
#' will be coerced to a `numeric` `matrix` via [data.matrix()]. |
|
| 434 |
#' @param s0 A length-\eqn{m} [`numeric`] vector giving the site beginning dates
|
|
| 435 |
#' expressed in CE years (BCE years must be given as negative numbers). |
|
| 436 |
#' @param s1 A length-\eqn{m} [`numeric`] vector giving the site end dates
|
|
| 437 |
#' expressed in CE years (BCE years must be given as negative numbers). |
|
| 438 |
#' @param t0 A length-\eqn{p} [`numeric`] vector giving the type beginning dates
|
|
| 439 |
#' expressed in CE years (BCE years must be given as negative numbers). |
|
| 440 |
#' @param t1 A length-\eqn{p} [`numeric`] vector giving the type end dates
|
|
| 441 |
#' expressed in CE years (BCE years must be given as negative numbers). |
|
| 442 |
#' @param from A length-one [`numeric`] vector giving the beginning of the |
|
| 443 |
#' period of interest (in years CE). |
|
| 444 |
#' @param to A length-one [`numeric`] vector giving the end of the period of |
|
| 445 |
#' interest (in years CE). |
|
| 446 |
#' @param step A length-one [`integer`] vector giving the step size, i.e. the |
|
| 447 |
#' width of each time step for apportioning (in years CE; defaults to |
|
| 448 |
#' \eqn{25}).
|
|
| 449 |
#' @param method A [`character`] string specifying the distribution to be used |
|
| 450 |
#' (type popularity curve). It must be one of "`uniform`" (uniform |
|
| 451 |
#' distribution) or "`truncated`" (truncated standard normal distribution). |
|
| 452 |
#' Any unambiguous substring can be given. |
|
| 453 |
#' @param z An [`integer`] value giving the lower and upper truncation points |
|
| 454 |
#' (defaults to \eqn{2}). Only used if `method` is "`truncated`".
|
|
| 455 |
#' @param progress A [`logical`] scalar: should a progress bar be displayed? |
|
| 456 |
#' @param ... Currently not used. |
|
| 457 |
#' @return |
|
| 458 |
#' A [`CountApportion-class`] object. |
|
| 459 |
#' @references |
|
| 460 |
#' Roberts, J. M., Mills, B. J., Clark, J. J., Haas, W. R., Huntley, D. L. & |
|
| 461 |
#' Trowbridge, M. A. (2012). A Method for Chronological Apportioning of Ceramic |
|
| 462 |
#' Assemblages. *Journal of Archaeological Science*, 39(5): 1513-20. |
|
| 463 |
#' \doi{10.1016/j.jas.2011.12.022}.
|
|
| 464 |
#' @example inst/examples/ex-apportion.R |
|
| 465 |
#' @author N. Frerebeau |
|
| 466 |
#' @family chronological apportioning methods |
|
| 467 |
#' @family chronological analysis |
|
| 468 |
#' @docType methods |
|
| 469 |
#' @aliases apportion-method |
|
| 470 |
setGeneric( |
|
| 471 |
name = "apportion", |
|
| 472 |
def = function(object, ...) standardGeneric("apportion"),
|
|
| 473 |
valueClass = "CountApportion" |
|
| 474 |
) |
|
| 475 | ||
| 476 |
# Frequency Increment Test ===================================================== |
|
| 477 |
#' Frequency Increment Test |
|
| 478 |
#' |
|
| 479 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 480 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 481 |
#' individuals for each category, i.e. a contingency table). A [`data.frame`] |
|
| 482 |
#' will be coerced to a `numeric` `matrix` via [data.matrix()]. |
|
| 483 |
#' @param dates A length-\eqn{m} [`numeric`] vector of dates.
|
|
| 484 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the calendar |
|
| 485 |
#' of `dates` (see [aion::calendar()]). Defaults to Gregorian Common Era. |
|
| 486 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 487 |
#' @param roll A [`logical`] scalar: should each time series be subsetted to |
|
| 488 |
#' look for episodes of selection? |
|
| 489 |
#' @param window An odd [`integer`] giving the size of the rolling |
|
| 490 |
#' window. Only used if `roll` is `TRUE`. |
|
| 491 |
#' @param ... Currently not used. |
|
| 492 |
#' @details |
|
| 493 |
#' The Frequency Increment Test (FIT) rejects neutrality if the distribution |
|
| 494 |
#' of normalized variant frequency increments exhibits a mean that deviates |
|
| 495 |
#' significantly from zero. |
|
| 496 |
#' |
|
| 497 |
#' If `roll` is `TRUE`, each time series is subsetted according to `window` to |
|
| 498 |
#' see if episodes of selection can be identified among variables that might |
|
| 499 |
#' not show overall selection. |
|
| 500 |
#' @return |
|
| 501 |
#' An [`IncrementTest-class`] object. |
|
| 502 |
#' @seealso [`plot()`][plot.IncrementTest] |
|
| 503 |
#' @example inst/examples/ex-fit.R |
|
| 504 |
#' @references |
|
| 505 |
#' Feder, A. F., Kryazhimskiy, S. & Plotkin, J. B. (2014). Identifying |
|
| 506 |
#' Signatures of Selection in Genetic Time Series. *Genetics*, 196(2): |
|
| 507 |
#' 509-522. \doi{10.1534/genetics.113.158220}.
|
|
| 508 |
#' @author N. Frerebeau |
|
| 509 |
#' @family chronological analysis |
|
| 510 |
#' @docType methods |
|
| 511 |
#' @aliases fit-method |
|
| 512 |
setGeneric( |
|
| 513 |
name = "fit", |
|
| 514 |
def = function(object, dates, ...) standardGeneric("fit"),
|
|
| 515 |
valueClass = "IncrementTest" |
|
| 516 |
) |
|
| 517 | ||
| 518 |
# Plot ========================================================================= |
|
| 519 |
#' Abundance vs Time Plot |
|
| 520 |
#' |
|
| 521 |
#' Produces an abundance *vs* time diagram. |
|
| 522 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 523 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 524 |
#' individuals for each category, i.e. a contingency table). A [`data.frame`] |
|
| 525 |
#' will be coerced to a `numeric` `matrix` via [data.matrix()]. |
|
| 526 |
#' @param dates A [`numeric`] vector of dates. |
|
| 527 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 528 |
#' calendar (see [aion::calendar()]). |
|
| 529 |
#' @param ... Further parameters to be passed to [aion::plot()]. |
|
| 530 |
#' @return |
|
| 531 |
#' `plot_time()` is called it for its side-effects: it results in a graphic |
|
| 532 |
#' being displayed (invisibly returns `object`). |
|
| 533 |
#' @example inst/examples/ex-plot.R |
|
| 534 |
#' @author N. Frerebeau |
|
| 535 |
#' @family plotting methods |
|
| 536 |
#' @docType methods |
|
| 537 |
#' @aliases plot_time-method |
|
| 538 |
setGeneric( |
|
| 539 |
name = "plot_time", |
|
| 540 | 2x |
def = function(object, dates, ...) standardGeneric("plot_time")
|
| 541 |
) |
|
| 542 | ||
| 543 |
#' MCD Plot |
|
| 544 |
#' |
|
| 545 |
#' @param x A [`MeanDate-class`] object. |
|
| 546 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 547 |
#' calendar (see [aion::calendar()]). |
|
| 548 |
#' @param interval A [`character`] string giving the type of confidence |
|
| 549 |
#' interval to be returned. It must be one "`student`" (the default), |
|
| 550 |
#' "`normal`", "`percentiles`" or "`range`" (min-max). |
|
| 551 |
#' Any unambiguous substring can be given. |
|
| 552 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 553 |
#' Only used if `interval` is not "`range`". |
|
| 554 |
#' @param decreasing A [`logical`] scalar: should the sort be increasing or |
|
| 555 |
#' decreasing? |
|
| 556 |
#' @param main A [`character`] string giving a main title for the plot. |
|
| 557 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
| 558 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x, |
|
| 559 |
#' y and z axis labels) appear on the plot? |
|
| 560 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
| 561 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
| 562 |
#' plot? |
|
| 563 |
#' @param panel.first An an `expression` to be evaluated after the plot axes are |
|
| 564 |
#' set up but before any plotting takes place. This can be useful for drawing |
|
| 565 |
#' background grids. |
|
| 566 |
#' @param panel.last An `expression` to be evaluated after plotting has taken |
|
| 567 |
#' place but before the axes, title and box are added. |
|
| 568 |
#' @param ... Further [graphical parameters][graphics::par]. |
|
| 569 |
#' @return |
|
| 570 |
#' `plot()` is called it for its side-effects: it results in a graphic being |
|
| 571 |
#' displayed (invisibly returns `x`). |
|
| 572 |
#' @seealso [mcd()] |
|
| 573 |
#' @example inst/examples/ex-mcd.R |
|
| 574 |
#' @author N. Frerebeau |
|
| 575 |
#' @family plotting methods |
|
| 576 |
#' @docType methods |
|
| 577 |
#' @name plot.MeanDate |
|
| 578 |
#' @rdname plot.MeanDate |
|
| 579 |
NULL |
|
| 580 | ||
| 581 |
#' Plot Aoristic Analysis |
|
| 582 |
#' |
|
| 583 |
#' @param x An [`AoristicSum-class`] object. |
|
| 584 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 585 |
#' calendar (see [aion::calendar()]). |
|
| 586 |
#' @param type A [`character`] string specifying whether bar or density should |
|
| 587 |
#' be plotted? It must be one of "`bar`" or "`density`". Any unambiguous |
|
| 588 |
#' substring can be given. |
|
| 589 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 590 |
#' @inheritParams aion::plot |
|
| 591 |
#' @return |
|
| 592 |
#' `plot()` is called it for its side-effects: it results in a graphic being |
|
| 593 |
#' displayed (invisibly returns `x`). |
|
| 594 |
#' @seealso [aoristic()] |
|
| 595 |
#' @example inst/examples/ex-aoristic.R |
|
| 596 |
#' @author N. Frerebeau |
|
| 597 |
#' @family plotting methods |
|
| 598 |
#' @docType methods |
|
| 599 |
#' @name plot.AoristicSum |
|
| 600 |
#' @rdname plot.AoristicSum |
|
| 601 |
NULL |
|
| 602 | ||
| 603 |
#' Plot Event and Accumulation Dates |
|
| 604 |
#' |
|
| 605 |
#' Produces an activity or a tempo plot. |
|
| 606 |
#' @param x An [`EventDate-class`] object. |
|
| 607 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 608 |
#' calendar (see [aion::calendar()]). |
|
| 609 |
#' @param type A [`character`] string indicating the type of plot. |
|
| 610 |
#' It must be one of "`activity`" (default) or "`tempo`" (see details). |
|
| 611 |
#' Any unambiguous substring can be given. |
|
| 612 |
#' @param event A [`logical`] scalar: should the distribution of the event date |
|
| 613 |
#' be displayed? Only used if type is "`activity`". |
|
| 614 |
#' @param select A [`numeric`] or [`character`] vector giving the selection of |
|
| 615 |
#' the assemblage that are drawn. |
|
| 616 |
#' @param n A length-one non-negative [`numeric`] vector giving the desired |
|
| 617 |
#' length of the vector of quantiles for density computation. |
|
| 618 |
#' @param eps A length-one [`numeric`] value giving the cutoff below which |
|
| 619 |
#' values will be removed. |
|
| 620 |
#' @param col.accumulation A color specification for the accumulation density |
|
| 621 |
#' curve. |
|
| 622 |
#' @param col.event A color specification for the event density curve. |
|
| 623 |
#' @inheritParams aion::plot |
|
| 624 |
#' @section Event and Acccumulation Dates: |
|
| 625 |
#' `plot()` displays the probability estimate density curves of archaeological |
|
| 626 |
#' assemblage dates (*event* and *accumulation* dates; Bellanger and Husi |
|
| 627 |
#' 2012). The *event* date is plotted as a line, while the *accumulation* date |
|
| 628 |
#' is shown as a grey filled area. |
|
| 629 |
#' |
|
| 630 |
#' The accumulation date can be displayed as a tempo plot (Dye 2016) or an |
|
| 631 |
#' activity plot (Philippe and Vibet 2020): |
|
| 632 |
#' \describe{
|
|
| 633 |
#' \item{`tempo`}{A tempo plot estimates the cumulative occurrence of
|
|
| 634 |
#' archaeological events, such as the slope of the plot directly reflects the |
|
| 635 |
#' pace of change.} |
|
| 636 |
#' \item{`activity`}{An activity plot displays the first derivative of the
|
|
| 637 |
#' tempo plot.} |
|
| 638 |
#' } |
|
| 639 |
#' @return |
|
| 640 |
#' `plot()` is called it for its side-effects: it results in a graphic being |
|
| 641 |
#' displayed (invisibly returns `x`). |
|
| 642 |
#' @references |
|
| 643 |
#' Bellanger, L. & Husi, P. (2012). Statistical Tool for Dating and |
|
| 644 |
#' Interpreting Archaeological Contexts Using Pottery. *Journal of |
|
| 645 |
#' Archaeological Science*, 39(4), 777-790. \doi{10.1016/j.jas.2011.06.031}.
|
|
| 646 |
#' |
|
| 647 |
#' Dye, T. S. (2016). Long-Term Rhythms in the Development of Hawaiian |
|
| 648 |
#' Social Stratification. *Journal of Archaeological Science*, 71, 1-9. |
|
| 649 |
#' \doi{10.1016/j.jas.2016.05.006}.
|
|
| 650 |
#' |
|
| 651 |
#' Philippe, A. & Vibet, M.-A. (2020). Analysis of Archaeological Phases Using |
|
| 652 |
#' the R Package ArchaeoPhases. *Journal of Statistical Software, Code |
|
| 653 |
#' Snippets*, 93(1), 1-25. \doi{10.18637/jss.v093.c01}.
|
|
| 654 |
#' @seealso [event()] |
|
| 655 |
#' @example inst/examples/ex-event.R |
|
| 656 |
#' @author N. Frerebeau |
|
| 657 |
#' @family plotting methods |
|
| 658 |
#' @docType methods |
|
| 659 |
#' @name plot.EventDate |
|
| 660 |
#' @rdname plot.EventDate |
|
| 661 |
NULL |
|
| 662 | ||
| 663 |
#' Detection of Selective Processes |
|
| 664 |
#' |
|
| 665 |
#' Produces an abundance *vs* time diagram. |
|
| 666 |
#' @param x An [`IncrementTest-class`] object to be plotted. |
|
| 667 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 668 |
#' calendar (see [aion::calendar()]). |
|
| 669 |
#' @param col.neutral,col.selection,col.roll A vector of colors. |
|
| 670 |
#' @inheritParams aion::plot |
|
| 671 |
#' @details |
|
| 672 |
#' Results of the frequency increment test can be displayed on an abundance |
|
| 673 |
#' *vs* time diagram aid in the detection and quantification of selective |
|
| 674 |
#' processes in the archaeological record. If `roll` is `TRUE`, each time |
|
| 675 |
#' series is subsetted according to `window` to see if episodes of selection |
|
| 676 |
#' can be identified among decoration types that might not show overall |
|
| 677 |
#' selection. If so, shading highlights the data points where |
|
| 678 |
#' [fit()] identifies selection. |
|
| 679 |
#' @return |
|
| 680 |
#' `plot()` is called it for its side-effects: it results in a graphic being |
|
| 681 |
#' displayed (invisibly returns `x`). |
|
| 682 |
#' @note |
|
| 683 |
#' Displaying FIT results on an abundance *vs* time diagram is adapted from Ben |
|
| 684 |
#' Marwick's [original idea](https://github.com/benmarwick/signatselect/). |
|
| 685 |
#' @seealso [fit()] |
|
| 686 |
#' @example inst/examples/ex-fit.R |
|
| 687 |
#' @author N. Frerebeau |
|
| 688 |
#' @family plotting methods |
|
| 689 |
#' @docType methods |
|
| 690 |
#' @name plot.IncrementTest |
|
| 691 |
#' @rdname plot.IncrementTest |
|
| 692 |
NULL |
|
| 693 | ||
| 694 |
# Resample ===================================================================== |
|
| 695 |
#' Bootstrap Mean Ceramic Dates |
|
| 696 |
#' |
|
| 697 |
#' Generates bootstrap estimations of an [MCD][mcd()]. |
|
| 698 |
#' @param object A [`MeanDate-class`] object (typically returned by [mcd()]). |
|
| 699 |
#' @param n A non-negative [`integer`] specifying the number of bootstrap |
|
| 700 |
#' replications. |
|
| 701 |
#' @param f A [`function`] that takes a single numeric vector (the result of |
|
| 702 |
#' the resampling procedure) as argument. |
|
| 703 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 704 |
#' Must be a single number between \eqn{0} and \eqn{1}. Only used if `f` is
|
|
| 705 |
#' `NULL`. |
|
| 706 |
#' @param interval A [`character`] string giving the type of confidence |
|
| 707 |
#' interval to be returned. It must be one "`basic`" (the default), "`normal`" |
|
| 708 |
#' or "`percentiles`" (see [arkhe::confidence_bootstrap()]). Any unambiguous |
|
| 709 |
#' substring can be given. Only used if `f` is `NULL`. |
|
| 710 |
#' @param seed An object specifying if and how the random number generator |
|
| 711 |
#' should be initialized (see [stats::simulate()]). |
|
| 712 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 713 |
#' calendar (see [aion::calendar()]). |
|
| 714 |
#' @return |
|
| 715 |
#' If `f` is `NULL`, `bootstrap()` returns a [`data.frame`] with the following |
|
| 716 |
#' elements (else, returns the result of `f` applied to the `n` resampled |
|
| 717 |
#' values) : |
|
| 718 |
#' \describe{
|
|
| 719 |
#' \item{`original`}{The observed value.}
|
|
| 720 |
#' \item{`mean`}{The bootstrap estimate of mean.}
|
|
| 721 |
#' \item{`bias`}{The bootstrap estimate of bias.}
|
|
| 722 |
#' \item{`error`}{The boostrap estimate of standard error.}
|
|
| 723 |
#' \item{`lower`}{The lower limit of the bootstrap confidence interval at `level`.}
|
|
| 724 |
#' \item{`upper`}{The upper limit of the bootstrap confidence interval at `level`.}
|
|
| 725 |
#' } |
|
| 726 |
#' @seealso [mcd()] |
|
| 727 |
#' @example inst/examples/ex-mcd.R |
|
| 728 |
#' @author N. Frerebeau |
|
| 729 |
#' @docType methods |
|
| 730 |
#' @family resampling methods |
|
| 731 |
#' @name bootstrap.MeanDate |
|
| 732 |
#' @rdname bootstrap.MeanDate |
|
| 733 |
NULL |
|
| 734 | ||
| 735 |
#' Jackknife Mean Ceramic Dates |
|
| 736 |
#' |
|
| 737 |
#' Generate jackknife estimations of an [MCD][mcd()]. |
|
| 738 |
#' @param object A [`MeanDate-class`] object (typically returned by [mcd()]). |
|
| 739 |
#' @param f A [`function`] that takes a single numeric vector (the result of |
|
| 740 |
#' the resampling procedure) as argument. |
|
| 741 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 742 |
#' calendar (see [aion::calendar()]). |
|
| 743 |
#' @return |
|
| 744 |
#' If `f` is `NULL`, `jackknife()` returns a [`data.frame`] with the following |
|
| 745 |
#' elements (else, returns the result of `f` applied to the `n` resampled |
|
| 746 |
#' values) : |
|
| 747 |
#' \describe{
|
|
| 748 |
#' \item{`original`}{The observed value.}
|
|
| 749 |
#' \item{`mean`}{The jackknife estimate of mean.}
|
|
| 750 |
#' \item{`bias`}{The jackknife estimate of bias.}
|
|
| 751 |
#' \item{`error`}{The jackknife estimate of standard erro.}
|
|
| 752 |
#' } |
|
| 753 |
#' @seealso [mcd()] |
|
| 754 |
#' @example inst/examples/ex-mcd.R |
|
| 755 |
#' @author N. Frerebeau |
|
| 756 |
#' @docType methods |
|
| 757 |
#' @family resampling methods |
|
| 758 |
#' @name jackknife.MeanDate |
|
| 759 |
#' @rdname jackknife.MeanDate |
|
| 760 |
NULL |
|
| 761 | ||
| 762 |
#' Bootstrap Event Dates |
|
| 763 |
#' |
|
| 764 |
#' Generates bootstrap estimations of an [event date][event()]. |
|
| 765 |
#' @param object An [`EventDate-class`] object (typically returned by [event()]). |
|
| 766 |
#' @param n A non-negative [`integer`] specifying the number of bootstrap |
|
| 767 |
#' replications. |
|
| 768 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 769 |
#' @param probs A [`numeric`] vector of probabilities with values in |
|
| 770 |
#' \eqn{[0,1]}.
|
|
| 771 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 772 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
| 773 |
#' @param progress A [`logical`] scalar: should a progress bar be displayed? |
|
| 774 |
#' @param ... Currently not used. |
|
| 775 |
#' @details |
|
| 776 |
#' A large number of new bootstrap assemblages is created, with the same sample |
|
| 777 |
#' size, by resampling each of the original assemblage with replacement. Then, |
|
| 778 |
#' examination of the bootstrap statistics makes it possible to pinpoint |
|
| 779 |
#' assemblages that require further investigation. |
|
| 780 |
#' |
|
| 781 |
#' A five columns `data.frame` is returned, giving the bootstrap |
|
| 782 |
#' distribution statistics for each replicated assemblage (in rows) |
|
| 783 |
#' with the following columns: |
|
| 784 |
#' \describe{
|
|
| 785 |
#' \item{`min`}{Minimum value.}
|
|
| 786 |
#' \item{`mean`}{Mean value (event date).}
|
|
| 787 |
#' \item{`max`}{Maximum value.}
|
|
| 788 |
#' \item{`Q5`}{Sample quantile to 0.05 probability.}
|
|
| 789 |
#' \item{`Q95`}{Sample quantile to 0.95 probability.}
|
|
| 790 |
#' } |
|
| 791 |
#' @seealso [event()] |
|
| 792 |
#' @return |
|
| 793 |
#' A [`data.frame`]. |
|
| 794 |
#' @author N. Frerebeau |
|
| 795 |
#' @docType methods |
|
| 796 |
#' @family resampling methods |
|
| 797 |
#' @name bootstrap.EventDate |
|
| 798 |
#' @rdname bootstrap.EventDate |
|
| 799 |
NULL |
|
| 800 | ||
| 801 |
#' Jackknife Event Dates |
|
| 802 |
#' |
|
| 803 |
#' Generates jackknife estimations of an [event date][event()]. |
|
| 804 |
#' @param object An [`EventDate-class`] object (typically returned by [event()]). |
|
| 805 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 806 |
#' @param calendar An [`aion::TimeScale-class`] object specifying the target |
|
| 807 |
#' calendar (see [aion::calendar()]). If `NULL`, *rata die* are returned. |
|
| 808 |
#' @param progress A [`logical`] scalar: should a progress bar be displayed? |
|
| 809 |
#' @param verbose A [`logical`] scalar: should \R report extra information |
|
| 810 |
#' on progress? |
|
| 811 |
#' @param ... Further arguments to be passed to internal methods. |
|
| 812 |
#' @details |
|
| 813 |
#' One type/fabric is removed at a time and all statistics are recalculated. |
|
| 814 |
#' In this way, one can assess whether certain type/fabric has a substantial |
|
| 815 |
#' influence on the date estimate. |
|
| 816 |
#' |
|
| 817 |
#' A three columns `data.frame` is returned, giving the results of the |
|
| 818 |
#' resampling procedure (jackknifing fabrics) for each assemblage (in rows) |
|
| 819 |
#' with the following columns: |
|
| 820 |
#' \describe{
|
|
| 821 |
#' \item{`mean`}{The jackknife mean (event date).}
|
|
| 822 |
#' \item{`lower`}{The lower boundary of the confidence interval.}
|
|
| 823 |
#' \item{`upper`}{The upper boundary of the confidence interval.}
|
|
| 824 |
#' } |
|
| 825 |
#' @return |
|
| 826 |
#' A [`data.frame`]. |
|
| 827 |
#' @seealso [event()] |
|
| 828 |
#' @author N. Frerebeau |
|
| 829 |
#' @docType methods |
|
| 830 |
#' @family resampling methods |
|
| 831 |
#' @name jackknife.EventDate |
|
| 832 |
#' @rdname jackknife.EventDate |
|
| 833 |
NULL |
|
| 834 | ||
| 835 |
# Seriation Methods ============================================================ |
|
| 836 |
## Reciprocal ranking ---------------------------------------------------------- |
|
| 837 |
#' Reciprocal Ranking Seriation |
|
| 838 |
#' |
|
| 839 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 840 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 841 |
#' individuals for each category, i.e. a contingency table). A [`data.frame`] |
|
| 842 |
#' will be coerced to a `numeric` `matrix` via [data.matrix()]. |
|
| 843 |
#' @param EPPM A [`logical`] scalar: should the seriation be computed on EPPM |
|
| 844 |
#' instead of raw data? |
|
| 845 |
#' @param margin A [`numeric`] vector giving the subscripts which the |
|
| 846 |
#' rearrangement will be applied over: `1` indicates rows, `2` indicates |
|
| 847 |
#' columns, `c(1, 2)` indicates rows then columns, `c(2, 1)` indicates columns |
|
| 848 |
#' then rows. |
|
| 849 |
#' @param stop An [`integer`] giving the stopping rule (i.e. maximum number of |
|
| 850 |
#' iterations) to avoid infinite loop. |
|
| 851 |
#' @param ... Currently not used. |
|
| 852 |
#' @details |
|
| 853 |
#' This procedure iteratively rearrange rows and/or columns according to their |
|
| 854 |
#' weighted rank in the data matrix until convergence. |
|
| 855 |
#' |
|
| 856 |
#' Note that this procedure could enter into an infinite loop. If no |
|
| 857 |
#' convergence is reached before the maximum number of iterations, it stops |
|
| 858 |
#' with a warning. |
|
| 859 |
#' @return |
|
| 860 |
#' A [RankPermutationOrder-class] object. |
|
| 861 |
#' @references |
|
| 862 |
#' Desachy, B. (2004). Le sériographe EPPM: un outil informatisé de sériation |
|
| 863 |
#' graphique pour tableaux de comptages. *Revue archéologique de Picardie*, |
|
| 864 |
#' 3(1), 39-56. \doi{10.3406/pica.2004.2396}.
|
|
| 865 |
#' |
|
| 866 |
#' Dunnell, R. C. (1970). Seriation Method and Its Evaluation. *American |
|
| 867 |
#' Antiquity*, 35(03), 305-319. \doi{10.2307/278341}.
|
|
| 868 |
#' |
|
| 869 |
#' Ihm, P. (2005). A Contribution to the History of Seriation in Archaeology. |
|
| 870 |
#' In C. Weihs & W. Gaul (Eds.), *Classification: The Ubiquitous |
|
| 871 |
#' Challenge*. Berlin Heidelberg: Springer, p. 307-316. |
|
| 872 |
#' \doi{10.1007/3-540-28084-7_34}.
|
|
| 873 |
#' @example inst/examples/ex-seriation.R |
|
| 874 |
#' @author N. Frerebeau |
|
| 875 |
#' @family seriation methods |
|
| 876 |
#' @docType methods |
|
| 877 |
#' @aliases seriate_rank-method |
|
| 878 |
setGeneric( |
|
| 879 |
name = "seriate_rank", |
|
| 880 |
def = function(object, ...) standardGeneric("seriate_rank"),
|
|
| 881 |
valueClass = "PermutationOrder" |
|
| 882 |
) |
|
| 883 | ||
| 884 |
## Average Ranking ------------------------------------------------------------- |
|
| 885 |
#' Correspondence Analysis-Based Seriation |
|
| 886 |
#' |
|
| 887 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 888 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 889 |
#' individuals for each category, i.e. a contingency table). A [`data.frame`] |
|
| 890 |
#' will be coerced to a `numeric` `matrix` via [data.matrix()]. |
|
| 891 |
#' @param margin A [`numeric`] vector giving the subscripts which the |
|
| 892 |
#' rearrangement will be applied over: `1` indicates rows, `2` indicates |
|
| 893 |
#' columns, `c(1, 2)` indicates rows then columns, `c(2, 1)` indicates columns |
|
| 894 |
#' then rows. |
|
| 895 |
#' @param axes An [`integer`] vector giving the subscripts of the CA axes to be |
|
| 896 |
#' used. |
|
| 897 |
#' @param sup_row A `vector` specifying the indices of the supplementary rows |
|
| 898 |
#' (see [dimensio::ca()]). |
|
| 899 |
#' @param sup_col A `vector` specifying the indices of the supplementary columns |
|
| 900 |
#' (see [dimensio::ca()]). |
|
| 901 |
#' @param ... Currently not used. |
|
| 902 |
#' @details |
|
| 903 |
#' Correspondence analysis (CA) is an effective method for the seriation of |
|
| 904 |
#' archaeological assemblages. The order of the rows and columns is given by |
|
| 905 |
#' the coordinates along one dimension of the CA space, assumed to account for |
|
| 906 |
#' temporal variation. The direction of temporal change within the |
|
| 907 |
#' correspondence analysis space is arbitrary: additional information is needed |
|
| 908 |
#' to determine the actual order in time. |
|
| 909 |
#' @return |
|
| 910 |
#' An [`AveragePermutationOrder-class`] object. |
|
| 911 |
#' @references |
|
| 912 |
#' Ihm, P. (2005). A Contribution to the History of Seriation in Archaeology. |
|
| 913 |
#' In C. Weihs & W. Gaul (Eds.), *Classification: The Ubiquitous |
|
| 914 |
#' Challenge*. Berlin Heidelberg: Springer, p. 307-316. |
|
| 915 |
#' \doi{10.1007/3-540-28084-7_34}.
|
|
| 916 |
#' @seealso [dimensio::ca()] |
|
| 917 |
#' @example inst/examples/ex-seriation.R |
|
| 918 |
#' @author N. Frerebeau |
|
| 919 |
#' @family seriation methods |
|
| 920 |
#' @docType methods |
|
| 921 |
#' @aliases seriate_average-method |
|
| 922 |
setGeneric( |
|
| 923 |
name = "seriate_average", |
|
| 924 |
def = function(object, ...) standardGeneric("seriate_average"),
|
|
| 925 |
valueClass = "PermutationOrder" |
|
| 926 |
) |
|
| 927 | ||
| 928 |
# @rdname seriate_constrain |
|
| 929 |
# @aliases seriate_constrain-method |
|
| 930 |
# setGeneric( |
|
| 931 |
# name = "seriate_constrain", |
|
| 932 |
# def = function(object, constrain, ...) standardGeneric("seriate_constrain"),
|
|
| 933 |
# valueClass = "PermutationOrder" |
|
| 934 |
# ) |
|
| 935 | ||
| 936 |
# @rdname seriate_idds |
|
| 937 |
# @aliases seriate_idds-method |
|
| 938 |
# setGeneric( |
|
| 939 |
# name = "seriate_idds", |
|
| 940 |
# def = function(object, ...) standardGeneric("seriate_idds"),
|
|
| 941 |
# valueClass = "PermutationOrder" |
|
| 942 |
# ) |
|
| 943 | ||
| 944 |
#' Coerce an \R Object to a Seriation Order |
|
| 945 |
#' |
|
| 946 |
#' @param object An \R object. |
|
| 947 |
#' @param margin A [`numeric`] vector giving the subscripts which the |
|
| 948 |
#' rearrangement will be applied over: `1` indicates rows, `2` indicates |
|
| 949 |
#' columns, `c(1, 2)` indicates rows then columns, `c(2, 1)` indicates columns |
|
| 950 |
#' then rows. |
|
| 951 |
#' @param axes An [`integer`] vector giving the subscripts of the CA axes to be |
|
| 952 |
#' used. |
|
| 953 |
#' @param ... Currently not used. |
|
| 954 |
#' @return |
|
| 955 |
#' A [`PermutationOrder-class`] object. |
|
| 956 |
#' @author N. Frerebeau |
|
| 957 |
#' @family seriation methods |
|
| 958 |
#' @docType methods |
|
| 959 |
#' @aliases as_seriation-method |
|
| 960 |
setGeneric( |
|
| 961 |
name = "as_seriation", |
|
| 962 | 1x |
def = function(object, ...) standardGeneric("as_seriation")
|
| 963 |
) |
|
| 964 | ||
| 965 |
## Refine ---------------------------------------------------------------------- |
|
| 966 |
#' Refine CA-based Seriation |
|
| 967 |
#' |
|
| 968 |
#' @param object A [`PermutationOrder-class`] object (typically returned by |
|
| 969 |
#' [seriate_average()]) or a [`dimensio::BootstrapCA-class`] object (typically |
|
| 970 |
#' returned by [dimensio::bootstrap()]). |
|
| 971 |
#' @param cutoff A function that takes a numeric vector as argument and returns |
|
| 972 |
#' a single numeric value (see below). |
|
| 973 |
#' @param n A non-negative [`integer`] giving the number of bootstrap |
|
| 974 |
#' replications. |
|
| 975 |
#' @param margin A length-one [`numeric`] vector giving the subscripts which the |
|
| 976 |
#' refinement will be applied over: `1` indicates rows, `2` indicates columns. |
|
| 977 |
#' @param axes An [`integer`] vector giving the subscripts of the CA axes to be |
|
| 978 |
#' used. |
|
| 979 |
#' @param ... Currently not used. |
|
| 980 |
#' @details |
|
| 981 |
#' `refine()` allows to identify samples that are subject to sampling error or |
|
| 982 |
#' samples that have underlying structural relationships and might be |
|
| 983 |
#' influencing the ordering along the CA space. |
|
| 984 |
#' |
|
| 985 |
#' This relies on a partial bootstrap approach to CA-based seriation where each |
|
| 986 |
#' sample is replicated `n` times. The maximum dimension length of the convex |
|
| 987 |
#' hull around the sample point cloud allows to remove samples for a given |
|
| 988 |
#' `cutoff` value. |
|
| 989 |
#' |
|
| 990 |
#' According to Peebles and Schachner (2012), "\[this\] point removal procedure |
|
| 991 |
#' \[results in\] a reduced dataset where the position of individuals within |
|
| 992 |
#' the CA are highly stable and which produces an ordering consistent with the |
|
| 993 |
#' assumptions of frequency seriation." |
|
| 994 |
#' |
|
| 995 |
#' See `vignette("seriation")`.
|
|
| 996 |
#' @return |
|
| 997 |
#' A [`list`] with the following elements: |
|
| 998 |
#' \describe{
|
|
| 999 |
#' \item{`length`}{A [`numeric`] vector giving the convex hull maximum
|
|
| 1000 |
#' dimension length.} |
|
| 1001 |
#' \item{`cutoff`}{A [`numeric`] value giving the cutoff value for samples
|
|
| 1002 |
#' selection.} |
|
| 1003 |
#' \item{`exclude`}{An [`integer`] vector giving the subscript of the
|
|
| 1004 |
#' observations to be removed.} |
|
| 1005 |
#' \item{`margin`}{A [`numeric`] value specifying the dimension along which
|
|
| 1006 |
#' the refinement procedure has been applied: `1` indicates rows, |
|
| 1007 |
#' `2` indicates columns.} |
|
| 1008 |
#' } |
|
| 1009 |
#' @references |
|
| 1010 |
#' Peeples, M. A., & Schachner, G. (2012). Refining correspondence |
|
| 1011 |
#' analysis-based ceramic seriation of regional data sets. *Journal of |
|
| 1012 |
#' Archaeological Science*, 39(8), 2818-2827. |
|
| 1013 |
#' \doi{10.1016/j.jas.2012.04.040}.
|
|
| 1014 |
#' @seealso [dimensio::bootstrap()] |
|
| 1015 |
#' @author N. Frerebeau |
|
| 1016 |
#' @docType methods |
|
| 1017 |
#' @family seriation methods |
|
| 1018 |
#' @aliases refine-method |
|
| 1019 |
setGeneric( |
|
| 1020 |
name = "refine", |
|
| 1021 | ! |
def = function(object, ...) standardGeneric("refine")
|
| 1022 |
) |
|
| 1023 | ||
| 1024 |
## Assess ---------------------------------------------------------------------- |
|
| 1025 |
#' Statistical Significance of Seriation Solutions |
|
| 1026 |
#' |
|
| 1027 |
#' Tests the significance of seriation solutions. |
|
| 1028 |
#' @param object A [`PermutationOrder-class`] object giving the permutation |
|
| 1029 |
#' order for rows and columns (typically returned by [seriate_average()]). |
|
| 1030 |
#' @param axes An [`integer`] vector giving the subscripts of the CA axes to be |
|
| 1031 |
#' used. |
|
| 1032 |
#' @param n A non-negative [`integer`] giving the number of bootstrap |
|
| 1033 |
#' replications. |
|
| 1034 |
#' @param progress A [`logical`] scalar: should a progress bar be displayed? |
|
| 1035 |
#' @param ... Currently not used. |
|
| 1036 |
#' @return |
|
| 1037 |
#' A [`list`] with the following elements: |
|
| 1038 |
#' \describe{
|
|
| 1039 |
#' \item{`random`}{A [`numeric`] vector giving the randomized total number of
|
|
| 1040 |
#' modes values.} |
|
| 1041 |
#' \item{`observed`}{A [`numeric`] value giving the observed total number of
|
|
| 1042 |
#' modes.} |
|
| 1043 |
#' \item{`expected`}{A [`numeric`] value giving the expected total number of
|
|
| 1044 |
#' modes if all types had unimodal distributions.} |
|
| 1045 |
#' \item{`maximum`}{A [`numeric`] value giving the maximum total number of
|
|
| 1046 |
#' modes.} |
|
| 1047 |
#' \item{`coef`}{A [`numeric`] value giving the seriation coefficient (a value
|
|
| 1048 |
#' close to 1 indicates a strong fit to the seriation model, while a value |
|
| 1049 |
#' close to 0 indicates a poor fit).} |
|
| 1050 |
#' } |
|
| 1051 |
#' @references |
|
| 1052 |
#' Porčić, M. (2013). The Goodness of Fit and Statistical Significance of |
|
| 1053 |
#' Seriation Solutions. *Journal of Archaeological Science*, 40(12): 4552-4559. |
|
| 1054 |
#' \doi{10.1016/j.jas.2013.07.013}.
|
|
| 1055 |
#' @example inst/examples/ex-assess.R |
|
| 1056 |
#' @author N. Frerebeau |
|
| 1057 |
#' @docType methods |
|
| 1058 |
#' @family seriation methods |
|
| 1059 |
#' @aliases assess-method |
|
| 1060 |
setGeneric( |
|
| 1061 |
name = "assess", |
|
| 1062 | 1x |
def = function(object, ...) standardGeneric("assess")
|
| 1063 |
) |
|
| 1064 | ||
| 1065 |
## Permute --------------------------------------------------------------------- |
|
| 1066 |
#' Rearrange a Data Matrix |
|
| 1067 |
#' |
|
| 1068 |
#' Rearranges a data matrix according to a permutation order. |
|
| 1069 |
#' @param object A \eqn{m \times p}{m x p} `numeric` [`matrix`] or
|
|
| 1070 |
#' [`data.frame`] of count data (absolute frequencies giving the number of |
|
| 1071 |
#' individuals for each category, i.e. a contingency table). |
|
| 1072 |
#' @param order A [`PermutationOrder-class`] object giving the permutation |
|
| 1073 |
#' order for rows and columns. |
|
| 1074 |
#' @param ... Currently not used. |
|
| 1075 |
#' @return |
|
| 1076 |
#' A permuted `matrix` or a permuted `data.frame` (the same as `object`). |
|
| 1077 |
#' @example inst/examples/ex-seriation.R |
|
| 1078 |
#' @author N. Frerebeau |
|
| 1079 |
#' @family seriation methods |
|
| 1080 |
#' @docType methods |
|
| 1081 |
#' @aliases permute-method |
|
| 1082 |
setGeneric( |
|
| 1083 |
name = "permute", |
|
| 1084 | 3x |
def = function(object, order, ...) standardGeneric("permute")
|
| 1085 |
) |
|
| 1086 | ||
| 1087 |
#' Permutation Order |
|
| 1088 |
#' |
|
| 1089 |
#' Returns the seriation order for rows and/or columns. |
|
| 1090 |
#' @param object A [`PermutationOrder-class`] object giving the permutation |
|
| 1091 |
#' order for rows and columns. |
|
| 1092 |
#' @param ... Currently not used. |
|
| 1093 |
#' @return |
|
| 1094 |
#' An [`integer`] vector. |
|
| 1095 |
#' @example inst/examples/ex-seriation.R |
|
| 1096 |
#' @author N. Frerebeau |
|
| 1097 |
#' @family seriation methods |
|
| 1098 |
#' @docType methods |
|
| 1099 |
#' @name order |
|
| 1100 |
#' @rdname order |
|
| 1101 |
NULL |
|
| 1102 | ||
| 1103 |
#' @rdname order |
|
| 1104 |
#' @aliases order_rows-method |
|
| 1105 |
setGeneric( |
|
| 1106 |
name = "order_rows", |
|
| 1107 | 6x |
def = function(object, ...) standardGeneric("order_rows")
|
| 1108 |
) |
|
| 1109 | ||
| 1110 |
#' @rdname order |
|
| 1111 |
#' @aliases order_columns-method |
|
| 1112 |
setGeneric( |
|
| 1113 |
name = "order_columns", |
|
| 1114 | 7x |
def = function(object, ...) standardGeneric("order_columns")
|
| 1115 |
) |
| 1 |
# EVENT MODEL |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @method summary EventDate |
|
| 7 |
summary.EventDate <- function(object, ...) {
|
|
| 8 | 1x |
summary(object@model, ...) |
| 9 |
} |
|
| 10 | ||
| 11 |
#' @export |
|
| 12 |
#' @rdname model_event |
|
| 13 |
#' @aliases summary,EventDate,missing-method |
|
| 14 |
setMethod("summary", c(object = "EventDate"), summary.EventDate)
|
|
| 15 | ||
| 16 |
#' @method coef EventDate |
|
| 17 |
#' @export |
|
| 18 |
coef.EventDate <- function(object, calendar = NULL, ...) {
|
|
| 19 | ! |
z <- stats::coef(object@model, ...) |
| 20 | ! |
if (is.null(calendar)) return(z) |
| 21 | ! |
unclass(z) / aion::calendar_year(calendar) # Approximate |
| 22 |
} |
|
| 23 | ||
| 24 |
#' @export |
|
| 25 |
#' @rdname model_event |
|
| 26 |
#' @aliases coef,EventDate-method |
|
| 27 |
setMethod("coef", "EventDate", coef.EventDate)
|
|
| 28 | ||
| 29 |
#' @method fitted EventDate |
|
| 30 |
#' @export |
|
| 31 |
fitted.EventDate <- function(object, calendar = NULL, ...) {
|
|
| 32 | ! |
z <- stats::fitted(object@model, ...) |
| 33 | ! |
if (is.null(calendar)) return(z) |
| 34 | ! |
aion::as_year(z, calendar = calendar) |
| 35 |
} |
|
| 36 | ||
| 37 |
#' @export |
|
| 38 |
#' @rdname model_event |
|
| 39 |
#' @aliases fitted,EventDate-method |
|
| 40 |
setMethod("fitted", "EventDate", fitted.EventDate)
|
|
| 41 | ||
| 42 |
#' @method residuals EventDate |
|
| 43 |
#' @export |
|
| 44 |
residuals.EventDate <- function(object, calendar = NULL, ...) {
|
|
| 45 | ! |
z <- stats::residuals(object@model, ...) |
| 46 | ! |
if (is.null(calendar)) return(z) |
| 47 | ! |
unclass(z) / aion::calendar_year(calendar) # Approximate |
| 48 |
} |
|
| 49 | ||
| 50 |
#' @export |
|
| 51 |
#' @rdname model_event |
|
| 52 |
#' @aliases residuals,EventDate-method |
|
| 53 |
setMethod("residuals", "EventDate", residuals.EventDate)
|
|
| 54 | ||
| 55 |
#' @method sigma EventDate |
|
| 56 |
#' @export |
|
| 57 |
sigma.EventDate <- function(object, calendar = NULL, ...) {
|
|
| 58 | ! |
z <- stats::sigma(object@model, ...) |
| 59 | ! |
if (is.null(calendar)) return(z) |
| 60 | ! |
unclass(z) / aion::calendar_year(calendar) # Approximate |
| 61 |
} |
|
| 62 | ||
| 63 |
#' @export |
|
| 64 |
#' @rdname model_event |
|
| 65 |
#' @aliases sigma,EventDate-method |
|
| 66 |
setMethod("sigma", "EventDate", sigma.EventDate)
|
|
| 67 | ||
| 68 |
#' @method terms EventDate |
|
| 69 |
#' @export |
|
| 70 | ! |
terms.EventDate <- function(x, ...) stats::terms(x@model, ...) |
| 71 | ||
| 72 |
#' @export |
|
| 73 |
#' @rdname model_event |
|
| 74 |
#' @aliases terms,EventDate-method |
|
| 75 |
setMethod("terms", "EventDate", terms.EventDate)
|
| 1 |
# PLOT LINE |
|
| 2 |
#' @include AllClasses.R AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# data.frame =================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname plot_time |
|
| 8 |
#' @aliases plot_time,data.frame,numeric-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "plot_time", |
|
| 11 |
signature = c(object = "data.frame", dates = "numeric"), |
|
| 12 |
definition = function(object, dates, |
|
| 13 |
calendar = get_calendar(), ...) {
|
|
| 14 | 1x |
object <- data.matrix(object) |
| 15 | 1x |
methods::callGeneric(object, dates = dates, calendar = calendar, ...) |
| 16 | 1x |
invisible(object) |
| 17 |
} |
|
| 18 |
) |
|
| 19 | ||
| 20 |
# matrix ======================================================================= |
|
| 21 |
#' @export |
|
| 22 |
#' @rdname plot_time |
|
| 23 |
#' @aliases plot_time,matrix,numeric-method |
|
| 24 |
setMethod( |
|
| 25 |
f = "plot_time", |
|
| 26 |
signature = c(object = "matrix", dates = "numeric"), |
|
| 27 |
definition = function(object, dates, |
|
| 28 |
calendar = get_calendar(), ...) {
|
|
| 29 |
## Validation |
|
| 30 | 1x |
arkhe::assert_type(dates, "numeric") |
| 31 | 1x |
arkhe::assert_length(dates, nrow(object)) |
| 32 | ||
| 33 |
## Convert to rata die |
|
| 34 | 1x |
if (is.null(calendar)) {
|
| 35 | ! |
dates <- aion::as_fixed(dates) |
| 36 |
} else {
|
|
| 37 | 1x |
dates <- aion::fixed(dates, calendar = calendar) |
| 38 |
} |
|
| 39 | ||
| 40 |
## Prepare data |
|
| 41 | 1x |
ts <- aion::series(object = object, time = dates) |
| 42 | ||
| 43 |
## Plot |
|
| 44 | 1x |
aion::plot(x = ts, calendar = calendar, ...) |
| 45 | ||
| 46 | 1x |
invisible(object) |
| 47 |
} |
|
| 48 |
) |
| 1 |
# MUTATORS |
|
| 2 |
#' @include AllClasses.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Getters ====================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname series |
|
| 8 |
#' @aliases time,EventDate-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "time", |
|
| 11 |
signature = "EventDate", |
|
| 12 |
definition = function(x, calendar = NULL) {
|
|
| 13 | ! |
z <- x@dates |
| 14 | ! |
if (is.null(calendar)) return(z) |
| 15 | ! |
aion::as_year(z, calendar = calendar, decimal = TRUE) |
| 16 |
} |
|
| 17 |
) |
|
| 18 | ||
| 19 |
#' @export |
|
| 20 |
#' @rdname series |
|
| 21 |
#' @aliases span,AoristicSum-method |
|
| 22 |
setMethod( |
|
| 23 |
f = "span", |
|
| 24 |
signature = "AoristicSum", |
|
| 25 |
definition = function(x, calendar = NULL) {
|
|
| 26 | 1x |
z <- x@span |
| 27 | 1x |
if (is.null(calendar)) return(unclass(z)) |
| 28 | ! |
aion::as_year(z, calendar = calendar, shift = FALSE) |
| 29 |
} |
|
| 30 |
) |
|
| 31 | ||
| 32 |
#' @export |
|
| 33 |
#' @rdname mutators |
|
| 34 |
#' @aliases weights,AoristicSum-method |
|
| 35 | 2x |
setMethod("weights", "AoristicSum", function(object, ...) object@p)
|
| 36 | ||
| 37 |
#' @export |
|
| 38 |
#' @rdname mutators |
|
| 39 |
#' @aliases weights,CountApportion-method |
|
| 40 | ! |
setMethod("weights", "CountApportion", function(object, ...) object@p)
|
| 41 | ||
| 42 |
# Setters ====================================================================== |
| 1 |
#' @include AllClasses.R AllGenerics.R |
|
| 2 |
NULL |
|
| 3 | ||
| 4 |
#' @export |
|
| 5 |
#' @rdname assess |
|
| 6 |
#' @aliases assess,AveragePermutationOrder-method |
|
| 7 |
setMethod( |
|
| 8 |
f = "assess", |
|
| 9 |
signature = c(object = "AveragePermutationOrder"), |
|
| 10 |
definition = function(object, axes = 1, n = 1000, |
|
| 11 |
progress = getOption("kairos.progress")) {
|
|
| 12 |
## Validation |
|
| 13 | 1x |
arkhe::assert_length(axes, 1) |
| 14 | 1x |
arkhe::assert_length(n, 1) |
| 15 | ||
| 16 |
## Reorder along 'axes' |
|
| 17 | 1x |
data <- dimensio::get_data(object) |
| 18 | 1x |
perm <- permute(data, object) |
| 19 | ||
| 20 |
## Number of local maxima |
|
| 21 | 1x |
freq <- data / rowSums(data) |
| 22 | 1x |
a <- sum(apply(X = freq, MARGIN = 2, FUN = local_maxima)) |
| 23 | ||
| 24 | 1x |
b <- numeric(n) |
| 25 | 1x |
if (n > 0) {
|
| 26 | ! |
progress_bar <- interactive() && isTRUE(progress) |
| 27 | ! |
if (progress_bar) pbar <- utils::txtProgressBar(max = n, style = 3) |
| 28 | ||
| 29 | ! |
for (i in seq_len(n)) {
|
| 30 |
## Randomize original data |
|
| 31 | ! |
i_obj <- apply(X = data, MARGIN = 2, FUN = sample, replace = FALSE) |
| 32 | ||
| 33 |
## Number of local maxima |
|
| 34 | ! |
i_ca <- seriate_average(i_obj, margin = c(1, 2), axes = axes) |
| 35 | ! |
i_perm <- permute(i_obj, i_ca) |
| 36 | ! |
i_freq <- i_perm / rowSums(i_perm) |
| 37 | ||
| 38 | ! |
b[[i]] <- sum(apply(X = i_freq, MARGIN = 2, FUN = local_maxima)) |
| 39 | ||
| 40 | ! |
if (progress_bar) utils::setTxtProgressBar(pbar, i) |
| 41 |
} |
|
| 42 | ||
| 43 | ! |
if (progress_bar) close(pbar) |
| 44 |
} |
|
| 45 | ||
| 46 |
## Seriation coefficient |
|
| 47 | 1x |
E <- ncol(data) |
| 48 | 1x |
M <- nrow(data) * ifelse(E%%2 > 0, E + 1, E) / 2 |
| 49 | 1x |
S <- (M - a) / (M - E) |
| 50 | ||
| 51 | 1x |
list( |
| 52 | 1x |
random = b, |
| 53 | 1x |
observed = a, |
| 54 | 1x |
expected = E, |
| 55 | 1x |
maximum = M, |
| 56 | 1x |
coef = S |
| 57 |
) |
|
| 58 |
} |
|
| 59 |
) |
|
| 60 | ||
| 61 |
local_maxima <- function(x) {
|
|
| 62 | 16x |
n <- length(x) |
| 63 | 16x |
left <- c(0, x[-n]) |
| 64 | 16x |
right <- c(x[-1L], 0) |
| 65 | 16x |
sum(x > left & x > right) |
| 66 |
} |
| 1 |
# BOOTSTRAP |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# MeanDate ===================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname bootstrap.MeanDate |
|
| 8 |
#' @aliases bootstrap,MeanDate-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "bootstrap", |
|
| 11 |
signature = c(object = "MeanDate"), |
|
| 12 |
definition = function(object, n = 1000, f = NULL, level = 0.95, |
|
| 13 |
interval = c("basic", "normal", "percentiles"),
|
|
| 14 |
seed = NULL, calendar = get_calendar()) {
|
|
| 15 |
## Validation |
|
| 16 | ! |
interval <- match.arg(interval, several.ok = FALSE) |
| 17 | ||
| 18 |
## Seed |
|
| 19 | ! |
if (!exists(".Random.seed", envir = .GlobalEnv, inherits = FALSE))
|
| 20 | ! |
stats::runif(1) |
| 21 | ! |
if (is.null(seed)) {
|
| 22 | ! |
RNGstate <- get(".Random.seed", envir = .GlobalEnv)
|
| 23 |
} else {
|
|
| 24 | ! |
R.seed <- get(".Random.seed", envir = .GlobalEnv)
|
| 25 | ! |
set.seed(seed) |
| 26 | ! |
RNGstate <- structure(seed, kind = as.list(RNGkind())) |
| 27 | ! |
on.exit(assign(".Random.seed", R.seed, envir = .GlobalEnv))
|
| 28 |
} |
|
| 29 | ||
| 30 | ! |
m <- nrow(object) |
| 31 | ! |
p <- ncol(object) |
| 32 | ! |
seq_col <- seq_len(p) |
| 33 | ! |
dates <- aion::as_year(object@dates, calendar = calendar) |
| 34 | ||
| 35 | ! |
results <- vector(mode = "list", length = m) |
| 36 | ! |
for (i in seq_len(m)) {
|
| 37 | ! |
hat <- .mcd(object[i, , 1, drop = TRUE], dates) |
| 38 | ! |
spl <- t(arkhe::resample_multinomial(object[i, , 1, drop = TRUE], n = n)) |
| 39 | ! |
res <- apply(X = spl, MARGIN = 2, FUN = .mcd, dates = dates) |
| 40 | ! |
if (is.function(f)) {
|
| 41 | ! |
results[[i]] <- f(res) |
| 42 |
} else {
|
|
| 43 | ! |
results[[i]] <- summary_bootstrap(res, hat, level = level, interval = interval) |
| 44 |
} |
|
| 45 |
} |
|
| 46 | ||
| 47 | ! |
results <- do.call(rbind, results) |
| 48 | ! |
results <- as.data.frame(results) |
| 49 | ! |
rownames(results) <- rownames(object) |
| 50 | ! |
attr(results, "seed") <- RNGstate |
| 51 | ! |
results |
| 52 |
} |
|
| 53 |
) |
|
| 54 | ||
| 55 |
summary_bootstrap <- function(x, hat, level = 0.95, interval = "basic") {
|
|
| 56 | ! |
n <- length(x) |
| 57 | ! |
boot_mean <- mean(x) |
| 58 | ! |
boot_bias <- boot_mean - hat |
| 59 | ! |
boot_error <- stats::sd(x) |
| 60 | ||
| 61 | ! |
ci <- arkhe::confidence_bootstrap(x, level = level, t0 = hat, type = interval) |
| 62 | ! |
results <- c(hat, boot_mean, boot_bias, boot_error, ci) |
| 63 | ! |
names(results) <- c("original", "mean", "bias", "error", "lower", "upper")
|
| 64 | ! |
results |
| 65 |
} |
|
| 66 | ||
| 67 |
# EventDate ==================================================================== |
|
| 68 |
#' @export |
|
| 69 |
#' @rdname bootstrap.EventDate |
|
| 70 |
#' @aliases bootstrap,EventDate-method |
|
| 71 |
setMethod( |
|
| 72 |
f = "bootstrap", |
|
| 73 |
signature = c(object = "EventDate"), |
|
| 74 |
definition = function(object, level = 0.95, probs = c(0.05, 0.95), n = 1000, |
|
| 75 |
calendar = get_calendar(), |
|
| 76 |
progress = getOption("kairos.progress"), ...) {
|
|
| 77 |
## Get data |
|
| 78 | ! |
fit_model <- object@model |
| 79 | ! |
fit_dim <- object@keep |
| 80 | ||
| 81 |
## Partial bootstrap CA |
|
| 82 |
## /!\ Be careful: EventDate inherits from CA |
|
| 83 | ! |
ca_boot <- methods::callNextMethod(object, n = n) |
| 84 | ! |
ca_rep_row <- dimensio::get_replications(ca_boot, margin = 1) |
| 85 | ||
| 86 |
## Bootstrap assemblages |
|
| 87 | ! |
event_rows <- apply( |
| 88 | ! |
X = ca_rep_row, |
| 89 | ! |
MARGIN = 1, |
| 90 | ! |
FUN = function(x, axes, model, level, probs) {
|
| 91 | ! |
compute_date_boot(t(x), axes, model, level, probs) |
| 92 |
}, |
|
| 93 | ! |
axes = fit_dim, |
| 94 | ! |
model = fit_model, |
| 95 | ! |
level = level, |
| 96 | ! |
probs = probs |
| 97 |
) |
|
| 98 | ||
| 99 | ! |
results <- as.data.frame(t(event_rows)) |
| 100 | ! |
if (is.null(calendar)) return(results) |
| 101 | ||
| 102 | ! |
results[] <- lapply( |
| 103 | ! |
X = results, |
| 104 | ! |
FUN = aion::as_year, |
| 105 | ! |
calendar = calendar, |
| 106 | ! |
decimal = TRUE |
| 107 |
) |
|
| 108 | ! |
results |
| 109 |
} |
|
| 110 |
) |
|
| 111 | ||
| 112 |
#' Bootstrap Resampling of Assemblages |
|
| 113 |
#' |
|
| 114 |
#' Computes date event bootstraped statistics for each replicated sample. |
|
| 115 |
#' @param x A [`numeric`] matrix of bootstrap replicates. |
|
| 116 |
#' @param axes A [`numeric`] vector giving the subscripts of the CA components |
|
| 117 |
#' to keep. |
|
| 118 |
#' @param model An object of class [`lm`][stats::lm()]. |
|
| 119 |
#' @param level A length-one [`numeric`] vector giving the confidence level. |
|
| 120 |
#' @param probs A [`numeric`] vector of probabilities with values in \eqn{[0,1]}
|
|
| 121 |
#' (see [stats::quantile()]). |
|
| 122 |
#' @return A [`numeric`] vector with the following elements: |
|
| 123 |
#' \describe{
|
|
| 124 |
#' \item{`min`}{Minimum value.}
|
|
| 125 |
#' \item{`mean`}{Mean value (event date).}
|
|
| 126 |
#' \item{`max`}{Maximum value.}
|
|
| 127 |
#' \item{`Q05`}{Sample quantile to 0.05 probability.}
|
|
| 128 |
#' \item{`Q95`}{Sample quantile to 0.95 probability.}
|
|
| 129 |
#' } |
|
| 130 |
#' @author N. Frerebeau |
|
| 131 |
#' @keywords internal |
|
| 132 |
#' @noRd |
|
| 133 |
compute_date_boot <- function(x, axes, model, level, probs = c(0.05, 0.95)) {
|
|
| 134 |
## Remove missing values |
|
| 135 | ! |
coords <- stats::na.omit(x[, axes]) |
| 136 | ||
| 137 |
## Gaussian multiple linear regression model |
|
| 138 | ! |
event <- compute_event(model, coords, level)[, 1] |
| 139 | ! |
Q <- stats::quantile(event, probs = probs, names = FALSE) |
| 140 | ||
| 141 | ! |
distrib <- c(min(event), mean(event), max(event), Q) |
| 142 | ! |
quant <- paste0("Q", round(probs * 100, 0))
|
| 143 | ! |
names(distrib) <- c("min", "mean", "max", quant)
|
| 144 | ! |
return(distrib) |
| 145 |
} |
| 1 |
#' @include AllClasses.R AllGenerics.R |
|
| 2 |
NULL |
|
| 3 | ||
| 4 |
#' @export |
|
| 5 |
#' @rdname seriate_rank |
|
| 6 |
#' @aliases seriate_rank,data.frame-method |
|
| 7 |
setMethod( |
|
| 8 |
f = "seriate_rank", |
|
| 9 |
signature = c(object = "data.frame"), |
|
| 10 |
definition = function(object, EPPM = FALSE, margin = c(1, 2), stop = 100) {
|
|
| 11 | 4x |
object <- data.matrix(object) |
| 12 | 4x |
methods::callGeneric(object, EPPM = EPPM, margin = margin, stop = stop) |
| 13 |
} |
|
| 14 |
) |
|
| 15 | ||
| 16 |
#' @export |
|
| 17 |
#' @rdname seriate_rank |
|
| 18 |
#' @aliases seriate_rank,matrix-method |
|
| 19 |
setMethod( |
|
| 20 |
f = "seriate_rank", |
|
| 21 |
signature = c(object = "matrix"), |
|
| 22 |
definition = function(object, EPPM = FALSE, margin = c(1, 2), stop = 100) {
|
|
| 23 |
## Validation |
|
| 24 | 5x |
margin <- as.integer(margin) |
| 25 | 5x |
stop <- as.integer(stop) |
| 26 | ||
| 27 | 5x |
data <- object |
| 28 | 1x |
if (EPPM) data <- tabula::eppm(object) |
| 29 | ||
| 30 |
## Compute ranks |
|
| 31 |
## margin = 1 : on rows |
|
| 32 |
## margin = 2 : on columns |
|
| 33 | 5x |
reorder <- function(x, margin) {
|
| 34 | 11x |
i <- seq_len(nrow(x)) |
| 35 | 11x |
j <- seq_len(ncol(x)) |
| 36 | 4x |
if (margin == 1) k <- colSums(t(x) * j) / rowSums(x) |
| 37 | 7x |
if (margin == 2) k <- colSums(x * i) / colSums(x) |
| 38 | 11x |
order(k) |
| 39 |
} |
|
| 40 | ||
| 41 | 5x |
start <- 0 |
| 42 | 5x |
index <- list(rows = seq_len(nrow(data)), columns = seq_len(ncol(data))) |
| 43 | 5x |
convergence <- FALSE |
| 44 | 5x |
while (!convergence) {
|
| 45 | 9x |
old_index <- index |
| 46 |
# Rearrange along margins |
|
| 47 | 9x |
for (k in margin) {
|
| 48 | 11x |
index[[k]] <- index[[k]][reorder(data[index[[1]], index[[2]]], margin = k)] |
| 49 |
} |
|
| 50 |
# Loop counter |
|
| 51 | 9x |
convergence <- identical(index, old_index) |
| 52 | 9x |
start <- start + 1 |
| 53 | 9x |
if (start >= stop) {
|
| 54 | 1x |
msg <- tr_("Convergence not reached (possible infinite loop).")
|
| 55 | 1x |
warning(msg, call. = FALSE) |
| 56 | 1x |
break |
| 57 |
} |
|
| 58 |
} |
|
| 59 | ||
| 60 |
# New PermutationOrder object |
|
| 61 | 5x |
.RankPermutationOrder( |
| 62 | 5x |
rows_order = as.integer(index[[1]]), |
| 63 | 5x |
columns_order = as.integer(index[[2]]) |
| 64 |
) |
|
| 65 |
} |
|
| 66 |
) |
| 1 |
#' @include AllClasses.R AllGenerics.R |
|
| 2 |
NULL |
|
| 3 | ||
| 4 |
#' @export |
|
| 5 |
#' @rdname as_seriation |
|
| 6 |
#' @aliases as_seriation,CA-method |
|
| 7 |
setMethod( |
|
| 8 |
f = "as_seriation", |
|
| 9 |
signature = c(object = "CA"), |
|
| 10 |
definition = function(object, margin = c(1, 2), axes = 1) {
|
|
| 11 |
## Validation |
|
| 12 | 1x |
arkhe::assert_length(axes, 1) |
| 13 | ||
| 14 | 1x |
margin <- as.integer(margin) |
| 15 | 1x |
axes <- as.integer(axes) |
| 16 | ||
| 17 |
## Original sequences |
|
| 18 | 1x |
data <- dimensio::get_data(object) |
| 19 | 1x |
i <- seq_len(nrow(data)) |
| 20 | 1x |
j <- seq_len(ncol(data)) |
| 21 | ||
| 22 |
## Correspondence analysis |
|
| 23 | 1x |
rows <- dimensio::get_coordinates(object, margin = 1) |
| 24 | 1x |
cols <- dimensio::get_coordinates(object, margin = 2) |
| 25 | ||
| 26 |
## Reorder in case if supplementary observations |
|
| 27 | 1x |
rows <- rows[order(object@rows@order), ] |
| 28 | 1x |
cols <- cols[order(object@columns@order), ] |
| 29 | ||
| 30 |
## Seriation order |
|
| 31 | 1x |
row_coords <- if (any(margin == 1)) order(rows[, axes]) else i |
| 32 | 1x |
col_coords <- if (any(margin == 2)) order(cols[, axes]) else j |
| 33 | ||
| 34 |
## New PermutationOrder object |
|
| 35 | 1x |
.AveragePermutationOrder( |
| 36 | 1x |
object, |
| 37 | 1x |
rows_order = as.integer(row_coords), |
| 38 | 1x |
columns_order = as.integer(col_coords) |
| 39 |
) |
|
| 40 |
} |
|
| 41 |
) |
| 1 |
# JACKKNIFE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# MeanDate ===================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname jackknife.MeanDate |
|
| 8 |
#' @aliases jackknife,MeanDate-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "jackknife", |
|
| 11 |
signature = c(object = "MeanDate"), |
|
| 12 |
definition = function(object, f = NULL, calendar = get_calendar()) {
|
|
| 13 | ||
| 14 | ! |
w <- object |
| 15 | ! |
m <- nrow(w) |
| 16 | ! |
p <- ncol(w) |
| 17 | ||
| 18 | ! |
dates <- aion::as_year(object@dates, calendar = calendar) |
| 19 | ! |
theta <- function(x, counts, dates) {
|
| 20 | ! |
.mcd(counts[x], dates[x]) |
| 21 |
} |
|
| 22 | ||
| 23 | ! |
results <- vector(mode = "list", length = m) |
| 24 | ! |
for (i in seq_len(m)) {
|
| 25 | ! |
results[[i]] <- arkhe::jackknife( |
| 26 | ! |
object = seq_len(p), |
| 27 | ! |
do = theta, |
| 28 | ! |
counts = w[i, , 1, drop = TRUE], |
| 29 | ! |
dates = dates, |
| 30 | ! |
f = f |
| 31 |
) |
|
| 32 |
} |
|
| 33 | ! |
results <- do.call(rbind, results) |
| 34 | ! |
results <- as.data.frame(results) |
| 35 | ! |
rownames(results) <- rownames(w) |
| 36 | ! |
results |
| 37 |
} |
|
| 38 |
) |
|
| 39 | ||
| 40 |
# EventDate ==================================================================== |
|
| 41 |
#' @export |
|
| 42 |
#' @rdname jackknife.EventDate |
|
| 43 |
#' @aliases jackknife,EventDate-method |
|
| 44 |
setMethod( |
|
| 45 |
f = "jackknife", |
|
| 46 |
signature = c(object = "EventDate"), |
|
| 47 |
definition = function(object, level = 0.95, |
|
| 48 |
calendar = get_calendar(), |
|
| 49 |
progress = getOption("kairos.progress"),
|
|
| 50 |
verbose = getOption("kairos.verbose"), ...) {
|
|
| 51 |
## Get data |
|
| 52 | ! |
fit_model <- object@model |
| 53 | ! |
fit_dates <- time(object) |
| 54 | ! |
fit_data <- dimensio::get_data(object) |
| 55 | ! |
fit_dim <- object@keep |
| 56 | ||
| 57 |
## Jackknife model coefficients |
|
| 58 | ! |
jack_values <- compute_date_jack( |
| 59 | ! |
x = fit_data, |
| 60 | ! |
dates = fit_dates, |
| 61 | ! |
rank = length(fit_dim), |
| 62 | ! |
progress = progress, |
| 63 | ! |
verbose = verbose |
| 64 |
) |
|
| 65 | ! |
jack_coef <- colMeans(jack_values) |
| 66 | ||
| 67 |
## Change lm coefficients (UGLY) |
|
| 68 | ! |
fit_model$coefficients <- jack_coef[c(1, fit_dim + 1)] |
| 69 | ||
| 70 |
## Predict event date for each context |
|
| 71 | ! |
row_coord <- dimensio::get_coordinates(object, margin = 1) |
| 72 | ! |
jack_event <- compute_event(fit_model, row_coord, level = level, error = FALSE) |
| 73 | ||
| 74 | ! |
results <- as.data.frame(jack_event) |
| 75 | ! |
if (!is.null(calendar)) {
|
| 76 | ! |
results[] <- lapply( |
| 77 | ! |
X = results, |
| 78 | ! |
FUN = aion::as_year, |
| 79 | ! |
calendar = calendar, |
| 80 | ! |
decimal = TRUE |
| 81 |
) |
|
| 82 |
} |
|
| 83 | ! |
results |
| 84 |
} |
|
| 85 |
) |
|
| 86 | ||
| 87 |
#' Jackknife Fabrics |
|
| 88 |
#' |
|
| 89 |
#' Compute date event jackknifed statistics for each replicated sample. |
|
| 90 |
#' @param x A [`numeric`] matrix of count data. |
|
| 91 |
#' @param dates A [`numeric`] vector of known dates. |
|
| 92 |
#' @param rank A [`numeric`] value. |
|
| 93 |
#' @param progress A [`logical`] scalar: should a progress bar be displayed? |
|
| 94 |
#' @param ... Currently not used]. |
|
| 95 |
#' @return A `numeric` [`matrix`] of linear model coefficients. |
|
| 96 |
#' @author N. Frerebeau |
|
| 97 |
#' @keywords internal |
|
| 98 |
#' @noRd |
|
| 99 |
compute_date_jack <- function(x, dates, rank = 10, |
|
| 100 |
progress = FALSE, verbose = FALSE, ...) {
|
|
| 101 | ! |
m <- ncol(x) |
| 102 | ! |
k <- seq_len(m) |
| 103 | ! |
jack <- vector(mode = "list", length = m) |
| 104 | ||
| 105 | ! |
progress_bar <- interactive() && isTRUE(progress) |
| 106 | ! |
if (progress_bar) pbar <- utils::txtProgressBar(max = m, style = 3) |
| 107 | ||
| 108 | ! |
for (j in k) {
|
| 109 | ! |
counts <- x[, -j, drop = FALSE] |
| 110 | ! |
model <- event(counts, dates = dates, calendar = NULL, rank = rank, verbose = verbose) |
| 111 | ! |
jack[[j]] <- coef(model, calendar = NULL) # Get model coefficients |
| 112 | ! |
if (progress_bar) utils::setTxtProgressBar(pbar, j) |
| 113 |
} |
|
| 114 | ||
| 115 | ! |
if (progress_bar) close(pbar) |
| 116 | ! |
do.call(rbind, jack) |
| 117 |
} |
| 1 |
# HELPERS |
|
| 2 | ||
| 3 |
## https://michaelchirico.github.io/potools/articles/developers.html |
|
| 4 |
tr_ <- function(...) {
|
|
| 5 | 2x |
enc2utf8(gettext(paste0(...), domain = "R-kairos")) |
| 6 |
} |
|
| 7 | ||
| 8 |
make_par <- function(params, x, n = 0) {
|
|
| 9 | ! |
p <- params[[x]] %||% graphics::par()[[x]] |
| 10 | ! |
if (n > 0) p <- rep(p, length.out = n) |
| 11 | ! |
p |
| 12 |
} |
|
| 13 | ||
| 14 |
#' Plotting Dimensions of Character Strings |
|
| 15 |
#' |
|
| 16 |
#' Convert string length in inch to number of (margin) lines. |
|
| 17 |
#' @param x A [`character`] vector of string whose length is to be calculated. |
|
| 18 |
#' @param ... Further parameter to be passed to [graphics::strwidth()]`, such as |
|
| 19 |
#' `cex`. |
|
| 20 |
#' @return |
|
| 21 |
#' A [`numeric`] vector (maximum string width in units of margin lines). |
|
| 22 |
#' @note For internal use only. |
|
| 23 |
#' @family graphic tools |
|
| 24 |
#' @keywords internal |
|
| 25 |
#' @noRd |
|
| 26 |
inch2line <- function(x, ...) {
|
|
| 27 | 2x |
(max(graphics::strwidth(x, units = "inch", ...)) / |
| 28 | 2x |
graphics::par("cin")[2] + graphics::par("mgp")[2]) * graphics::par("cex")
|
| 29 |
} |
|
| 30 | ||
| 31 |
#' Compute x Limits |
|
| 32 |
#' |
|
| 33 |
#' Computes x limits for a time series according to a given calendar. |
|
| 34 |
#' This ensures that the x axis is always in chronological order. |
|
| 35 |
#' @param x A [`TimeSeries-class`] object. |
|
| 36 |
#' @param calendar A [`TimeScale-class`] object. |
|
| 37 |
#' @return A length-two [`numeric`] vector. |
|
| 38 |
#' @keywords internal |
|
| 39 |
#' @noRd |
|
| 40 |
xlim <- function(x, calendar) {
|
|
| 41 | ! |
x <- range(time(x, calendar = NULL)) |
| 42 | ! |
if (is.null(calendar)) return(x) |
| 43 | ! |
as_year(x, calendar = calendar) |
| 44 |
} |
|
| 45 | ||
| 46 |
#' Indices of a rolling window |
|
| 47 |
#' |
|
| 48 |
#' @param x An object. |
|
| 49 |
#' @param window An [`integer`] scalar giving the window size. |
|
| 50 |
#' @return A [`list`] with the following components: |
|
| 51 |
#' \describe{
|
|
| 52 |
#' \item{i}{An [`integer`] vector of indices.}
|
|
| 53 |
#' \item{w}{An [`integer`] vector of indices giving the indice of the window
|
|
| 54 |
#' mid-point.} |
|
| 55 |
#' } |
|
| 56 |
#' @keywords internal |
|
| 57 |
#' @noRd |
|
| 58 |
roll <- function(x, window = 3) {
|
|
| 59 |
## Validation |
|
| 60 | 1x |
arkhe::assert_odd(window) |
| 61 | ||
| 62 | 1x |
n <- if (is.matrix(x) || is.data.frame(x)) nrow(x) else length(x) |
| 63 | 1x |
i <- seq_len(n) # Indices of the rows |
| 64 | ||
| 65 |
## Matrix of rolling-window indices of length w |
|
| 66 | 1x |
w <- stats::embed(i, window)[, window:1] |
| 67 | 1x |
inds <- as.vector(t(w)) # Flatten indices |
| 68 | ||
| 69 |
## Window mid-point |
|
| 70 | 1x |
m <- w[, ceiling(window / 2)] |
| 71 | ||
| 72 | 1x |
list(i = inds, w = rep(m, each = window)) |
| 73 |
} |
|
| 74 | ||
| 75 |
#' Quantiles of a Density Estimate |
|
| 76 |
#' |
|
| 77 |
#' @param x A [`numeric`] vector giving the n coordinates of the points where |
|
| 78 |
#' the density is estimated. |
|
| 79 |
#' @param y A `numeric` [`matrix`] of density estimates (each column is a |
|
| 80 |
#' density estimate). |
|
| 81 |
#' @param probs A [`numeric`] vector of probabilities with values in |
|
| 82 |
#' \eqn{[0,1]}.
|
|
| 83 |
#' @param na.rm A [`logical`] scalar: should `NA` values be stripped before the |
|
| 84 |
#' computation proceeds? |
|
| 85 |
#' @param ... Currently not used. |
|
| 86 |
#' @return |
|
| 87 |
#' A `numeric` [`matrix`] containing the quantiles. |
|
| 88 |
#' @keywords internal |
|
| 89 |
#' @noRd |
|
| 90 |
quantile_density <- function(x, y, probs = seq(0, 1, 0.25), na.rm = FALSE, ...) {
|
|
| 91 | 1x |
eps <- 100 * .Machine$double.eps |
| 92 | 1x |
if (anyNA(probs) | any(probs < -eps | probs > 1 + eps)) |
| 93 | ! |
stop(sprintf("%s outside [0,1]", sQuote("probs")))
|
| 94 | ||
| 95 | 1x |
q <- apply( |
| 96 | 1x |
X = y, |
| 97 | 1x |
MARGIN = 2, |
| 98 | 1x |
FUN = function(y, x, probs, na.rm) {
|
| 99 | 420x |
np <- length(probs) |
| 100 | 420x |
qs <- rep(NA_real_, np) |
| 101 | 420x |
if (na.rm) {
|
| 102 | ! |
i <- !is.na(x) & !is.na(y) |
| 103 | ! |
x <- x[i] |
| 104 | ! |
y <- y[i] |
| 105 |
} |
|
| 106 | 420x |
if (np > 0) {
|
| 107 | 420x |
nn <- length(x) |
| 108 | 420x |
Fx <- cumsum(y * c(0, diff(x))) |
| 109 | 420x |
Fx <- Fx / Fx[nn] |
| 110 | 420x |
for (j in seq_len(np)) {
|
| 111 | 1260x |
ii <- min(which(Fx >= probs[j])) |
| 112 | 1260x |
if (!is.na(ii) && ii >= 1 && ii <= nn) qs[j] <- x[ii] |
| 113 |
} |
|
| 114 | 420x |
qs |
| 115 |
} |
|
| 116 |
}, |
|
| 117 | 1x |
x = x, |
| 118 | 1x |
probs = probs, |
| 119 | 1x |
na.rm = na.rm |
| 120 |
) |
|
| 121 | ||
| 122 | 1x |
if (!is.null(dim(q))) {
|
| 123 | 1x |
q <- t(q) |
| 124 | 1x |
colnames(q) <- paste0(round(probs * 100, digits = 0), "%") |
| 125 |
} |
|
| 126 | 1x |
q |
| 127 |
} |
| 1 |
#' @include AllClasses.R AllGenerics.R |
|
| 2 |
NULL |
|
| 3 | ||
| 4 |
#' @export |
|
| 5 |
#' @rdname permute |
|
| 6 |
#' @aliases permute,data.frame,PermutationOrder-method |
|
| 7 |
setMethod( |
|
| 8 |
f = "permute", |
|
| 9 |
signature = c(object = "data.frame", order = "PermutationOrder"), |
|
| 10 |
definition = function(object, order) {
|
|
| 11 |
# Rearrange data.frame |
|
| 12 | 2x |
object[order@rows_order, order@columns_order] |
| 13 |
} |
|
| 14 |
) |
|
| 15 | ||
| 16 |
#' @export |
|
| 17 |
#' @rdname permute |
|
| 18 |
#' @aliases permute,matrix,PermutationOrder-method |
|
| 19 |
setMethod( |
|
| 20 |
f = "permute", |
|
| 21 |
signature = c(object = "matrix", order = "PermutationOrder"), |
|
| 22 |
definition = function(object, order) {
|
|
| 23 |
# Rearrange matrix |
|
| 24 | 1x |
object[order@rows_order, order@columns_order] |
| 25 |
} |
|
| 26 |
) |
|
| 27 | ||
| 28 |
#' @export |
|
| 29 |
#' @rdname order |
|
| 30 |
#' @aliases order_rows,PermutationOrder-method |
|
| 31 |
setMethod( |
|
| 32 |
f = "order_rows", |
|
| 33 |
signature = c("PermutationOrder"),
|
|
| 34 | 6x |
definition = function(object) object@rows_order |
| 35 |
) |
|
| 36 | ||
| 37 |
#' @export |
|
| 38 |
#' @rdname order |
|
| 39 |
#' @aliases order_columns,PermutationOrder-method |
|
| 40 |
setMethod( |
|
| 41 |
f = "order_columns", |
|
| 42 |
signature = c("PermutationOrder"),
|
|
| 43 | 7x |
definition = function(object) object@columns_order |
| 44 |
) |
| 1 |
#' @include AllClasses.R AllGenerics.R |
|
| 2 |
NULL |
|
| 3 | ||
| 4 |
#' @export |
|
| 5 |
#' @rdname seriate_average |
|
| 6 |
#' @aliases seriate_average,data.frame-method |
|
| 7 |
setMethod( |
|
| 8 |
f = "seriate_average", |
|
| 9 |
signature = c(object = "data.frame"), |
|
| 10 |
definition = function(object, margin = c(1, 2), axes = 1, |
|
| 11 |
sup_row = NULL, sup_col = NULL, ...) {
|
|
| 12 | 2x |
object <- data.matrix(object) |
| 13 | 2x |
methods::callGeneric(object, margin = margin, axes = axes, |
| 14 | 2x |
sup_row = sup_row, sup_col = sup_col, ...) |
| 15 |
} |
|
| 16 |
) |
|
| 17 | ||
| 18 |
#' @export |
|
| 19 |
#' @rdname seriate_average |
|
| 20 |
#' @aliases seriate_average,matrix-method |
|
| 21 |
setMethod( |
|
| 22 |
f = "seriate_average", |
|
| 23 |
signature = c(object = "matrix"), |
|
| 24 |
definition = function(object, margin = c(1, 2), axes = 1, |
|
| 25 |
sup_row = NULL, sup_col = NULL, ...) {
|
|
| 26 |
## Correspondence analysis |
|
| 27 | 2x |
corresp <- dimensio::ca(object, sup_row = sup_row, sup_col = sup_col) |
| 28 | ||
| 29 |
## New PermutationOrder object |
|
| 30 | 1x |
as_seriation(corresp, margin = margin, axes = axes) |
| 31 |
} |
|
| 32 |
) |