| Title: | Transition Data Analysis |
|---|---|
| Description: | An R interface to 'TDA' 6.4, Goetz Rohwer's and Ulrich Poetter's program for transition data analysis, built into the package as a library. Its event history and transition rate models, regression, sequence, cluster, graph and spatial methods and its matrix language are available as R functions that take data frames and return R objects. The package keeps the program and its methods usable and documented, and reproduces results obtained with 'TDA'. |
| Authors: | Goetz Rohwer [aut, cph], Ulrich Poetter [aut, cph], Jan Marvin Garbuszus [aut, cre] |
| Maintainer: | Jan Marvin Garbuszus <[email protected]> |
| License: | GPL (>= 2) |
| Version: | 0.1.0 |
| Built: | 2026-09-20 11:01:12 UTC |
| Source: | https://github.com/JanMarvin/TDA |
Marks a set of columns, used inside a tda_qreg formula, as
the same underlying variable's value at each category of the response –
price for choice 1, choice 2, choice 3, say, one coefficient shared
across all of them – rather than the formula's ordinary
one-column-per-predictor, shared-across-categories shape. TDA's
"(Z1,Z2,...)" grouped variable-list syntax (what its source
calls "Z variables" or "generic variables"), reached
through R's Surv()-style formula convention (from the
survival package – not a dependency of this one, just the same
idea) instead of a separate argument.
lvl(...)lvl(...)
... |
one column per category of the response, in category order. |
lvl() is only meaningful inside a tda_qreg formula – it is
not a real transformation, just a marker tda_qreg looks for and
removes before fitting, the same way Surv() is not itself computed
by coxph(), only recognised by it.
A matrix, for model.matrix's benefit –
not meaningful on its own.
# Daganzo's classic mode-choice example (examples/exam/qr4.cf in TDA's # own sources): commute time by car (Z1), bus (Z2), and train (Z3), one # coefficient for time itself, shared across all three modes # (seeded synthetic version: choices generated from utility # -0.3 * time + Gumbel noise, so the estimate recovers about -0.3) set.seed(21) n <- 80 d <- data.frame(Z1 = runif(n, 5, 30), Z2 = runif(n, 5, 30), Z3 = runif(n, 5, 30)) u <- -0.3 * as.matrix(d) + matrix(-log(-log(runif(3 * n))), n) d$Y <- max.col(u) tda_qreg(Y ~ lvl(Z1, Z2, Z3), d, model = "multinomial_logit", nq = 3, intercept = FALSE)$estimates# Daganzo's classic mode-choice example (examples/exam/qr4.cf in TDA's # own sources): commute time by car (Z1), bus (Z2), and train (Z3), one # coefficient for time itself, shared across all three modes # (seeded synthetic version: choices generated from utility # -0.3 * time + Gumbel noise, so the estimate recovers about -0.3) set.seed(21) n <- 80 d <- data.frame(Z1 = runif(n, 5, 30), Z2 = runif(n, 5, 30), Z3 = runif(n, 5, 30)) u <- -0.3 * as.matrix(d) + matrix(-log(-log(runif(3 * n))), n) d$Y <- max.col(u) tda_qreg(Y ~ lvl(Z1, Z2, Z3), d, model = "multinomial_logit", nq = 3, intercept = FALSE)$estimates
TDA's graph-drawing command, pltree, only draws trees. For
anything else – a cycle, more than one component, or a directed graph –
this lays the nodes out on a circle and draws it with
tda_pl_graph instead, which takes explicit coordinates and
so can draw any graph.
## S3 method for class 'tda_graph' plot( x, width = 110, height = 80, file = "graph.ps", newpage = TRUE, layout = c("auto", "circle", "tree"), ... )## S3 method for class 'tda_graph' plot( x, width = 110, height = 80, file = "graph.ps", newpage = TRUE, layout = c("auto", "circle", "tree"), ... )
x |
a |
width, height
|
size of the plotting area in millimetres. |
file |
name for the PostScript file. |
newpage |
start a new page before drawing. |
layout |
|
... |
further options for |
The parsed drawing operations, invisibly.
Other graph analysis:
tda_dmet(),
tda_g(),
tda_g_analyses,
tda_graph(),
tda_locate_line(),
tda_ptree(),
tda_ucl()
e <- data.frame(from = c(1, 1, 2), to = c(2, 3, 4), value = 1) g <- tda_graph(e, directed = FALSE) # 4 nodes, 3 edges: already a tree pdf(NULL); plot(g); dev.off() # a graph with a cycle is not a tree, and this one is directed besides -- # both are fine with the default circular layout e2 <- data.frame(from = c(1, 1, 2, 2, 3, 4), to = c(2, 3, 3, 4, 4, 5)) g2 <- tda_graph(e2, directed = TRUE) pdf(NULL); plot(g2); dev.off()e <- data.frame(from = c(1, 1, 2), to = c(2, 3, 4), value = 1) g <- tda_graph(e, directed = FALSE) # 4 nodes, 3 edges: already a tree pdf(NULL); plot(g); dev.off() # a graph with a cycle is not a tree, and this one is directed besides -- # both are fine with the default circular layout e2 <- data.frame(from = c(1, 1, 2, 2, 3, 4), to = c(2, 3, 3, 4, 4, 5)) g2 <- tda_graph(e2, directed = TRUE) pdf(NULL); plot(g2); dev.off()
Base graphics, drawn from the tables the estimators already return, so no plotting dependency is needed. Censored times are marked, a band is drawn where a standard error is available, and groups get a legend.
## S3 method for class 'tda_ple' plot( x, conf.int = TRUE, mark.censored = TRUE, col = NULL, lty = 1, lwd = 1.5, xlab = "Time", ylab = "Survivor function", main = NULL, legend = TRUE, ylim = c(0, 1), ... ) ## S3 method for class 'tda_ltb' plot(x, ...) ## S3 method for class 'tda_rate' plot( x, what = c("survivor", "rate", "density"), xlab = "Time", ylab = NULL, col = "black", lwd = 1.5, main = NULL, ... )## S3 method for class 'tda_ple' plot( x, conf.int = TRUE, mark.censored = TRUE, col = NULL, lty = 1, lwd = 1.5, xlab = "Time", ylab = "Survivor function", main = NULL, legend = TRUE, ylim = c(0, 1), ... ) ## S3 method for class 'tda_ltb' plot(x, ...) ## S3 method for class 'tda_rate' plot( x, what = c("survivor", "rate", "density"), xlab = "Time", ylab = NULL, col = "black", lwd = 1.5, main = NULL, ... )
x |
an estimate from |
conf.int |
draw a band at plus or minus 1.96 standard errors. |
mark.censored |
mark censoring times with a cross. |
col, lty, lwd
|
colour, line type and width, recycled over groups. |
xlab, ylab, main, ylim
|
as usual. |
legend |
draw a legend when there is more than one group. |
... |
passed to |
what |
for a fitted rate model, which of the survivor, rate or
density curves to draw. The fit must have been made with |
The object, invisibly.
Other plotting:
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
set.seed(40) d <- data.frame(t = round(rexp(60, 0.1), 1) + 0.5, s = rbinom(60, 1, 0.8)) km <- tda_km(Surv(t, s) ~ 1, d) plot(km)set.seed(40) d <- data.frame(t = round(rexp(60, 0.1), 1) + 0.5, s = rbinom(60, 1, 0.8)) km <- tda_km(Surv(t, s) ~ 1, d) plot(km)
sdplot needs a PostScript coordinate system as well as the spatial
data, so the ranges have to be given.
## S3 method for class 'tda_spatial' plot( x, xlim = NULL, ylim = NULL, width = 100, height = NULL, newpage = TRUE, what = c("objects", "hull", "hull_per_polygon"), symbol = NULL, size = NULL, lty = NULL, lw = NULL, gray = NULL, ... )## S3 method for class 'tda_spatial' plot( x, xlim = NULL, ylim = NULL, width = 100, height = NULL, newpage = TRUE, what = c("objects", "hull", "hull_per_polygon"), symbol = NULL, size = NULL, lty = NULL, lw = NULL, gray = NULL, ... )
x |
a |
xlim, ylim
|
ranges of the coordinate system. |
width, height
|
size of the plotting area in millimetres; the height follows the data's aspect ratio unless given. |
newpage |
start a new page before drawing. |
what |
what to draw: |
symbol, size, lty, lw, gray
|
marker symbol and size, line type, line
width in mm, and grey level from 0 (black) to 1 (white); |
... |
further options for |
Points need a marker or nothing is drawn: give symbol (or another
TDA symbol number). This is the same trap noted for
tda_sd_plot3 – without a marker or a zvar attribute,
sdplot draws nothing at all rather than erroring.
The parsed drawing operations, invisibly.
Other spatial analysis:
tda_map(),
tda_polygons(),
tda_read_dbf(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd(),
tda_sd_analyses,
tda_sd_ps3(),
tda_spatial()
d <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) plot(s, symbol = 1) # a marker is needed; points draw nothing without oned <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) plot(s, symbol = 1) # a marker is needed; points draw nothing without one
TDA's arcd: opens access described by an archive
description file, or closes it with file = NULL.
tda_arcd(file = NULL, ...)tda_arcd(file = NULL, ...)
file |
archive description file, or NULL to close. |
... |
passed to |
the printed output, invisibly.
# an archive description file names the zoo archive and then one # line per member: number, name, type (1 data, 2 variable # descriptions), record length, records, variables dr <- tempfile("tda"); dir.create(dr) zoo <- system.file("extdata", "tda.zoo", package = "tdaR") file.copy(zoo, file.path(dr, "tda.zoo")) writeLines(c("tda.zoo", "1 adata.dat 1 24 20 3", "2 avar.dat 2 40 3 0"), file.path(dr, "arc.ad")) out <- tda_arcd("arc.ad", dir = dr) cat(grep("archive|Checking|adata", out, value = TRUE), sep = "\n")# an archive description file names the zoo archive and then one # line per member: number, name, type (1 data, 2 variable # descriptions), record length, records, variables dr <- tempfile("tda"); dir.create(dr) zoo <- system.file("extdata", "tda.zoo", package = "tdaR") file.copy(zoo, file.path(dr, "tda.zoo")) writeLines(c("tda.zoo", "1 adata.dat 1 24 20 3", "2 avar.dat 2 40 3 0"), file.path(dr, "arc.ad")) out <- tda_arcd("arc.ad", dir = dr) cat(grep("archive|Checking|adata", out, value = TRUE), sep = "\n")
TDA's arcv on an open archive. It requires an open archive (see
tda_arcd) containing a type-2 (variable description)
member.
tda_arcv(out, data_file = NULL, archive = NULL, ...)tda_arcv(out, data_file = NULL, archive = NULL, ...)
out |
output file name. |
data_file |
optional data-file filter. |
archive |
the archive description ( |
... |
passed to |
the printed output, invisibly.
d <- tempfile(); dir.create(d) for (f in c("tda.zad", "tda.zoo")) file.copy(system.file("extdata", f, package = "tdaR"), d) tda_arcv("vars.vd", archive = "tda.zad", dir = d) readLines(file.path(d, "vars.vd"))d <- tempfile(); dir.create(d) for (f in c("tda.zad", "tda.zoo")) file.copy(system.file("extdata", f, package = "tdaR"), d) tda_arcv("vars.vd", archive = "tda.zad", dir = d) readLines(file.path(d, "vars.vd"))
TDA's arcvc. It requires an open archive (see
tda_arcd) containing a type-2 (variable description)
member.
tda_arcvc(file, rewrite = NULL, suffix = c("number", "lower", "upper"), ...)tda_arcvc(file, rewrite = NULL, suffix = c("number", "lower", "upper"), ...)
file |
the description file. |
rewrite |
optional path for a rewritten file with unique names. |
suffix |
how names are made unique: "number", "lower", or "upper" (file number or file name in either case). |
... |
passed to |
the printed output, invisibly.
# the file arcv writes, checked for duplicate variable names d <- tempfile(); dir.create(d) for (f in c("tda.zad", "tda.zoo")) file.copy(system.file("extdata", f, package = "tdaR"), d) tda_arcv("vars.vd", archive = "tda.zad", dir = d) # arcv writes a template with every definition commented out, for the # caller to uncomment; arcvc reports its verdict on it either way out <- tda_arcvc("vars.vd", dir = d) cat(grep("variable|once", out, value = TRUE), sep = "\n")# the file arcv writes, checked for duplicate variable names d <- tempfile(); dir.create(d) for (f in c("tda.zad", "tda.zoo")) file.copy(system.file("extdata", f, package = "tdaR"), d) tda_arcv("vars.vd", archive = "tda.zad", dir = d) # arcv writes a template with every definition commented out, for the # caller to uncomment; arcvc reports its verdict on it either way out <- tda_arcvc("vars.vd", dir = d) cat(grep("variable|once", out, value = TRUE), sep = "\n")
TDA's bfc: Y as a Boolean function of binary X's.
tda_bfc(y, x, undefined = c("dontcare", "as_one", "as_zero"), ...)tda_bfc(y, x, undefined = c("dontcare", "as_one", "as_zero"), ...)
y |
binary outcome. |
x |
binary matrix. |
undefined |
how undefined arguments count: "dontcare", "as_one", or "as_zero". |
... |
passed to |
the printed output (implicants).
x <- expand.grid(a = 0:1, b = 0:1) r <- tda_bfc(y = as.integer(x$a & x$b), x = x) cat(head(tda_payload(r), 12), sep = "\n")x <- expand.grid(a = 0:1, b = 0:1) r <- tda_bfc(y = as.integer(x$a & x$b), x = x) cat(head(tda_payload(r), 12), sep = "\n")
Which combinations of binary conditions produce the outcome? TDA's
bfa builds the truth table of y over the condition
variables, finds all prime implicants (Quine-McCluskey), and selects
minimal covers. This is the machinery behind crisp-set QCA-style
analyses.
tda_boolean_min( y, conditions, data = NULL, undefined = c("dont_care", "true", "false"), algorithm = c("lawler", "petrick", "lawler2", "none"), max_implicants = NULL, options = list(), dir = tempfile("tda"), ... )tda_boolean_min( y, conditions, data = NULL, undefined = c("dont_care", "true", "false"), algorithm = c("lawler", "petrick", "lawler2", "none"), max_implicants = NULL, options = list(), dir = tempfile("tda"), ... )
y |
the outcome: a 0/1 vector, or a column name in |
conditions |
the condition variables: a 0/1 matrix or data
frame, or column names in |
data |
optional data frame supplying the columns. |
undefined |
how rows never observed are treated:
|
algorithm |
cover selection: |
max_implicants |
storage cap. |
options |
a named list of further TDA options for |
dir |
working directory. |
... |
passed to |
A list: $selections, a data frame with one row per
term of each minimal cover – selection number and one
column per condition holding 1, 0, or NA for "does not matter" –
and $expression, the printed symbolic forms.
Other optimization:
tda_mlp(),
tda_mlpi(),
tda_mls(),
tda_mqap(),
tda_mqp()
d <- expand.grid(X1 = 0:1, X2 = 0:1, X3 = 0:1) d$Y <- as.integer(d$X1 & d$X2 | d$X3) tda_boolean_min("Y", c("X1", "X2", "X3"), data = d)$selectionsd <- expand.grid(X1 = 0:1, X2 = 0:1, X3 = 0:1) d$Y <- as.integer(d$X1 & d$X2 | d$X3) tda_boolean_min("Y", c("X1", "X2", "X3"), data = d)$selections
An interval regression identifies its coefficient only up to an interval,
so coef() would be misleading. This returns the bounds TDA reports.
tda_bounds(x, what = c("beta", "alpha", "mean_y", "mean_x", "var_x"))tda_bounds(x, what = c("beta", "alpha", "mean_y", "mean_x", "var_x"))
x |
a fit from |
what |
which bounds: the slope, the intercept ( |
A named vector with lower and upper, or NULL.
Other interval-valued data:
tda_idf(),
tda_ilsreg(),
tda_imean(),
tda_imreg(),
tda_inpreg(),
tda_ivar1(),
tda_ivreg(),
tda_sddf()
set.seed(37) n <- 40 xlo <- round(rnorm(n), 2); xhi <- xlo + round(runif(n, 0.5, 1.5), 2) ylo <- round(1 + 0.6 * xlo + rnorm(n, sd = 0.3), 2) yhi <- ylo + round(runif(n, 0.5, 1.5), 2) d <- data.frame(xlo = xlo, xhi = xhi, ylo = ylo, yhi = yhi) ivf <- tda_ivreg(iv(ylo, yhi) ~ iv(xlo, xhi), d) tda_bounds(ivf, "beta") tda_bounds(ivf, "mean_x") # ilsreg: an interval response, a point regressor -- beta and alpha (the # intercept) both come back bounded, not just the slope set.seed(2) d2 <- data.frame(x = round(rnorm(30), 2)) d2$ylo <- 2 + 0.5 * d2$x + rnorm(30, sd = 0.2) d2$yhi <- d2$ylo + round(runif(30, 0.3, 1), 2) lsf <- tda_ilsreg(iv(ylo, yhi) ~ x, d2) tda_bounds(lsf, "beta") tda_bounds(lsf, "alpha")set.seed(37) n <- 40 xlo <- round(rnorm(n), 2); xhi <- xlo + round(runif(n, 0.5, 1.5), 2) ylo <- round(1 + 0.6 * xlo + rnorm(n, sd = 0.3), 2) yhi <- ylo + round(runif(n, 0.5, 1.5), 2) d <- data.frame(xlo = xlo, xhi = xhi, ylo = ylo, yhi = yhi) ivf <- tda_ivreg(iv(ylo, yhi) ~ iv(xlo, xhi), d) tda_bounds(ivf, "beta") tda_bounds(ivf, "mean_x") # ilsreg: an interval response, a point regressor -- beta and alpha (the # intercept) both come back bounded, not just the slope set.seed(2) d2 <- data.frame(x = round(rnorm(30), 2)) d2$ylo <- 2 + 0.5 * d2$x + rnorm(30, sd = 0.2) d2$yhi <- d2$ylo + round(runif(30, 0.3, 1), 2) lsf <- tda_ilsreg(iv(ylo, yhi) ~ x, d2) tda_bounds(lsf, "beta") tda_bounds(lsf, "alpha")
brr: builds the replicate-weight matrix balanced repeated
replication needs – a variance-estimation technique from survey
statistics that works by refitting an estimator on nr
half-sample replicates of the data (nr, the number of
replications required, is determined from strata and
secu and reported back) and taking the spread across them as
the variance, rather than a model-based formula. This returns the
design itself – TDA's orthogonal (Hadamard-based) construction,
not practical to reproduce independently in R – so it can be applied
to whatever estimator is being replicated; actually refitting a model
nr times and computing the BRR variance from the results is
ordinary R code once the design is in hand, not shown here since it
depends entirely on what is being estimated.
tda_brr(strata, secu, dir = tempfile("tda"), ...)tda_brr(strata, secu, dir = tempfile("tda"), ...)
strata |
number of strata. |
secu |
number of sampling units per stratum; |
dir |
working directory. |
... |
passed to |
Not every (strata, secu) combination succeeds: secu must
be at least 2 (one stratum, one unit gives nothing to replicate), and
at least one combination that satisfies every other documented
constraint (brr = 4,2) can still fail with “no success
in calculating orthogonal weights”: 2, 3, and 8 strata at
secu = 2 all succeed, 4 does not. This is a limitation in
TDA's Galois-field construction for
specific sizes, not something this wrapper can lift.
A list: replications (nr, how many are needed),
and design, the strata by replications matrix
itself (TDA's description: design[i, j] is which
sampling unit of stratum i to use in replication j).
Other descriptive statistics:
tda_cov(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_segr(),
tda_subm()
b <- tda_brr(3, 2) b$replications b$designb <- tda_brr(3, 2) b$replications b$design
Small file-diagnostic utilities from TDA's toolkit, from an era
before assuming wc, od or split were available:
tda_ccnt a character frequency table, tda_lcnt a
record-length frequency table, tda_dump a hex dump, and
tda_dsplit splits a file into fixed-size parts on disk.
tda_ccnt(file, dir = tempfile("tda"), ...) tda_lcnt(file, noc = NULL, dir = tempfile("tda"), ...) tda_dump(file, nc = NULL, offset = NULL, dir = tempfile("tda"), ...) tda_dsplit(file, len = NULL, dir = tempfile("tda"), ...)tda_ccnt(file, dir = tempfile("tda"), ...) tda_lcnt(file, noc = NULL, dir = tempfile("tda"), ...) tda_dump(file, nc = NULL, offset = NULL, dir = tempfile("tda"), ...) tda_dsplit(file, len = NULL, dir = tempfile("tda"), ...)
file |
path to the file to inspect. |
dir |
working directory; for |
... |
passed to |
noc |
for |
nc |
for |
offset |
for |
len |
for |
tda_ccnt and tda_lcnt return a data frame.
tda_dump returns the hex dump as a character vector, one line
each. tda_dsplit returns the paths of the parts it wrote.
Other TDA infrastructure:
tda_help(),
tda_output(),
tda_read_table(),
tda_run(),
tda_write_data()
f <- tempfile() writeLines(c("hello world", "foo bar baz", "x"), f) tda_ccnt(f) tda_lcnt(f) cat(tda_dump(f), sep = "\n") f2 <- tempfile() writeLines(rep("0123456789", 10), f2) tda_dsplit(f2, len = 20)f <- tempfile() writeLines(c("hello world", "foo bar baz", "x"), f) tda_ccnt(f) tda_lcnt(f) cat(tda_dump(f), sep = "\n") f2 <- tempfile() writeLines(rep("0123456789", 10), f2) tda_dsplit(f2, len = 20)
Counts the drawing operators in the file and the operations the parser produced, and reports anything unaccounted for. Reading a plot back is easy to get half right – an operator that is silently ignored looks exactly like one that is not there – so this compares the two directly rather than leaving it to the eye.
tda_check_ps(file, ...)tda_check_ps(file, ...)
file |
a |
... |
passed to |
A data frame with one row per operator: how often it appears in the file, whether the parser handles it, and how many operations resulted.
Other plotting:
plot.tda_ple(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
p <- tda_ps(xlim = c(0, 10), ylim = c(0, 10)) p <- tda_pl_circle(p, at = c(5, 5), r = 2) tda_check_ps(tda_ps_file(p))p <- tda_ps(xlim = c(0, 10), ylim = c(0, 10)) p <- tda_pl_circle(p, at = c(5, 5), r = 2) tda_check_ps(tda_ps_file(p))
TDA's clpyr on a distance matrix.
tda_clpyr(d, linkage = c("single", "complete"), ...)tda_clpyr(d, linkage = c("single", "complete"), ...)
d |
symmetric distance matrix. |
linkage |
"single" or "complete" link. |
... |
passed to |
the printed output.
r <- tda_clpyr(as.matrix(dist(c(0, 1, 5, 6)))) # the top of the pyramid joins everything: 4 objects spanning 1..4 tail(r$pyramid, 1)r <- tda_clpyr(as.matrix(dist(c(0, 1, 5, 6)))) # the top of the pyramid joins everything: 4 objects spanning 1..4 tail(r$pyramid, 1)
TDA's clustering commands, all of which take a dissimilarity and so accept
a dist – including the one tda_seqm returns.
TDA_CLUSTER tda_cluster( d, method = "hierarchical", algorithm = c("centers", "diameter"), min_size = NULL, max_splits = NULL, options = list(), dir = tempfile("tda"), ... )TDA_CLUSTER tda_cluster( d, method = "hierarchical", algorithm = c("centers", "diameter"), min_size = NULL, max_splits = NULL, options = list(), dir = tempfile("tda"), ... )
d |
a |
method |
one of the names in |
algorithm |
for |
min_size |
for |
max_splits |
for |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
The default, "hierarchical" (hcld), writes a ragged table –
a node, its member count, then that many member indices – which is not a
rectangular data.frame, so it is parsed separately into
clusters, a named list of member-index vectors, one per node of the
divisive tree (the root first, then each split). "unidimensional"
and "additive" report their result only as text (a final partition
or a fitted tree), never through df=; read $run$output for
those.
An object carrying a table, or for "hierarchical"
clusters instead (see Details). For "hierarchical" the
object also carries merges: one row per split, the two
clusters, their sizes and their diameters.
Other clustering:
TDA_MDS,
tda_conjoint(),
tda_cutree(),
tda_dma(),
tda_pdatd()
d <- dist(matrix(c(1, 2, 3, 8, 9, 10), ncol = 1)) tda_cluster(d)$clusters # the divisive tree: root, then each splitd <- dist(matrix(c(1, 2, 3, 8, 9, 10), ncol = 1)) tda_cluster(d)$clusters # the divisive tree: root, then each split
TDA's com: enumerate tuples, sets, permutations or
partitions into an output file.
tda_com( pattern = c("tuples", "subsets", "m_tuples", "permutations", "partitions", "partitions_m", "bipartitions"), n = 1, m = 1, ... )tda_com( pattern = c("tuples", "subsets", "m_tuples", "permutations", "partitions", "partitions_m", "bipartitions"), n = 1, m = 1, ... )
pattern |
one of "tuples", "subsets", "m_tuples", "permutations", "partitions", "partitions_m", "bipartitions". |
n, m
|
dimensions (n the base size, m where the pattern needs it). |
... |
passed to |
the output file's lines.
# the six 2-element subsets of {0, 1, 2, 3}: a row number, then the members tda_com("subsets", n = 4, m = 2) # the five partitions of 4: 4, 3+1, 2+2, 2+1+1, 1+1+1+1 tda_com("partitions", n = 4)# the six 2-element subsets of {0, 1, 2, 3}: a row number, then the members tda_com("subsets", n = 4, m = 2) # the five partitions of 4: 4, 3+1, 2+2, 2+1+1, 1+1+1+1 tda_com("partitions", n = 4)
tda_combine_ps reaches TDA's dplot command, which lays
out a grid of previously-created PostScript files (each from its own
tda_ps() session, already run) into a single output file – one
row per element of rows, side by side within a row. Unlike every
other tda_pl_* function here, this is not a command added to an
in-progress session: dplot combines files that already exist on
disk into a new one of its own, so this takes file paths (or tda_ps
objects that have already been run, via tda_ps_file) and
runs standalone, the way tda_run does.
tda_combine_ps( rows, width = 120, height = 80, origin = c(10, 10), file = "combined.ps", ... )tda_combine_ps( rows, width = 120, height = 80, origin = c(10, 10), file = "combined.ps", ... )
rows |
A list of PostScript files to lay out in a grid, one row per
list element; each element is a character vector of file paths (or
|
width, height
|
Size of the combined output, in mm (TDA's defaults: 120 and 80). |
origin |
Physical origin of the combined plot, |
file |
Name of the combined output file. |
... |
Further options passed to |
The result of tda_run, whose own run directory
holds file.
# two small plots, then both side by side in one file p1 <- tda_ps(xlim = c(0, 10), ylim = c(-1, 1), width = 55, height = 40) p1 <- tda_pl_axes(tda_pl_function(p1, "sin(x)")) p2 <- tda_ps(xlim = c(0, 10), ylim = c(0, 100), width = 55, height = 40) p2 <- tda_pl_axes(tda_pl_function(p2, "x * x")) r <- tda_combine_ps(list(c(tda_ps_file(p1), tda_ps_file(p2)))) file.exists(file.path(r$dir, "combined.ps"))# two small plots, then both side by side in one file p1 <- tda_ps(xlim = c(0, 10), ylim = c(-1, 1), width = 55, height = 40) p1 <- tda_pl_axes(tda_pl_function(p1, "sin(x)")) p2 <- tda_ps(xlim = c(0, 10), ylim = c(0, 100), width = 55, height = 40) p2 <- tda_pl_axes(tda_pl_function(p2, "x * x")) r <- tda_combine_ps(list(c(tda_ps_file(p1), tda_ps_file(p2)))) file.exists(file.path(r$dir, "combined.ps"))
TDA's conj (alternating least squares) on a preference
variable and factor columns.
tda_conj(y, x, algorithm = c("monotone", "lp"), ...)tda_conj(y, x, algorithm = c("monotone", "lp"), ...)
y |
preference values. |
x |
factor matrix. |
algorithm |
"monotone" regression or "lp" (linear programming). |
... |
passed to |
the printed output.
x <- expand.grid(a = 1:2, b = 1:2) r <- tda_conj(y = c(4, 3, 2, 1), x = x) cat(tail(tda_payload(r), 8), sep = "\n") # the part-worthsx <- expand.grid(a = 1:2, b = 1:2) r <- tda_conj(y = c(4, 3, 2, 1), x = x) cat(tail(tda_payload(r), 8), sep = "\n") # the part-worths
nmca is conjoint measurement: it takes a rank order over profiles
and the categorical factors describing them, and estimates the part-worth
of each factor level. It draws a Hasse diagram of the order as part of the
output.
tda_conjoint(formula, data, options = list(), dir = tempfile("tda"), ...)tda_conjoint(formula, data, options = list(), dir = tempfile("tda"), ...)
formula |
|
data |
a data frame. Factor levels are numbered from 1 upwards, and a value outside that range is rejected by TDA with the record it occurred in. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object carrying the run; the diagram and the estimates are in
$run$output.
Other clustering:
TDA_CLUSTER,
TDA_MDS,
tda_cutree(),
tda_dma(),
tda_pdatd()
d <- expand.grid(price = 1:2, brand = 1:2) d$rank <- c(4, 2, 3, 1) cj <- tda_conjoint(rank ~ price + brand, d) cat(tda_payload(cj$run), sep = "\n") # the nmca section itselfd <- expand.grid(price = 1:2, brand = 1:2) d$rank <- c(4, 2, 3, 1) cj <- tda_conjoint(rank ~ price + brand, d) cat(tda_payload(cj$run), sep = "\n") # the nmca section itself
tda_rate takes constraints in TDA's notation, where
parameters are numbered in the order they are estimated:
"b3 - b10 = 0" makes the third and tenth equal. This builds such a
string from a fitted model's coefficient names, so the numbering does not
have to be counted out by hand.
tda_constrain(fit, ...)tda_constrain(fit, ...)
fit |
a fit from |
... |
constraints, each a character vector of two coefficient names
to be held equal, or a formula like |
A character vector of constraints for tda_rate.
Other rate models:
tda_control(),
tda_dple(),
tda_rates(),
tda_split(),
tda_survivor(),
tda_transitions(),
vcov.tda_fit()
d <- tda_rrdat(states = 4) f <- tda_rate(Surv(TFP, DES) ~ EDU + PRES, d) tda_constrain(f, c("0->1: EDU", "0->2: EDU"))d <- tda_rrdat(states = 4) f <- tda_rate(Surv(TFP, DES) ~ EDU + PRES, d) tda_constrain(f, c("0->1: EDU", "0->2: EDU"))
Convergence control
tda_control( algorithm = NULL, tolsg = NULL, tolsp = NULL, tolg = NULL, tolf = NULL, maxit = NULL, tol_param = NULL, tol_var = NULL, tol_reduction = NULL, step_length = NULL, step_reduction = NULL, step_min = NULL, maxit_line = NULL, criterion = NULL, derivatives = NULL ) tda_strict(tol = 1e-12) tda_converged(x)tda_control( algorithm = NULL, tolsg = NULL, tolsp = NULL, tolg = NULL, tolf = NULL, maxit = NULL, tol_param = NULL, tol_var = NULL, tol_reduction = NULL, step_length = NULL, step_reduction = NULL, step_min = NULL, maxit_line = NULL, criterion = NULL, derivatives = NULL ) tda_strict(tol = 1e-12) tda_converged(x)
algorithm |
TDA minimiser number, its |
tolsg, tolsp
|
tolerances for the scaled gradient and scaled parameter change, used by algorithms 7 and 8. |
tolg, tolf
|
tolerances for the gradient norm and the function value, used by the default algorithm. |
maxit |
iteration cap, TDA's |
tol_param, tol_var, tol_reduction
|
three more tolerances TDA's
minimiser reads for other algorithms/situations – |
step_length, step_reduction, step_min
|
step-size controls for
TDA's line search – |
maxit_line |
cap on line-search iterations within one step –
TDA's |
criterion |
which convergence test to apply – TDA's
|
derivatives |
|
tol |
tolerance for |
x |
a fitted model. |
A list of options for control=; tda_converged returns
TRUE, FALSE, or NA where TDA reports nothing.
TDA's default minimiser stops on the norm of the gradient against an
absolute tolerance, plus a loose disjunction that also stops when the
change in function value is small. Algorithms 7 and 8 switch to
optstp(), the Dennis-Schnabel test on the largest relative
gradient and relative parameter step. That is scale-invariant, closer to
what R's optimisers do, and gives results that reproduce across platforms.
It is reachable only through algorithm: TDA's crit= accepts
1 to 3 and cannot select it.
The default is TDA's, so a plain call reproduces a plain command file.
tda_strict() opts in.
Algorithms 7 and 8 also lower the iteration cap to 20 when derivatives are
numerical, against 100 otherwise, so asking for a tighter tolerance can
turn a converged fit into a truncated one. Every fit reports how it
stopped, warns if it did not converge, and tda_converged() reads
that back.
Other rate models:
tda_constrain(),
tda_dple(),
tda_rates(),
tda_split(),
tda_survivor(),
tda_transitions(),
vcov.tda_fit()
set.seed(36) d <- data.frame(x = rnorm(200)) d$y <- rbinom(200, 1, plogis(0.3 + 0.8 * d$x)) f <- tda_qreg(y ~ x, d, control = tda_control(maxit = 50, tolg = 1e-8)) coef(f) tda_converged(f) # tda_strict: the same idea, one shared tolerance for both algorithm 7/8 # criteria at once f2 <- tda_qreg(y ~ x, d, control = tda_strict()) coef(f2)set.seed(36) d <- data.frame(x = rnorm(200)) d$y <- rbinom(200, 1, plogis(0.3 + 0.8 * d$x)) f <- tda_qreg(y ~ x, d, control = tda_control(maxit = 50, tolg = 1e-8)) coef(f) tda_converged(f) # tda_strict: the same idea, one shared tolerance for both algorithm 7/8 # criteria at once f2 <- tda_qreg(y ~ x, d, control = tda_strict()) coef(f2)
The -denominator covariance matrix, as stats::cov()
computes it, extended to case weights when a cwt command is
active. tda_corr is its correlation counterpart.
tda_cov(..., options = list(), dir = tempfile("tda"))tda_cov(..., options = list(), dir = tempfile("tda"))
... |
a data frame, a matrix, or vectors. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
An object carrying matrix, the covariance matrix with
the variables' names on both dimensions.
Other descriptive statistics:
tda_brr(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_segr(),
tda_subm()
set.seed(26) d <- data.frame(x = rnorm(40), y = rnorm(40)) d$y <- d$y + 0.6 * d$x tda_cov(d)$matrix cov(d) # matchesset.seed(26) d <- data.frame(x = rnorm(40), y = rnorm(40)) d$y <- d$y + 0.6 * d$x tda_cov(d)$matrix cov(d) # matches
Builds a dendrogram with TDA's hcls and cuts it with hclsp.
tda_cutree( d, nlev = 2, nodes = NULL, options = list(), dir = tempfile("tda"), ... )tda_cutree( d, nlev = 2, nodes = NULL, options = list(), dir = tempfile("tda"), ... )
d |
a |
nlev |
number of levels at which to cut. |
nodes |
an explicit sequence of node numbers to cut at, TDA's
|
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
Unlike R's cutree, which returns one group label per observation,
hclsp reports the cut as a set of nodes: table has one row
per resulting cluster, its TDA node number, how many leaves (original
observations) it holds, and its parent node – not a per-observation
vector. Getting a label for each observation means walking merge
(the dendrogram hcls built, one row per step) down from a node in
table to the leaves under it; this wrapper does not do that walk
for you.
An object carrying merge, the dendrogram, and table,
one row per cluster in the cut (node, leaves,
parent).
Other clustering:
TDA_CLUSTER,
TDA_MDS,
tda_conjoint(),
tda_dma(),
tda_pdatd()
set.seed(35) pts <- rbind(matrix(rnorm(10, 0), 5, 2), matrix(rnorm(10, 8), 5, 2)) ct <- tda_cutree(dist(pts), nlev = 2) ct$table # two clusters of five leaves each ct$merge # the nine merge steps that built the dendrogramset.seed(35) pts <- rbind(matrix(rnorm(10, 0), 5, 2), matrix(rnorm(10, 8), 5, 2)) ct <- tda_cutree(dist(pts), nlev = 2) ct$table # two clusters of five leaves each ct$merge # the nine merge steps that built the dendrogram
tda_cwt_norm reproduces TDA's cwt(wnorm=s)=W; (or the
bare-flag cwt(wnorm)=W;) as a plain vector transform, for
weights= on tda_qreg, tda_glm,
tda_ple, tda_ltb and tda_rate –
none of which expose wnorm as an argument, since this is
all it does: fitted coefficients come
back identical whether the weights are rescaled this way first or
not, only the standard errors change (rescaling is a constant
multiplier on
the whole weighted log-likelihood, so it moves the curvature at the
optimum, not where the optimum is). cwt(wnorm=s)=W; on the raw
weights and plain cwt=W; on tda_cwt_norm(W, s) give the
same fit, to the last printed digit.
tda_cwt_norm(w, s = length(w))tda_cwt_norm(w, s = length(w))
w |
a numeric vector of raw case weights. |
s |
the target sum for the rescaled weights – TDA's
|
w, rescaled so it sums to s.
w <- c(2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10) # sums to 74 tda_cwt_norm(w) # cwt(wnorm)=W; -- rescaled to sum 13 (length(w)) tda_cwt_norm(w, 100) # cwt(wnorm=100)=W;w <- c(2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10) # sums to 74 tda_cwt_norm(w) # cwt(wnorm)=W; -- rescaled to sum 13 (length(w)) tda_cwt_norm(w, 100) # cwt(wnorm=100)=W;
TDA's standalone dblock on the current-run data: blocks are
maximal runs of identical values. Mostly useful inside longer
tda_run pipelines; for block-mode variable creation
put dblock= inside nvar (see the package tests).
tda_dblock(data, by, commands = character(), ...)tda_dblock(data, by, commands = character(), ...)
data |
data frame. |
by |
column name defining blocks. |
commands |
further command lines run under the block structure. Column names are TDA-sanitised (upper-cased) first, so refer to them in that form. |
... |
passed to |
the printed output, invisibly.
out <- tda_dblock(data.frame(G = c(1, 1, 2), X = 1:3), by = "G", commands = "dstat = X;") # blocks are defined by G; dstat runs under the block structure grep("^X", out, value = TRUE)out <- tda_dblock(data.frame(G = c(1, 1, 2), X = 1:3), by = "G", commands = "dstat = X;") # blocks are defined by G; dstat runs under the block structure grep("^X", out, value = TRUE)
Runs nvar on a data frame with new variables defined by TDA
expressions, and returns the frame with them added. This is the way
to the operators of the manual's 5.2.6 that have no R counterpart:
the change and count operators (change, cntch), the
aggregates over blocks (gcnt, grec, gmean,
gstd, ...), TDA's random numbers, and so on.
tda_derive(data, ..., block = NULL, options = list(), dir = tempfile("tda"))tda_derive(data, ..., block = NULL, options = list(), dir = tempfile("tda"))
data |
a data frame. |
... |
named TDA expressions, as strings: |
block |
a column name: with it, |
options |
a named list of further |
dir |
working directory. |
data with the new columns, from the export channel.
d <- data.frame(ID = c(1, 1, 2), S = c(1, 3, 2)) tda_derive(d, CH = "change(S)", CN = "cntch(S)") tda_derive(d, CN = "cntch(S)", block = "ID")d <- data.frame(ID = c(1, 1, 2), S = c(1, 3, 2)) tda_derive(d, CH = "change(S)", CN = "cntch(S)") tda_derive(d, CN = "cntch(S)", block = "ID")
Every error, warning, note or "cannot" line TDA printed, on stdout or
stderr, for a run or a fitted model. TDA reports problems by printing
them and carrying on, so a fit can come back with a full table and a
message about what it could not do; nothing here is dropped from
tda_output(), this is the short list.
tda_diagnostics(x)tda_diagnostics(x)
x |
a |
a character vector, empty when TDA reported nothing.
# a clean run reports nothing tda_diagnostics(tda_run("nvar(noc = 5, X = case);")) # dstat asks for a variable that was never defined: TDA prints the # error and continues, so the run returns and the message is here r <- tda_run(c("nvar(noc = 5, X = case);", "dstat = Y;")) tda_diagnostics(r) # a fit stopped after one iteration still returns a coefficient # table; the problem is reported alongside it d <- data.frame(x = c(-1, -0.5, 0, 0.5, 1, 1.5), y = c(0, 0, 1, 0, 1, 1)) f <- suppressWarnings(tda_qreg(y ~ x, d, control = tda_control(maxit = 1))) tda_diagnostics(f)# a clean run reports nothing tda_diagnostics(tda_run("nvar(noc = 5, X = case);")) # dstat asks for a variable that was never defined: TDA prints the # error and continues, so the run returns and the message is here r <- tda_run(c("nvar(noc = 5, X = case);", "dstat = Y;")) tda_diagnostics(r) # a fit stopped after one iteration still returns a coefficient # table; the problem is reported alongside it d <- data.frame(x = c(-1, -0.5, 0, 0.5, 1, 1.5), y = c(0, 0, 1, 0, 1, 1)) f <- suppressWarnings(tda_qreg(y ~ x, d, control = tda_control(maxit = 1))) tda_diagnostics(f)
dma: seven related methods for reducing a data matrix to a
handful of derived scores, selected with alg – principal
components (1, from the raw data; 2, from a covariance or correlation
matrix already computed), factor analysis (3, 4, the same two starting
points but with eigenvectors rescaled as loadings), dual scaling and
correspondence analysis (5, 6, for a frequency table rather than a
data matrix), and a direct SVD-based projection (7). Verified against
prcomp for algorithm 1: eigenvalues match exactly,
eigenvectors match up to sign (an ordinary, harmless ambiguity in any
eigendecomposition).
tda_dma( data, alg = 1, preprocess = NULL, ns = NULL, variables = NULL, options = list(), dir = tempfile("tda"), ... )tda_dma( data, alg = 1, preprocess = NULL, ns = NULL, variables = NULL, options = list(), dir = tempfile("tda"), ... )
data |
a data frame or matrix. For algorithms 1–4 and 7, a standard data matrix (rows are cases); for 2 and 4, a covariance or correlation matrix (square, symmetric); for 5 and 6, a frequency table. |
alg |
which of the seven algorithms; see Description. Default 1, ordinary principal components. |
preprocess |
preprocessing, for algorithms 1, 5 and 7 only – for
|
ns |
keep at most this many components; all of them by default. |
variables |
optional subset of |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
TDA's v= (choosing a subset of variables from a larger data
matrix) needs variable names that start uppercase, the same rule as
anywhere else in TDA – lowercase R column names are displayed
correctly when declared but cannot be referenced again later in
the same script, including by v= itself, failing with a
“Syntax error or undefined variables” that gives no hint the
name's case is the problem. variables handles this
automatically; there is no need to rename columns yourself first.
A list with values (the eigenvalues), percent (each
eigenvalue's share of the total, as TDA prints it), vectors
(the eigenvectors or factor loadings, one column per component, row
names taken from data), and scores (the derived score
for each case, one column per component) – scores is empty
for algorithms where TDA does not calculate it (2 and 4).
Other clustering:
TDA_CLUSTER,
TDA_MDS,
tda_conjoint(),
tda_cutree(),
tda_pdatd()
set.seed(1) d <- data.frame(x1 = rnorm(30), x2 = rnorm(30)) d$x3 <- d$x1 + d$x2 + rnorm(30, sd = 0.3) # correlated with both pc <- tda_dma(d) pc$values # most of the variance is in the first PC pc$vectors # loadings: x3 dominates it head(pc$scores) # a subset of the variables, instead of all of them tda_dma(d, variables = c("x1", "x2"))$valuesset.seed(1) d <- data.frame(x1 = rnorm(30), x2 = rnorm(30)) d$x3 <- d$x1 + d$x2 + rnorm(30, sd = 0.3) # correlated with both pc <- tda_dma(d) pc$values # most of the variance is in the first PC pc$vectors # loadings: x3 dominates it head(pc$scores) # a subset of the variables, instead of all of them tda_dma(d, variables = c("x1", "x2"))$values
dmet: an undirected valued graph's edge values, read as a
distance matrix, do not always satisfy the triangle inequality (a
direct edge can be "longer" than going via a third node). This finds
the smallest constant that, added to every distance, makes the whole
matrix satisfy it – – and returns both the original and the corrected matrix.
tda_dmet(g, options = list(), dir = tempfile("tda"), ...)tda_dmet(g, options = list(), dir = tempfile("tda"), ...)
g |
a |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
A list: original and modified, both distance
matrices, and constant, the value added to get from one to
the other.
Other graph analysis:
plot.tda_graph(),
tda_g(),
tda_g_analyses,
tda_graph(),
tda_locate_line(),
tda_ptree(),
tda_ucl()
e <- data.frame(from = c(1, 2, 3), to = c(2, 3, 1), value = c(1, 2, 5)) g <- tda_graph(e, directed = FALSE) # 1-3 direct (5) exceeds # 1-2-3 via node 2 (1+2=3) tda_dmet(g)e <- data.frame(from = c(1, 2, 3), to = c(2, 3, 1), value = c(1, 2, 5)) g <- tda_graph(e, directed = FALSE) # 1-3 direct (5) exceeds # 1-2-3 via node 2 (1+2=3) tda_dmet(g)
TDA's dmet1: adjusts a distance matrix (given as an
undirected valued graph) toward metricity.
tda_dmet1(d, tolerance = 1e-04, max_iterations = 20, ...)tda_dmet1(d, tolerance = 1e-04, max_iterations = 20, ...)
d |
symmetric distance matrix. |
tolerance, max_iterations
|
deviation tolerance and cap. |
... |
passed to |
the output file's lines.
# 5 breaks the triangle inequality (1 + 2 < 5), so the # metricized matrix shortens it to 3 d <- rbind(c(0, 1, 5), c(1, 0, 2), c(5, 2, 0)) r <- tda_dmet1(d) r$modified# 5 breaks the triangle inequality (1 + 2 < 5), so the # metricized matrix shortens it to 3 d <- rbind(c(0, 1, 5), c(1, 0, 2), c(5, 2, 0)) r <- tda_dmet1(d) r$modified
tda_ple is the product-limit estimator, which is Kaplan-Meier;
tda_km is an alias for it. tda_ltb groups into intervals.
tda_dple and tda_dltb are the discrete time versions, and
tda_diple handles interval censored data.
tda_dple(formula, data, dir = tempfile("tda"), ...) tda_dltb(formula, data, dir = tempfile("tda"), ...) tda_diple(data, start, lower, upper, status, dir = tempfile("tda"), ...) tda_ltb( formula, data, tp = NULL, cfrac = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... ) tda_ple( formula, data, compare = FALSE, quantiles = NULL, at_survival = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... ) tda_km(formula, data, ...)tda_dple(formula, data, dir = tempfile("tda"), ...) tda_dltb(formula, data, dir = tempfile("tda"), ...) tda_diple(data, start, lower, upper, status, dir = tempfile("tda"), ...) tda_ltb( formula, data, tp = NULL, cfrac = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... ) tda_ple( formula, data, compare = FALSE, quantiles = NULL, at_survival = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... ) tda_km(formula, data, ...)
formula |
|
data |
a data frame. |
dir |
working directory. |
... |
passed to |
start, lower, upper, status
|
columns for |
tp |
interval boundaries for the life table, e.g.
|
cfrac |
for |
weights |
optional case weights, a column name or a vector as
long as the data – TDA's |
options |
a named list of further TDA options, passed through. |
compare |
for |
quantiles |
for |
at_survival |
for |
The survivor function's standard errors are the usual Greenwood
estimate (the manual gives the formula in section 6.5.2), the same
one survival::survfit reports, so the two agree on identical
data.
An object carrying table, blocks with one entry per
group or transition, and for the product limit median. Be
precise about the pair: table is deliberately only the
first block, the convenience view for the common single-group
call; a grouped or multi-transition fit's full result is
blocks (named by group), and anything that must see
everything – comparisons, exports, your summaries – should
read do.call(rbind, fit$blocks), never table alone.
The product-limit columns are time, events,
censored, n.risk, survivor, std.err
and cum.rate.
The second argument of Surv() is the destination state, not simply
an event indicator. Zero means no transition, so it is a censored case. A
value above 1 is a second destination, which makes the data competing
risks, and the estimate is returned per transition in $blocks.
Other rate models:
tda_constrain(),
tda_control(),
tda_rates(),
tda_split(),
tda_survivor(),
tda_transitions(),
vcov.tda_fit()
d <- data.frame(t = c(4, 3, 1, 1, 2, 2, 3, 5), s = c(1, 1, 1, 0, 1, 1, 0, 1)) km <- tda_km(Surv(t, s) ~ 1, d) km$table plot(km) # ltb: the same data grouped into intervals rather than at each event time tda_ltb(Surv(t, s) ~ 1, d, tp = seq(0, 6, 2))$table # ple: tda_km's underlying function, with two features tda_km does # not expose -- compare = TRUE tests whether group survivor functions # differ, and quantiles reads the curve at chosen times set.seed(1) d1b <- data.frame(t = round(rexp(40, 0.1), 1) + 0.5, s = rbinom(40, 1, 0.8), grp = rep(c("A", "B"), 20)) pf <- tda_ple(Surv(t, s) ~ factor(grp), d1b, compare = TRUE, quantiles = c(5, 10)) pf$comparison # a log-rank test between the two groups' curves pf$quantiles # the survivor function at t = 5 and t = 10, per group # dple, dltb: the discrete-time versions, for integer time already grouped # into periods -- t itself is the period here, not a continuous duration set.seed(44) d2 <- data.frame(t = sample(1:10, 60, TRUE), s = rbinom(60, 1, 0.8)) tda_dple(Surv(t, s) ~ 1, d2)$table tda_dltb(Surv(t, s) ~ 1, d2)$table # diple: the event is known only to fall between lower and upper set.seed(45) d3 <- data.frame(start = 0, lower = sample(1:8, 40, TRUE)) d3$upper <- d3$lower + sample(1:3, 40, TRUE) d3$status <- rbinom(40, 1, 0.85) tda_diple(d3, start = "start", lower = "lower", upper = "upper", status = "status")$tabled <- data.frame(t = c(4, 3, 1, 1, 2, 2, 3, 5), s = c(1, 1, 1, 0, 1, 1, 0, 1)) km <- tda_km(Surv(t, s) ~ 1, d) km$table plot(km) # ltb: the same data grouped into intervals rather than at each event time tda_ltb(Surv(t, s) ~ 1, d, tp = seq(0, 6, 2))$table # ple: tda_km's underlying function, with two features tda_km does # not expose -- compare = TRUE tests whether group survivor functions # differ, and quantiles reads the curve at chosen times set.seed(1) d1b <- data.frame(t = round(rexp(40, 0.1), 1) + 0.5, s = rbinom(40, 1, 0.8), grp = rep(c("A", "B"), 20)) pf <- tda_ple(Surv(t, s) ~ factor(grp), d1b, compare = TRUE, quantiles = c(5, 10)) pf$comparison # a log-rank test between the two groups' curves pf$quantiles # the survivor function at t = 5 and t = 10, per group # dple, dltb: the discrete-time versions, for integer time already grouped # into periods -- t itself is the period here, not a continuous duration set.seed(44) d2 <- data.frame(t = sample(1:10, 60, TRUE), s = rbinom(60, 1, 0.8)) tda_dple(Surv(t, s) ~ 1, d2)$table tda_dltb(Surv(t, s) ~ 1, d2)$table # diple: the event is known only to fall between lower and upper set.seed(45) d3 <- data.frame(start = 0, lower = sample(1:8, 40, TRUE)) d3$upper <- d3$lower + sample(1:3, 40, TRUE) d3$status <- rbinom(40, 1, 0.85) tda_diple(d3, start = "start", lower = "lower", upper = "upper", status = "status")$table
These take data rather than a formula, following cor and
summary: there is no response and no model here. A data frame, a
matrix, or loose vectors are all accepted, and non-numeric columns are
dropped.
tda_dstat(..., by = NULL, options = list(), dir = tempfile("tda")) tda_corr(..., options = list(), dir = tempfile("tda"))tda_dstat(..., by = NULL, options = list(), dir = tempfile("tda")) tda_corr(..., options = list(), dir = tempfile("tda"))
... |
a data frame, a matrix, or vectors. |
by |
optional grouping, as a vector or a one-sided formula, in the
manner of |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
tda_dstat reports each variable's minimum, maximum, mean,
standard deviation (denominator , or the weight total
minus one under case weights) and sum. tda_corr and
tda_cov are the ordinary product-moment correlation and the
-denominator covariance – cor() and cov()
– extended to case weights when a cwt command is active
(manual, section 6.2.6). All of them compute over every case given,
including any -5 standing in for an NA – see
?tdaR on missing values.
An object carrying a table, or for tda_corr a
matrix.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_segr(),
tda_subm()
set.seed(1) d <- data.frame(x = round(rnorm(40, 10, 3), 1)) d$y <- round(2 + 0.8 * d$x + rnorm(40, sd = 2), 1) tda_dstat(d) tda_corr(d$x, d$y)set.seed(1) d <- data.frame(x = round(rnorm(40, 10, 3), 1)) d$y <- round(2 + 0.8 * d$x + rnorm(40, sd = 2), 1) tda_dstat(d) tda_corr(d$x, d$y)
Runs TDA's etest, which computes the eigenvalues and
eigenvectors of a square matrix and reports the residual of each.
It is a test of TDA's eigen routines rather than a general
facility – eigen is what you want for ordinary
work – but it is the way to check what TDA itself computes for a
matrix a model is about to be fitted on.
tda_eigen( x, algorithm = 1, max_iter = NULL, options = list(), dir = tempfile("tda"), ... )tda_eigen( x, algorithm = 1, max_iter = NULL, options = list(), dir = tempfile("tda"), ... )
x |
a square numeric matrix. |
algorithm |
1 (default), 2 ( |
max_iter |
for |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
The eigenvalues come from an exporter rather than from the printed table, so they arrive at full precision instead of rounded to the print format.
A data frame with one row per eigenvalue: re and
im, its real and imaginary parts. attr(x, "run")
carries the run, whose output holds the eigenvectors and residuals.
m <- diag(c(2, 3, 5)) tda_eigen(m)m <- diag(c(2, 3, 5)) tda_eigen(m)
tda_episodes returns the episode data edef builds from a
formula, which is what every model in this package is actually fitted to.
It is the way to check that a Surv() specification means what you
intended before trusting a fit.
tda_episodes( formula, data, vars = NULL, options = list(), dir = tempfile("tda"), ... ) tda_state_dist( formula, data, times, id = NULL, spell = NULL, options = list(), dir = tempfile("tda"), ... )tda_episodes( formula, data, vars = NULL, options = list(), dir = tempfile("tda"), ... ) tda_state_dist( formula, data, times, id = NULL, spell = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
the same |
data |
a data frame. |
vars |
additional variables to carry into the output, as names. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
times |
time points at which to evaluate the state distribution. |
id, spell
|
for |
tda_state_dist gives the distribution over states at a set of time
points – how many cases occupy each state when – which is the natural
summary of multi-state data.
A data frame of episodes, or of state proportions by time.
Other episodes:
tda_esort()
d <- data.frame(t = c(4, 3, 1, 5), s = c(1, 0, 1, 1), x = c(2, 1, 3, 1)) tda_episodes(Surv(t, s) ~ x, d) tda_state_dist(Surv(t, s) ~ x, d, times = c(1, 3, 5))d <- data.frame(t = c(4, 3, 1, 5), s = c(1, 0, 1, 1), x = c(2, 1, 3, 1)) tda_episodes(Surv(t, s) ~ x, d) tda_state_dist(Surv(t, s) ~ x, d, times = c(1, 3, 5))
TDA was written when a data file could be larger than the machine's
memory, and these commands work a record at a time on an ASCII file
rather than loading it: esort sorts the records, eskip
drops character positions, eselect keeps the records whose key
appears in a second file, emerge joins sorted files on a key.
They are file-in, file-out, on raw text records addressed by character
position, and they are that here too: name the input and the output
file and the output path comes back, invisibly, with the run as its
"run" attribute. Nothing is read back; for a data frame, use
tda_read_table on the file you asked for.
tda_esort(file, keys, out, options = list(), dir = tempfile("tda")) tda_eskip(file, drop, out, options = list(), dir = tempfile("tda")) tda_eselect( file, with, keys, with_keys = keys, out, options = list(), dir = tempfile("tda") ) tda_emerge( file, with, keys, with_keys = keys, out, options = list(), dir = tempfile("tda") ) tda_ejoin( data, id, start, end, state, with = NULL, with_id = NULL, with_start = NULL, with_end = NULL, with_state = NULL, options = list(), dir = tempfile("tda") )tda_esort(file, keys, out, options = list(), dir = tempfile("tda")) tda_eskip(file, drop, out, options = list(), dir = tempfile("tda")) tda_eselect( file, with, keys, with_keys = keys, out, options = list(), dir = tempfile("tda") ) tda_emerge( file, with, keys, with_keys = keys, out, options = list(), dir = tempfile("tda") ) tda_ejoin( data, id, start, end, state, with = NULL, with_id = NULL, with_start = NULL, with_end = NULL, with_state = NULL, options = list(), dir = tempfile("tda") )
file |
an existing ASCII data file. |
keys |
character positions in the record, as a start and end pair –
|
out |
the output file to write. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
drop |
character positions to drop, in the same form. |
with |
a second file supplying the keys, or the file(s) to merge in. |
with_keys |
where the key sits in |
data |
for |
id, start, end, state
|
for |
with_id, with_start, with_end, with_state
|
for |
tda_emerge is a merge join and requires both inputs sorted in
ascending order on the key; it says so and stops otherwise, naming the two
records that are out of order.
tda_ejoin is different in kind: it joins episode data into
levels, takes data frames, and returns one through the export channel.
The output path, invisibly, for the four file utilities; a data
frame for tda_ejoin.
Other episodes:
tda_episodes()
f <- tempfile(); writeLines(c("103 30", "101 10", "102 20"), f) o <- tempfile() tda_esort(f, keys = c(1, 3), out = o) readLines(o) tda_eskip(f, drop = c(1, 4), out = o) readLines(o) # eselect/emerge need their inputs already sorted on the key f1 <- tempfile(); writeLines(c("101 10", "102 20", "103 30"), f1) f2 <- tempfile(); writeLines(c("101 1", "103 3"), f2) tda_eselect(f1, with = f2, keys = c(1, 3), out = o); readLines(o) tda_emerge(f1, with = f2, keys = c(1, 3), out = o); readLines(o) # ejoin: joins one or two episode datasets, splitting overlapping # spells into levels -- an activity spanning 0-10, and a state that # changes mid-activity at t=4, joined so each row is a period where # neither changes act <- data.frame(id = 1, start = 0, end = 10, state = 1) st <- data.frame(id = 1, start = c(0, 4), end = c(4, 10), state = c(1, 2)) tda_ejoin(act, id = "id", start = "start", end = "end", state = "state", with = st)f <- tempfile(); writeLines(c("103 30", "101 10", "102 20"), f) o <- tempfile() tda_esort(f, keys = c(1, 3), out = o) readLines(o) tda_eskip(f, drop = c(1, 4), out = o) readLines(o) # eselect/emerge need their inputs already sorted on the key f1 <- tempfile(); writeLines(c("101 10", "102 20", "103 30"), f1) f2 <- tempfile(); writeLines(c("101 1", "103 3"), f2) tda_eselect(f1, with = f2, keys = c(1, 3), out = o); readLines(o) tda_emerge(f1, with = f2, keys = c(1, 3), out = o); readLines(o) # ejoin: joins one or two episode datasets, splitting overlapping # spells into levels -- an activity spanning 0-10, and a state that # changes mid-activity at t=4, joined so each row is a period where # neither changes act <- data.frame(id = 1, start = 0, end = 10, state = 1) st <- data.frame(id = 1, start = c(0, 4), end = c(4, 10), state = c(1, 2)) tda_ejoin(act, id = "id", start = "start", end = "end", state = "state", with = st)
evalfi: given an expression and an interval domain for each of
its arguments, returns an interval guaranteed to contain the
expression's true range over that domain – interval arithmetic, not a
numeric evaluation at a point. The bound is conservative rather than
tight where a variable appears more than once (the standard
"dependency problem" of interval arithmetic: each occurrence is
widened independently, as if they were unrelated variables that
happened to share a domain) – evalfi(x = c(0, 3), "x*x-2*x+1")
returns [-5, 10], not the true range [0, 4] that
(x-1)^2 takes over [0, 3]. evalfi1 is the same but
for the first derivative.
tda_evalfi( expr, ..., derivative = FALSE, options = list(), dir = tempfile("tda") )tda_evalfi( expr, ..., derivative = FALSE, options = list(), dir = tempfile("tda") )
expr |
the expression, as a string, in TDA's language. |
... |
one interval per argument the expression uses, named for
the argument, each as |
derivative |
if |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
^ is not a valid operator in an interval expression – write
a power as repeated multiplication (x*x, not x^2).
A named numeric vector, c(lower, upper).
Other sequence analysis:
tda_fml(),
tda_frml(),
tda_seq_info(),
tda_seqgc(),
tda_seqm(),
tda_seqmd(),
tda_seqpe(),
tda_seqpm()
# true range of (x-1)^2 over [0,3] is [0,4] -- this is wider, since x # appears twice and interval arithmetic cannot see they are the same x tda_evalfi("x*x-2*x+1", x = c(0, 3)) tda_evalfi("x*x-2*x+1", x = c(0, 3), derivative = TRUE) # 2x-2, exact # here: [-2,4]# true range of (x-1)^2 over [0,3] is [0,4] -- this is wider, since x # appears twice and interval arithmetic cannot see they are the same x tda_evalfi("x*x-2*x+1", x = c(0, 3)) tda_evalfi("x*x-2*x+1", x = c(0, 3), derivative = TRUE) # 2x-2, exact # here: [-2,4]
tda_expand runs TDA's expm, which expands an expression
into its fully written-out form – a model formula with interaction
shorthand becomes the explicit list of terms. tda_mparse runs
mparse, which parses a matrix expression and reports how it
read it, without evaluating anything.
tda_expand(expr, setup = NULL, options = list(), dir = tempfile("tda"), ...) tda_mparse( expr, setup = NULL, mfmt = NULL, options = list(), dir = tempfile("tda"), ... )tda_expand(expr, setup = NULL, options = list(), dir = tempfile("tda"), ...) tda_mparse( expr, setup = NULL, mfmt = NULL, options = list(), dir = tempfile("tda"), ... )
expr |
the expression, as a single string. |
setup |
TDA commands to run first, as a character vector. A
matrix expression needs its matrices to exist, so this is where
|
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
mfmt |
for |
Both are diagnostics: they answer "what did TDA make of what I wrote", which is otherwise only visible in an error message.
A character vector: the lines TDA printed in response.
attr(x, "run") carries the run.
tda_expand("A*B") tda_mparse("A+B", setup = c("mdefi(2,2,A);", "mdefi(2,2,B);"))tda_expand("A*B") tda_mparse("A+B", setup = c("mdefi(2,2,A);", "mdefi(2,2,B);"))
Fits a generalized linear model, taking R's family objects.
TDA_FAMILIES tda_glm( formula, data, family = stats::gaussian, link = NULL, custom_link = NULL, domain = NULL, trials = NULL, weights = NULL, intercept = NULL, start = NULL, predictions = FALSE, protocol = FALSE, equality = NULL, inequality = NULL, control = NULL, options = list(), dir = tempfile("tda"), ... )TDA_FAMILIES tda_glm( formula, data, family = stats::gaussian, link = NULL, custom_link = NULL, domain = NULL, trials = NULL, weights = NULL, intercept = NULL, start = NULL, predictions = FALSE, protocol = FALSE, equality = NULL, inequality = NULL, control = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a two-sided formula. |
data |
a data frame. |
family |
an R family object, a family function, its name, or TDA's
own |
link |
the link function – a name (from Families and links
below) or TDA's |
custom_link |
a user-defined link function, one not among the 8
in |
domain |
the domain |
trials |
for a binomial model, the number of trials, with the
response given as the number of successes (not a proportion) –
|
weights |
optional case weights, a column name in |
intercept |
|
start |
optional starting values, in the order the predictors
are listed – |
predictions |
also write out each case's fitted mean, linear
predictor, and predictor values – |
protocol |
ask TDA to also write its iteration-by-iteration
diagnostic log – |
equality, inequality
|
linear constraints on the coefficients,
written in the predictors' own names – the same mechanism and
syntax as |
control |
convergence settings from |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object of class tda_fit, its fit element
(shown by summary()) carrying the deviance and residual
degrees of freedom, the rank of the design matrix, and – for the
families where TDA prints them – the Pearson statistic and the
ML- and deviance-based dispersion estimates. Cases with missing
values are dropped before the fit, with a message (see
?tdaR). logLik() is
NA: TDA's glm() never prints a log-likelihood
itself, only Deviance – and it stays that way here rather than
being reconstructed from Deviance, since that reconstruction would
be a derived, unverifiable-by-the-user computation on top of what
TDA itself actually computes.
TDA_FAMILIES maps R's names onto TDA's d= (distribution)
and link= numbering, from TDA's manual (which
tda_help("glm") cannot show – glm has no entry in
TDA's help database, despite being fully implemented). The first
link
listed for each family is the default, and is the canonical one:
| family | d= | links (name = TDA's link=) |
gaussian |
1 | identity=1, log=2, inverse=4 |
binomial |
2 | logit=3, probit=5, cloglog=6 |
poisson |
3 | log=2, identity=1, sqrt=7 |
Gamma |
4 | inverse=4, identity=1, log=2 |
inverse.gaussian |
5 | 1/mu^2=8, inverse=4, identity=1, log=2 |
TDA's link numbering runs 1 to 8 in total (identity, log, logit,
reciprocal/inverse, probit, cloglog, sqrt, and the inverse-Gaussian's
quadratic inverse, 1/mu^2) – every one of the 8 appears above, on
whichever family it is offered for through R's family()
system. A family TDA does not implement, or a link it does not offer
for that family, is rejected with the list of what is available rather
than silently replaced by a default.
glm's ab= option – the domain for a user-defined
link function, one not among the 8 above, given as its TDA
expression on the right-hand side of the command rather than a number
– is reachable through custom_link/domain below.
Other regression:
TDA_QRMODELS,
tda_freg(),
tda_gdf(),
tda_l1reg(),
tda_lsreg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
set.seed(5) d <- data.frame(x = round(rnorm(40), 2)) d$y <- rbinom(40, 1, plogis(-0.5 + 1.2 * d$x)) fit <- tda_glm(y ~ x, d, family = binomial) fit predict(fit) # fitted values, on the data # the model was fit on predict(fit, newdata = data.frame(x = 1)) # a binomial model of trial data (successes out of a known number of # trials), not just 0/1 outcomes -- the response is the success count, # trials the number of trials, not a proportion set.seed(1) n <- 60 d2 <- data.frame(x = rnorm(n)) p <- plogis(0.3 + 0.8 * d2$x) d2$trials <- sample(5:20, n, replace = TRUE) d2$successes <- rbinom(n, d2$trials, p) coef(tda_glm(successes ~ x, d2, family = binomial, trials = d2$trials)) # case weights instead (or as well) -- a different thing from # the trial counts above d2$imp <- runif(n, 0.5, 2) coef(tda_glm(successes ~ x, d2, family = binomial, trials = d2$trials, weights = "imp")) # a constrained fit: the two coefficients forced to sum to exactly 1 d3 <- data.frame(x1 = rnorm(60), x2 = rnorm(60)) d3$y <- rbinom(60, 1, plogis(0.6 * d3$x1 + 0.4 * d3$x2)) coef(tda_glm(y ~ x1 + x2, d3, family = binomial, equality = "x1 + x2 = 1")) # family and link as TDA's raw numbers -- useful when translating # a .cf file directly, which only ever writes them this way. Reaches # the identical call as family = Gamma(link = "log"). set.seed(2) d4 <- data.frame(x = rnorm(60)) d4$y <- rgamma(60, shape = 2, rate = 2 / exp(0.5 + 0.3 * d4$x)) coef(tda_glm(y ~ x, d4, family = 4, link = 2)) # a user-defined link -- the logit link, spelled out by hand instead # of using link = "logit"; reaches the same fit exactly coef(tda_glm(y ~ x, d, family = binomial, custom_link = "log(mue / (1 - mue))", start = c(0, 0)))set.seed(5) d <- data.frame(x = round(rnorm(40), 2)) d$y <- rbinom(40, 1, plogis(-0.5 + 1.2 * d$x)) fit <- tda_glm(y ~ x, d, family = binomial) fit predict(fit) # fitted values, on the data # the model was fit on predict(fit, newdata = data.frame(x = 1)) # a binomial model of trial data (successes out of a known number of # trials), not just 0/1 outcomes -- the response is the success count, # trials the number of trials, not a proportion set.seed(1) n <- 60 d2 <- data.frame(x = rnorm(n)) p <- plogis(0.3 + 0.8 * d2$x) d2$trials <- sample(5:20, n, replace = TRUE) d2$successes <- rbinom(n, d2$trials, p) coef(tda_glm(successes ~ x, d2, family = binomial, trials = d2$trials)) # case weights instead (or as well) -- a different thing from # the trial counts above d2$imp <- runif(n, 0.5, 2) coef(tda_glm(successes ~ x, d2, family = binomial, trials = d2$trials, weights = "imp")) # a constrained fit: the two coefficients forced to sum to exactly 1 d3 <- data.frame(x1 = rnorm(60), x2 = rnorm(60)) d3$y <- rbinom(60, 1, plogis(0.6 * d3$x1 + 0.4 * d3$x2)) coef(tda_glm(y ~ x1 + x2, d3, family = binomial, equality = "x1 + x2 = 1")) # family and link as TDA's raw numbers -- useful when translating # a .cf file directly, which only ever writes them this way. Reaches # the identical call as family = Gamma(link = "log"). set.seed(2) d4 <- data.frame(x = rnorm(60)) d4$y <- rgamma(60, shape = 2, rate = 2 / exp(0.5 + 0.3 * d4$x)) coef(tda_glm(y ~ x, d4, family = 4, link = 2)) # a user-defined link -- the logit link, spelled out by hand instead # of using link = "logit"; reaches the same fit exactly coef(tda_glm(y ~ x, d, family = binomial, custom_link = "log(mue / (1 - mue))", start = c(0, 0)))
fml maximises a log-likelihood you write yourself, which is what TDA
offers that a fixed catalogue of models cannot. The likelihood is written
in an expression language, evaluated inside TDA rather than as an R
function – but as of this version, that expression can be written in
ordinary R syntax and translated automatically, rather than TDA's.
tda_fml( definitions, data, start = NULL, control = NULL, constraints = NULL, residuals = FALSE, residual_vars = NULL, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )tda_fml( definitions, data, start = NULL, control = NULL, constraints = NULL, residuals = FALSE, residual_vars = NULL, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )
definitions |
either an unevaluated |
data |
a data frame; its columns are the variables the definitions can refer to. |
start |
optional named vector of starting values, e.g.
|
control |
convergence settings from |
constraints |
optional linear constraints on the parameters –
|
residuals |
ask TDA to also compute, per case, its
contribution to the log-likelihood at the converged parameters –
|
residual_vars |
with |
protocol |
ask TDA to also write its iteration-by-iteration
diagnostic log – |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object of class tda_fit. With residuals =
TRUE, also carries $residuals (see residuals above).
Give definitions as an unevaluated { } block of plain R
assignments instead of a character vector, and it is translated to TDA's
own expression syntax for you – never actually run as R code (DES,
rate and the rest only ever exist inside TDA, so it cannot be).
ifelse(cond, yes, no) becomes TDA's if() (TDA's
if takes a 2- or 3-argument
if(cond, then)/if(cond, then, else) shape matching
ifelse exactly, not R's control-flow if), and
R's comparison operators (<, >, <=, >=,
==, !=) become TDA's comparison functions (lt,
gt, le, ge, eq, ne). Arithmetic
(+ - * / ^), &/|, and ordinary function calls
(exp, log, negbin, ...) already mean the same thing
in both and pass through unchanged.
These six TDA functions are not the strict comparisons their R
equivalents are. Every one of them – lt, le, gt,
ge, eq, ne alike – carries a fixed tolerance,
EPSI2 = 1000 * DBL_EPSILON (about 2.22e-13): le,
say, computes x <= y + EPSI2, not x <= y. This can
matter on real data: a case in examples/exam/rrdat.1
has PRESN/PRES - 1 equal to 0.2 exactly in exact arithmetic,
and the two land on different sides of 0.2 once represented as
IEEE 754 doubles – ge(x, 0.2) inside TDA still calls it true, R's
own x >= 0.2 on the identical computation does not. Applied
consistently across all six, at least, but nowhere in TDA's
documentation: not in the manual, not in tda_help()'s
operator table, which describes le as plainly as “true if
less than, or equal” with no footnote at all. A hand-written R
replication of a TDA calculation involving a comparison near a round
number (==, or a boundary like 0.2 here) can therefore
disagree with TDA's output at that boundary, for a
reason with nothing to do with which language computed it – this is a
property of TDA's expression evaluator, present whether the
comparison was written by hand in TDA's syntax or reached it through
this translation.
tda_fml({
rate = exp(a0 + COHO2 * a1 + COHO3 * a2 + W * a3)
l1 = ifelse(DES, log(rate), 0)
fn = l1 - rate * DUR
}, data = d, start = c(-4, 0, 0, 0))
The older, direct form – a character vector of TDA's assignment
syntax – still works exactly as before, for anything the translator
does not (yet) cover, or for pasting a .cf file's text in
directly.
tda_fml(c("xb = b0 + x * b1",
"fn = -0.5 * (y - xb)^2"), data = d)
estimates b0 and b1 by least squares written as a likelihood.
TDA's functions are available, so fn = negbin(alpha, gamma, y)
and the rest work.
Other sequence analysis:
tda_evalfi(),
tda_frml(),
tda_seq_info(),
tda_seqgc(),
tda_seqm(),
tda_seqmd(),
tda_seqpe(),
tda_seqpm()
set.seed(1) d <- data.frame(x = 1:20, y = 2 + 0.5 * (1:20) + rnorm(20)) tda_fml(c("xb = b0 + x * b1", "fn = -0.5 * (y - xb)^2"), d) # the same model, written in R syntax instead tda_fml({ xb = b0 + x * b1 fn = -0.5 * (y - xb)^2 }, d) # a compound Poisson (negative binomial) count regression -- TDA has no # separate command for this (unlike its plain Poisson, which is a glm() # family), but negbin(alpha, gamma, k) is a built-in log-likelihood # function in its expression language, reachable through fml like any # other: gamma is the mean, alpha = 1/sigma the dispersion set.seed(7) d2 <- data.frame(x = rnorm(200)) d2$ndi <- rnbinom(200, mu = exp(0.5 + 0.8 * d2$x), size = 2) coef(tda_fml({ xb = b0 + x * b1 gamma = exp(xb) sigma = exp(sig) alpha = 1 / sigma fn = negbin(alpha, gamma, ndi) }, d2, start = list(b0 = 0, b1 = 0, sig = 0)))set.seed(1) d <- data.frame(x = 1:20, y = 2 + 0.5 * (1:20) + rnorm(20)) tda_fml(c("xb = b0 + x * b1", "fn = -0.5 * (y - xb)^2"), d) # the same model, written in R syntax instead tda_fml({ xb = b0 + x * b1 fn = -0.5 * (y - xb)^2 }, d) # a compound Poisson (negative binomial) count regression -- TDA has no # separate command for this (unlike its plain Poisson, which is a glm() # family), but negbin(alpha, gamma, k) is a built-in log-likelihood # function in its expression language, reachable through fml like any # other: gamma is the mean, alpha = 1/sigma the dispersion set.seed(7) d2 <- data.frame(x = rnorm(200)) d2$ndi <- rnbinom(200, mu = exp(0.5 + 0.8 * d2$x), size = 2) coef(tda_fml({ xb = b0 + x * b1 gamma = exp(xb) sigma = exp(sig) alpha = 1 / sigma fn = negbin(alpha, gamma, ndi) }, d2, start = list(b0 = 0, b1 = 0, sig = 0)))
freg fits a regression function you write yourself, in the same way
tda_fml takes a likelihood. The expression is TDA's language,
not R's.
tda_freg( definitions, data, start = NULL, control = NULL, constraints = NULL, residuals = FALSE, residual_vars = NULL, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )tda_freg( definitions, data, start = NULL, control = NULL, constraints = NULL, residuals = FALSE, residual_vars = NULL, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )
definitions |
a character vector of TDA assignments, the last defining
|
data |
a data frame; its columns are the variables the definitions may refer to. |
start |
optional named vector of starting values. |
control |
convergence settings from |
constraints |
optional linear constraints on the parameters –
|
residuals |
ask TDA to also compute, per case, its
contribution to |
residual_vars |
with |
protocol |
ask TDA to also write its iteration-by-iteration
diagnostic log – |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
tda_nlreg's expr argument also fits a
user-written nonlinear function now, using nlreg's dedicated
algorithm (proper standard errors, and orthogonal distance regression
as an option) rather than a general-purpose minimiser – prefer it for
an ordinary nonlinear least-squares fit. tda_freg stays the more
flexible tool for the cases nlreg cannot express at all: any
summed objective, not just a sum of squared residuals (a robust loss,
a weighted or constrained one, anything written by hand).
An object of class tda_fit. With residuals = TRUE,
also carries $residuals.
fn is the quantity summed over cases and minimised, not the
regression function itself. Least squares is therefore the squared
residual:
tda_freg(c("r = y - a * exp(b * x)", "fn = r*r"), d,
start = c(a = 1, b = 0.1))
TDA's default minimiser is Newton, which overflows exp() on the
first step for functions of this shape. tda_freg therefore defaults
to BFGS, which is stable and reaches the same estimates as nls.
Pass control = tda_control(algorithm = 5) for TDA's default.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_gdf(),
tda_l1reg(),
tda_lsreg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
set.seed(1) d <- data.frame(x = 1:20, y = 3 * exp(0.1 * (1:20)) + rnorm(20, 0, 0.5)) tda_freg(c("r = y - a * exp(b * x)", "fn = r*r"), d, start = c(a = 1, b = 0.1)) # the same model, written in R syntax instead tda_freg({ r = y - a * exp(b * x) fn = r * r }, d, start = c(a = 1, b = 0.1))set.seed(1) d <- data.frame(x = 1:20, y = 3 * exp(0.1 * (1:20)) + rnorm(20, 0, 0.5)) tda_freg(c("r = y - a * exp(b * x)", "fn = r*r"), d, start = c(a = 1, b = 0.1)) # the same model, written in R syntax instead tda_freg({ r = y - a * exp(b * x) fn = r * r }, d, start = c(a = 1, b = 0.1))
tda_freq counts occurrences of each combination of values across
one or more variables; tda_freq1 counts occurrences of each
value of one variable; tda_freq2 cross-tabulates two. TDA's
manual documents all three (freq, freq1, freq2)
on one shared page, since they mostly share the same options
(maxcat=/fmt=/tfmt=/df=) and differ mainly
in shape. Their R outputs are shaped
differently too – tda_freq/tda_freq1 return a
table, tda_freq2 a matrix of counts – but all
three describe a frequency distribution, so they sit together here as TDA's
own manual does.
tda_freq(..., maxcat = NULL, dir = tempfile("tda")) tda_freq1(..., maxcat = NULL, options = list(), dir = tempfile("tda")) tda_freq2( ..., contingency = FALSE, maxcat = NULL, options = list(), dir = tempfile("tda") )tda_freq(..., maxcat = NULL, dir = tempfile("tda")) tda_freq1(..., maxcat = NULL, options = list(), dir = tempfile("tda")) tda_freq2( ..., contingency = FALSE, maxcat = NULL, options = list(), dir = tempfile("tda") )
... |
a data frame, a matrix, or vectors. |
maxcat |
the maximum number of categories per variable (all
three commands' own |
dir |
working directory. |
options |
a named list of further TDA options, passed through. |
contingency |
for |
An object carrying a table for tda_freq/
tda_freq1, a matrix for tda_freq2, and, with
contingency = TRUE, a measures named vector (chi-square,
Cramer's V, lambda, Somers' D, and the rest).
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_segr(),
tda_subm()
set.seed(48) d <- data.frame(g = sample(1:3, 80, TRUE), h = sample(1:2, 80, TRUE)) tda_freq1(d["g"])$table tda_freq(d)$table # a joint table over both variables at once, unlike # tda_freq1's single-variable count tda_freq2(d)$matrix # a cross-tabulation, rows by g, columns by h tda_freq2(d, contingency = TRUE)$measures[c("Cramer's V", "Phi")]set.seed(48) d <- data.frame(g = sample(1:3, 80, TRUE), h = sample(1:2, 80, TRUE)) tda_freq1(d["g"])$table tda_freq(d)$table # a joint table over both variables at once, unlike # tda_freq1's single-variable count tda_freq2(d)$matrix # a cross-tabulation, rows by g, columns by h tda_freq2(d, contingency = TRUE)$measures[c("Cramer's V", "Phi")]
frml: like tda_fml, but for episode (survival)
data rather than plain cross-sectional rows – fn is the
log-likelihood contribution of one episode, and can refer to
time (the position within it) the way tda_rate's
own define can. This is not fml under another name:
the same definitions that work with fml on plain rows fail
here with “no episode data defined” until an actual episode
structure (survival::Surv()) is given.
tda_frml( formula, data, definitions, start = NULL, id = NULL, spell = NULL, control = NULL, constraints = NULL, residuals = FALSE, residual_vars = NULL, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )tda_frml( formula, data, definitions, start = NULL, id = NULL, spell = NULL, control = NULL, constraints = NULL, residuals = FALSE, residual_vars = NULL, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )
formula |
a |
data |
a data frame. |
definitions |
a character vector of assignments, evaluated in
order inside TDA, the last of which must define |
start |
optional named list of starting values, in the order the definitions introduce the parameters. |
id, spell
|
columns identifying the case and numbering its spells,
for multi-episode data – the same pair |
control |
optional |
constraints |
optional linear constraints on the parameters –
|
residuals |
ask TDA to also compute, per episode, its
contribution to |
residual_vars |
with |
protocol |
ask TDA to also write its iteration-by-iteration
diagnostic log – |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
fn's expression cannot reference the raw duration/status columns
from data directly – Surv()'s columns are consumed
by edef() into TDA's internal episode representation, and are
not separately visible by name afterward. An
fn written against the original column names fails with those
names listed as parameters to estimate (TDA's convention for any
identifier it does not otherwise recognise), not as a lookup error.
Use TDA's built-in accessors for an episode instead: ts and
tf (start and finish time), org and des (origin
and destination state), time (tf - ts, and the same
built-in tda_rate's define can use). A
covariate, by contrast, is referenced by its own name from
formula, translated automatically the same way
tda_fml does it.
An object of class tda_fit. With residuals = TRUE,
also carries $residuals.
Other sequence analysis:
tda_evalfi(),
tda_fml(),
tda_seq_info(),
tda_seqgc(),
tda_seqm(),
tda_seqmd(),
tda_seqpe(),
tda_seqpm()
set.seed(1) n <- 200 d <- data.frame(x = rnorm(n)) haz <- exp(0.5 + 0.8 * d$x) d$dur <- rexp(n, haz) d$status <- 1 # the exponential hazard model, written out by hand -- matches # tda_rate(Surv(dur, status) ~ x, d, model = "exponential"). des and # (tf - ts) are TDA's built-ins, not d's dur/status columns -- see # Details. fit <- tda_frml(Surv(dur, status) ~ x, d, c("xb = b0 + x * b1", "gamma = exp(xb)", "fn = des * xb - gamma * (tf - ts)")) coef(fit) coef(tda_rate(Surv(dur, status) ~ x, d, model = "exponential")) # the same model, written in R syntax instead fit2 <- tda_frml(Surv(dur, status) ~ x, d, { xb = b0 + x * b1 gamma = exp(xb) fn = des * xb - gamma * (tf - ts) }) coef(fit2)set.seed(1) n <- 200 d <- data.frame(x = rnorm(n)) haz <- exp(0.5 + 0.8 * d$x) d$dur <- rexp(n, haz) d$status <- 1 # the exponential hazard model, written out by hand -- matches # tda_rate(Surv(dur, status) ~ x, d, model = "exponential"). des and # (tf - ts) are TDA's built-ins, not d's dur/status columns -- see # Details. fit <- tda_frml(Surv(dur, status) ~ x, d, c("xb = b0 + x * b1", "gamma = exp(xb)", "fn = des * xb - gamma * (tf - ts)")) coef(fit) coef(tda_rate(Surv(dur, status) ~ x, d, model = "exponential")) # the same model, written in R syntax instead fit2 <- tda_frml(Surv(dur, status) ~ x, d, { xb = b0 + x * b1 gamma = exp(xb) fn = des * xb - gamma * (tf - ts) }) coef(fit2)
tda_g reaches any of TDA's forty graph commands; the named functions
are the ones with an obvious meaning.
tda_g(g, cmd, options = list(), dir = tempfile("tda"), ...)tda_g(g, cmd, options = list(), dir = tempfile("tda"), ...)
g |
a |
cmd |
the command name, e.g. |
options |
a named list of options for the command. |
dir |
working directory. |
... |
passed to |
An object carrying a table and the run.
Other graph analysis:
plot.tda_graph(),
tda_dmet(),
tda_g_analyses,
tda_graph(),
tda_locate_line(),
tda_ptree(),
tda_ucl()
e <- data.frame(from = c(1, 1, 2, 3), to = c(2, 3, 4, 4), value = 1) g <- tda_graph(e, directed = FALSE) tda_g(g, "gmst")$table # minimum spanning treee <- data.frame(from = c(1, 1, 2, 3), to = c(2, 3, 4, 4), value = 1) g <- tda_graph(e, directed = FALSE) tda_g(g, "gmst")$table # minimum spanning tree
One function per graph command, each a thin wrapper: the command name, the
options it takes and the table TDA writes. Everything TDA offers that has
no named wrapper is still reachable with tda_g.
tda_g_components(g, edges = FALSE, ...) tda_g_shortest(g, format = c("reachable", "matrix", "matrix_no_labels"), ...) tda_g_mst(g, algorithm = c("kruskal", "prim"), max = FALSE, sort = FALSE, ...) tda_g_cliques( g, algorithm = c("bron_kerbosch", "harary_ross"), min_size = NULL, sort = FALSE, ... ) tda_g_cycles( g, format = c("fundamental_nodes", "fundamental_edges", "all_v1", "all_v2"), ... ) tda_g_cutpoints(g, per_node = FALSE, ...) tda_g_flow(g, matrix = FALSE, ...) tda_g_degrees(g) tda_g_edges( g, format = c("edges", "lower_triangle", "lower_triangle_diag", "full", "full_square"), ... ) tda_g_transitive(g, ...) tda_g_aggregate(g, ...) tda_g_symmetric(g, ...) tda_g_toposort(g, relabel_graph = FALSE, ...) tda_g_nodes(g, ...) tda_g_dot(g, ...) tda_g_links(g, backward = FALSE, ...) tda_g_dcycles( g, format = c("per_cycle", "per_node", "progress"), stop_at_first = FALSE, ... ) tda_g_dblocks(g, ...) tda_g_compact(g, per_node = FALSE, ...) tda_g_gcliques(g, ...) tda_g_random(g, ...) tda_g_ownership(g, ...) tda_g_backward(g, ...) tda_g_paths(g, ...) tda_g_flowcontrol(g, ...) tda_g_centred(g, ...) tda_g_spantrees(g, edges = FALSE, ...) tda_g_reachable( g, format = c("count", "list", "strong_nodes", "strong_edges"), ... ) tda_g_neighbourhoods(g, ...) tda_g_independent(g, min_size = NULL, use_complement = FALSE, ...) tda_g_spanning(g) tda_g_eigen(g, n = NULL, tol = NULL, control = NULL, ...)tda_g_components(g, edges = FALSE, ...) tda_g_shortest(g, format = c("reachable", "matrix", "matrix_no_labels"), ...) tda_g_mst(g, algorithm = c("kruskal", "prim"), max = FALSE, sort = FALSE, ...) tda_g_cliques( g, algorithm = c("bron_kerbosch", "harary_ross"), min_size = NULL, sort = FALSE, ... ) tda_g_cycles( g, format = c("fundamental_nodes", "fundamental_edges", "all_v1", "all_v2"), ... ) tda_g_cutpoints(g, per_node = FALSE, ...) tda_g_flow(g, matrix = FALSE, ...) tda_g_degrees(g) tda_g_edges( g, format = c("edges", "lower_triangle", "lower_triangle_diag", "full", "full_square"), ... ) tda_g_transitive(g, ...) tda_g_aggregate(g, ...) tda_g_symmetric(g, ...) tda_g_toposort(g, relabel_graph = FALSE, ...) tda_g_nodes(g, ...) tda_g_dot(g, ...) tda_g_links(g, backward = FALSE, ...) tda_g_dcycles( g, format = c("per_cycle", "per_node", "progress"), stop_at_first = FALSE, ... ) tda_g_dblocks(g, ...) tda_g_compact(g, per_node = FALSE, ...) tda_g_gcliques(g, ...) tda_g_random(g, ...) tda_g_ownership(g, ...) tda_g_backward(g, ...) tda_g_paths(g, ...) tda_g_flowcontrol(g, ...) tda_g_centred(g, ...) tda_g_spantrees(g, edges = FALSE, ...) tda_g_reachable( g, format = c("count", "list", "strong_nodes", "strong_edges"), ... ) tda_g_neighbourhoods(g, ...) tda_g_independent(g, min_size = NULL, use_complement = FALSE, ...) tda_g_spanning(g) tda_g_eigen(g, n = NULL, tol = NULL, control = NULL, ...)
g |
a |
edges |
for |
... |
options for the command. |
format |
for |
algorithm |
for |
max |
for |
sort |
for |
min_size |
for |
per_node |
for |
matrix |
for |
relabel_graph |
for |
backward |
for |
stop_at_first |
for |
use_complement |
for |
n |
for |
tol |
for |
control |
for |
The descriptions below are Rohwer's, from TDA's manual; the exact
wording and the full option list for any command are available with
tda_help("gmst") and so on.
An object carrying table – the records the command
writes, in that command's layout (edges for the tree and path
commands, node rows for the centrality and component ones; see the
command's tda_help() entry) – or, for the few commands
whose output is ragged or non-tabular, table as a ragged
record list or text as plain lines.
tda_g_backward also carries summary, one row per node,
from the second file gbcf writes; TDA does not produce it
unless a file is named for it, so the wrapper asks by default.
tda_g_componentsconnected components (gcon).
tda_g_reachablefor each node of a directed graph, the
set of nodes reachable from it by a directed path (gdcon).
tda_g_cutpointscut nodes of an undirected graph
(gcut).
tda_g_transitivetransitive closure (gtcl).
tda_g_symmetricwhether every edge from i to j is
matched by one from j to i (gsym).
tda_g_toposorttopological sort of a directed graph
(gsort).
tda_g_cliquesall cliques – maximally connected
subgraphs – of an undirected graph (gcliq).
tda_g_independenta maximal independent set, found by a
greedy randomized search procedure (GRASP), so the answer is a good
one rather than a proven optimum (giset).
tda_g_compactcompact sets in an undirected valued graph
(gcset).
tda_g_neighbourhoodscompares the neighbourhoods of the
nodes and groups those that agree. Needs an unvalued graph; the
wrapper arranges that (gcni).
tda_g_shortesta shortest path for each pair of nodes.
Directed or undirected, valued or unvalued; in an unvalued graph
every edge counts as 1 (gsp).
tda_g_pathsall paths between any two nodes, with their
minimal or maximal length (gep).
tda_g_msta minimum, or maximum, spanning tree for each
connected component of an undirected valued graph (gmst).
tda_g_spantreesenumerates every spanning tree of an
undirected graph (gnst).
tda_g_cyclesa fundamental set of cycles, and optionally
all cycles, of an undirected graph (gcyc).
tda_g_dcyclescycles in a directed graph
(gdcyc).
tda_g_linksforward and backward links in a directed
graph (gdln).
tda_g_flowa maximal flow between each pair of nodes
joined by a directed path (gflow).
tda_g_flowcontrolthe quantities from which measures of
flow control are built, for a directed valued graph (gfc).
tda_g_ownershipintegrated ownership in a directed
valued graph (gio).
tda_g_backwarddirect and indirect backward control
(gbcf).
tda_g_centrednode-centred networks (gnc).
tda_g_nodesinformation about the nodes of the current
graph (gni).
tda_g_eigeneigenvalues and eigenvectors of the
adjacency matrix of an undirected graph (gev).
tda_g_aggregateaggregates the nodes of a valued graph
(gda).
tda_g_dblocksblocks of a directed graph
(gdcset).
tda_g_randomgenerates an unvalued graph with a given
number of nodes and edges (gcd).
tda_g_dot, tda_g_edges
write the graph out
as a Graphviz dot file, or an edge list/adjacency matrix,
respectively (gdot, gdp).
tda_g_degreesnode degrees from gni, TDA's
node-information command: in-degree, out-degree, loops, and a
degree column (for an undirected graph each incident edge is
reported on both sides, so the degree is the in-degree, not
the sum). Takes no further arguments.
TDA refuses a command whose graph is of the wrong kind rather than
answering wrongly, so the error message is worth reading. Most of the
gd* commands want a directed graph, gcliq, gcut,
gcyc, gmst, gnst, gcset and gnc
want an undirected one, and gcni wants an unvalued one.
Other graph analysis:
plot.tda_graph(),
tda_dmet(),
tda_g(),
tda_graph(),
tda_locate_line(),
tda_ptree(),
tda_ucl()
# a small directed graph: 1 and 2 both feed 3, which feeds 4, which # feeds 5 e <- data.frame(from = c(1, 1, 2, 2, 3, 4), to = c(2, 3, 3, 4, 4, 5), value = c(1, 2, 1, 3, 2, 1)) # undirected questions want an undirected graph g <- tda_graph(e, directed = FALSE) tda_g_components(g)$table tda_g_cliques(g)$table tda_g_mst(g)$table tda_g_cycles(g)$table tda_g_cutpoints(g)$table tda_g_compact(g)$table tda_g_spantrees(g)$table tda_g_spanning(g)$table tda_g_independent(g)$table tda_g_centred(g)$table # directed ones want a directed graph d <- tda_graph(e, directed = TRUE) tda_g_toposort(d)$table tda_g_reachable(d)$table tda_g_transitive(d)$table tda_g_nodes(d)$table tda_g_links(d)$table tda_g_paths(d)$table tda_g_flow(d)$table tda_g_flowcontrol(d)$table tda_g_backward(d)$table tda_g_degrees(d)[, c("node", "in_degree", "out_degree")] tda_g_edges(d)$table # the raw edge dump (gdp) tda_g_random(d)$table # a fresh random graph, ignores e's edges tda_g_dot(d)$text # Graphviz source, not a table -- see tda_g() tda_g_shortest(g)$table # all-pairs shortest paths # a denser graph, with an actual triangle and edges valued in [0, 1] -- # what gcliques (a real clique, not just a connected pair) and gio (an # ownership fraction) both need to find something on this small example e2 <- data.frame(from = c(1, 2, 3, 1, 4), to = c(2, 3, 1, 4, 5), value = c(0.3, 0.5, 0.8, 0.6, 0.9)) g2 <- tda_graph(e2, directed = FALSE) d2 <- tda_graph(e2, directed = TRUE) tda_g_gcliques(g2)$table tda_g_ownership(d2)$table # aggregate collapses named nodes into new ones -- rcn=, TDA's # recode syntax, is required; without it there is nothing to do tda_g_aggregate(d, rcn = "1[1,2],2[3,4,5]")$table # neighbourhoods wants an unvalued graph (gcni's restriction) e3 <- data.frame(from = c(1, 1, 2, 2, 3, 4), to = c(2, 3, 3, 4, 4, 5)) tda_g_neighbourhoods(tda_graph(e3, directed = FALSE))$table # this graph has no cycles (it is a DAG) and every edge already agrees # with itself in one direction, so these two are empty rather than # broken -- not every command has something to report tda_g_dcycles(d)$table tda_g_symmetric(d)$run$output[grepl("Nodes|symmetr", d$run$output)] tda_g_dblocks(d)$table # 0 compact blocks in this graph, also real tda_g_eigen(g) # small graphs like these often do not converge # anything without a named wrapper goes through tda_g() tda_g(d, "gdp")$table# a small directed graph: 1 and 2 both feed 3, which feeds 4, which # feeds 5 e <- data.frame(from = c(1, 1, 2, 2, 3, 4), to = c(2, 3, 3, 4, 4, 5), value = c(1, 2, 1, 3, 2, 1)) # undirected questions want an undirected graph g <- tda_graph(e, directed = FALSE) tda_g_components(g)$table tda_g_cliques(g)$table tda_g_mst(g)$table tda_g_cycles(g)$table tda_g_cutpoints(g)$table tda_g_compact(g)$table tda_g_spantrees(g)$table tda_g_spanning(g)$table tda_g_independent(g)$table tda_g_centred(g)$table # directed ones want a directed graph d <- tda_graph(e, directed = TRUE) tda_g_toposort(d)$table tda_g_reachable(d)$table tda_g_transitive(d)$table tda_g_nodes(d)$table tda_g_links(d)$table tda_g_paths(d)$table tda_g_flow(d)$table tda_g_flowcontrol(d)$table tda_g_backward(d)$table tda_g_degrees(d)[, c("node", "in_degree", "out_degree")] tda_g_edges(d)$table # the raw edge dump (gdp) tda_g_random(d)$table # a fresh random graph, ignores e's edges tda_g_dot(d)$text # Graphviz source, not a table -- see tda_g() tda_g_shortest(g)$table # all-pairs shortest paths # a denser graph, with an actual triangle and edges valued in [0, 1] -- # what gcliques (a real clique, not just a connected pair) and gio (an # ownership fraction) both need to find something on this small example e2 <- data.frame(from = c(1, 2, 3, 1, 4), to = c(2, 3, 1, 4, 5), value = c(0.3, 0.5, 0.8, 0.6, 0.9)) g2 <- tda_graph(e2, directed = FALSE) d2 <- tda_graph(e2, directed = TRUE) tda_g_gcliques(g2)$table tda_g_ownership(d2)$table # aggregate collapses named nodes into new ones -- rcn=, TDA's # recode syntax, is required; without it there is nothing to do tda_g_aggregate(d, rcn = "1[1,2],2[3,4,5]")$table # neighbourhoods wants an unvalued graph (gcni's restriction) e3 <- data.frame(from = c(1, 1, 2, 2, 3, 4), to = c(2, 3, 3, 4, 4, 5)) tda_g_neighbourhoods(tda_graph(e3, directed = FALSE))$table # this graph has no cycles (it is a DAG) and every edge already agrees # with itself in one direction, so these two are empty rather than # broken -- not every command has something to report tda_g_dcycles(d)$table tda_g_symmetric(d)$run$output[grepl("Nodes|symmetr", d$run$output)] tda_g_dblocks(d)$table # 0 compact blocks in this graph, also real tda_g_eigen(g) # small graphs like these often do not converge # anything without a named wrapper goes through tda_g() tda_g(d, "gdp")$table
TDA's gap on a cost matrix: the permutation that assigns each
row to a column at minimal total cost (Carpaneto and Toth's
algorithm), the manual's 7.3.1.1. The matrix goes to TDA as a full
matrix graph (gdd(opt=7)), so it need not be symmetric.
tda_gap(cost, ...)tda_gap(cost, ...)
cost |
a square numeric cost matrix. |
... |
passed to |
assignment, the permutation as a two-column matrix
(i, p(i)); permuted, the cost matrix with its rows permuted
accordingly; and output.
cost <- rbind(c(60, 0, 0, 76, 0, 0), c(0, 40, 18, 0, 60, 24), c(60, 16, 2, 4, 0, 40), c(0, 27, 18, 3, 55, 75), c(0, 40, 62, 16, 11, 53), c(28, 4, 10, 84, 0, 16)) tda_gap(cost)$assignmentcost <- rbind(c(60, 0, 0, 76, 0, 0), c(0, 40, 18, 0, 60, 24), c(60, 16, 2, 4, 0, 40), c(0, 27, 18, 3, 55, 75), c(0, 40, 62, 16, 11, 53), c(28, 4, 10, 84, 0, 16)) tda_gap(cost)$assignment
TDA's gap (CACM algorithm 548) on two integer-valued
graphs, given as matrices the way tda_gqap takes
them.
tda_gap_permute(g1, g2, ...)tda_gap_permute(g1, g2, ...)
g1, g2
|
symmetric integer matrices of equal dimension. |
... |
passed to |
permuted, the permuted matrix, and output.
f <- rbind(c(0, 3, 1), c(3, 0, 2), c(1, 2, 0)) d <- rbind(c(0, 1, 4), c(1, 0, 2), c(4, 2, 0)) r <- tda_gap_permute(f, d) r$permutedf <- rbind(c(0, 3, 1), c(3, 0, 2), c(1, 2, 0)) d <- rbind(c(0, 1, 4), c(1, 0, 2), c(4, 2, 0)) r <- tda_gap_permute(f, d) r$permuted
TDA's gde: builds an undirected graph from a data matrix
where node numbers each unit and id identifies the
objects they share; units sharing an id become adjacent.
tda_gde(node, id, output = c("edges", "matrix"), loops = TRUE, ...)tda_gde(node, id, output = c("edges", "matrix"), loops = TRUE, ...)
node, id
|
integer vectors of equal length. |
output |
"edges" for an edge list, "matrix" for the square adjacency matrix. |
loops |
FALSE removes loops. |
... |
passed to |
the values TDA wrote, as a matrix (one row per line of the output file), from the export channel.
# three persons (node) and the organisations they belong to (id): # person 1 in 10 and 20, person 2 in 20 and 30, person 3 in 30. # Sharing an organisation makes two persons adjacent: 1-2 and 2-3. tda_gde(node = c(1, 1, 2, 2, 3), id = c(10, 20, 20, 30, 30))# three persons (node) and the organisations they belong to (id): # person 1 in 10 and 20, person 2 in 20 and 30, person 3 in 30. # Sharing an organisation makes two persons adjacent: 1-2 and 2-3. tda_gde(node = c(1, 1, 2, 2, 3), id = c(10, 20, 20, 30, 30))
TDA's gdf: the marginal (or, with method, joint)
distribution or survivor function for possibly right-censored data,
via a Kaplan-Meier-style calculation – the same underlying censoring
machinery as tda_lsreg1, but estimating the distribution
function directly rather than a conditional expectation.
tda_gdf( formula, data, censor = NULL, id = NULL, dimension = NULL, what = c("distribution", "survivor", "expected_values"), method = c("marginal", "joint1", "joint2"), offset = NULL, n_boxes = NULL, delta = NULL, control = NULL, options = list(), dir = tempfile("tda"), ... )tda_gdf( formula, data, censor = NULL, id = NULL, dimension = NULL, what = c("distribution", "survivor", "expected_values"), method = c("marginal", "joint1", "joint2"), offset = NULL, n_boxes = NULL, delta = NULL, control = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a one-sided formula naming the (possibly censored)
variable, e.g. |
data |
a data frame. |
censor |
the censoring indicator, as a name or a vector, or
|
id |
for multi-dimensional data, the name of the column
identifying which unit each row belongs to (TDA's |
dimension |
with |
what |
the distribution function (default), the survivor
function, or the expected value of each case's observation
under the fitted distribution – |
method |
|
offset, n_boxes
|
for |
delta |
for |
control |
for |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object carrying a table of values and the
distribution (or survivor) function at each.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_freg(),
tda_l1reg(),
tda_lsreg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
set.seed(1) n <- 20 d <- data.frame(y = round(rexp(n, 0.2), 1), cen = rbinom(n, 1, 0.3)) fit <- tda_gdf(~ y, d, censor = "cen") fit$table # expected values: one row per case, not per distinct value fit2 <- tda_gdf(~ y, d, censor = "cen", what = "expected_values") head(fit2$table)set.seed(1) n <- 20 d <- data.frame(y = round(rexp(n, 0.2), 1), cen = rbinom(n, 1, 0.3)) fit <- tda_gdf(~ y, d, censor = "cen") fit$table # expected values: one row per case, not per distinct value fit2 <- tda_gdf(~ y, d, censor = "cen", what = "expected_values") head(fit2$table)
TDA's gdu: graph 1 is loaded from edges1 (with the
perm option of gdd), then the union with the edge
list edges2 is written to the output file.
tda_gdu(edges1, edges2, missing_value = -1, ...)tda_gdu(edges1, edges2, missing_value = -1, ...)
edges1, edges2
|
data frames: from, to, value. |
missing_value |
substitute written for missing values. |
... |
passed to |
the output file's lines.
e1 <- data.frame(i = c(1, 2), j = c(2, 3), v = c(1, 1)) e2 <- data.frame(i = c(1, 3), j = c(3, 1), v = c(2, 2)) tda_gdu(e1, e2) # value1/value2 side by side, -1 where absente1 <- data.frame(i = c(1, 2), j = c(2, 3), v = c(1, 1)) e2 <- data.frame(i = c(1, 3), j = c(3, 1), v = c(2, 2)) tda_gdu(e1, e2) # value1/value2 side by side, -1 where absent
TDA's gfcf on a directed graph loaded from an edge list.
tda_gfcf(edges, threshold = 0.5, variant = 1, ...)tda_gfcf(edges, threshold = 0.5, variant = 1, ...)
edges |
data frame: from, to. |
threshold |
control threshold, default 0.5. |
variant |
1 or 2 (the two forms the command documents). |
... |
passed to |
one row per node: the node, how many nodes it controls,
and the controlled nodes as a comma-joined string; the pair table
TDA writes (node, controlled node, path length L, share S, M, R –
the manual's Box 2 of 7.6.1.1) is the "pairs" attribute.
# 1 -> 2 -> 4 and 1 -> 3 -> 4: node 1 controls everything downstream, # 2 and 3 control node 4 only, node 4 controls nothing fc <- tda_gfcf(data.frame(i = c(1, 1, 2, 3), j = c(2, 3, 4, 4))) fc attr(fc, "pairs") # per pair: path length and the flow shares# 1 -> 2 -> 4 and 1 -> 3 -> 4: node 1 controls everything downstream, # 2 and 3 control node 4 only, node 4 controls nothing fc <- tda_gfcf(data.frame(i = c(1, 1, 2, 3), j = c(2, 3, 4, 4))) fc attr(fc, "pairs") # per pair: path length and the flow shares
TDA's ghd: the rows of x are (assumed unique)
patterns; the command derives the dominance order's Hasse diagram.
tda_ghd(x, ...)tda_ghd(x, ...)
x |
matrix or data frame of patterns. |
... |
passed to |
the edge list lines of the diagram.
# five patterns over two criteria; a row dominates another when it # is at least as large in both. The Hasse diagram keeps only the # covering relations: (0,0) < (1,0), (0,1) < (1,1) < (2,1) tda_ghd(rbind(c(0, 0), c(1, 0), c(0, 1), c(1, 1), c(2, 1)))# five patterns over two criteria; a row dominates another when it # is at least as large in both. The Hasse diagram keeps only the # covering relations: (0,0) < (1,0), (0,1) < (1,1) < (2,1) tda_ghd(rbind(c(0, 0), c(1, 0), c(0, 1), c(1, 1), c(2, 1)))
TDA's gpro on a proximity matrix given as an undirected
valued graph.
tda_gpro(d, max_iterations = 50, ...)tda_gpro(d, max_iterations = 50, ...)
d |
symmetric proximity matrix. |
max_iterations |
iteration cap. |
... |
passed to |
projection, the projected coordinates, and
output.
r <- tda_gpro(as.matrix(dist(cbind(c(0, 0, 3, 3), c(0, 2, 0, 2))))) r$projectionr <- tda_gpro(as.matrix(dist(cbind(c(0, 0, 3, 3), c(0, 2, 0, 2))))) r$projection
TDA's gqap: given a flow graph and a distance graph (both
undirected, integer-valued), search for the assignment minimizing
total cost, with the GRASP heuristic of CACM algorithm 754.
tda_gqap(flow, dist, max_iterations = 100, ...)tda_gqap(flow, dist, max_iterations = 100, ...)
flow, dist
|
symmetric integer matrices of equal dimension. |
max_iterations |
iteration cap. |
... |
passed to |
with direct exports enabled, a list with cost,
assignment and output; otherwise the printed
output lines.
f <- rbind(c(0, 3, 1), c(3, 0, 2), c(1, 2, 0)) d <- rbind(c(0, 1, 4), c(1, 0, 2), c(4, 2, 0)) tda_gqap(f, d)f <- rbind(c(0, 3, 1), c(3, 0, 2), c(1, 2, 0)) d <- rbind(c(0, 1, 4), c(1, 0, 2), c(4, 2, 0)) tda_gqap(f, d)
A graph for TDA's graph commands
tda_graph( edges, directed = TRUE, form = c("edges", "dissimilarity"), options = list() )tda_graph( edges, directed = TRUE, form = c("edges", "dissimilarity"), options = list() )
edges |
an edge list – from, to, and one value, or two values when
the graph carries a different one in each direction, as the shipped
|
directed |
whether the graph is directed. |
form |
how TDA is to read it: |
options |
a named list of further |
A tda_graph.
Other graph analysis:
plot.tda_graph(),
tda_dmet(),
tda_g(),
tda_g_analyses,
tda_locate_line(),
tda_ptree(),
tda_ucl()
e <- data.frame(from = c(1, 1, 2, 3), to = c(2, 3, 4, 4), value = 1) # gcon works on an undirected graph only, so `directed = FALSE` tda_g_components(tda_graph(e, directed = FALSE))e <- data.frame(from = c(1, 1, 2, 3), to = c(2, 3, 4, 4), value = 1) # gcon works on an undirected graph only, so `directed = FALSE` tda_g_components(tda_graph(e, directed = FALSE))
TDA's gtopo: reads a raw GTOPO30 digital-elevation tile
(16-bit big-endian integers, row-major from the upper-left corner)
and extracts a PROFILE – one latitude across a longitude range,
or one longitude across a latitude range. A rectangular window is
not supported by the command (established from the source: the
one-value-plus-range shapes are the only accepted forms).
tda_gtopo(file, rows, cols, upper_left, pixel_size, lon, lat, ...)tda_gtopo(file, rows, cols, upper_left, pixel_size, lon, lat, ...)
file |
the raw DEM file. |
rows, cols
|
tile dimensions. |
upper_left |
c(x, y) of the upper-left corner. |
pixel_size |
c(dx, dy). |
lon, lat
|
the profile: one of them a single value, the other a c(from, to) range. |
... |
passed to |
the profile records (a numeric matrix under direct exports, the file's lines otherwise).
f <- tempfile(fileext = ".dem") # synthesize a tiny 3x4 tile con <- file(f, "wb") writeBin(as.integer(100 + 1:12), con, size = 2, endian = "big") close(con) tda_gtopo(f, rows = 3, cols = 4, upper_left = c(10, 50), pixel_size = c(0.5, 0.5), lat = 49.5, lon = c(10, 11.5))f <- tempfile(fileext = ".dem") # synthesize a tiny 3x4 tile con <- file(f, "wb") writeBin(as.integer(100 + 1:12), con, size = 2, endian = "big") close(con) tda_gtopo(f, rows = 3, cols = 4, upper_left = c(10, 50), pixel_size = c(0.5, 0.5), lat = 49.5, lon = c(10, 11.5))
tda_help looks a keyword up in tda.hlp, the manual that
ships with TDA – the same text the standalone program prints for
help=.... With no keyword it lists every topic.
tda_help(topic = "") tda_time() tda_memory()tda_help(topic = "") tda_time() tda_memory()
topic |
a keyword. TDA appends its wildcard, so a prefix is enough; an empty topic lists every keyword. |
tda_time and tda_memory report what TDA reports for its
time and mem commands.
The text TDA printed, invisibly; it is also printed.
Other TDA infrastructure:
tda_ccnt(),
tda_output(),
tda_read_table(),
tda_run(),
tda_write_data()
tda_help("rate") tda_time() tda_memory()tda_help("rate") tda_time() tda_memory()
The interval of all covariance (or correlation) values reachable when
each observation varies in its interval – the same estimand as
tda_ivariance, computed by TDA's icov and
icorr (added to this build; not in Rohwer's TDA). The formula
names two interval pairs: ~ iv(xlo, xhi) + iv(ylo, yhi).
tda_icov( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... ) tda_icorr( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... )tda_icov( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... ) tda_icorr( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
|
data |
a data frame with the four bound columns. |
max_boxes, max_iter, tol_width, tol_fd, tol_fe
|
search limits and
tolerances, as in |
options, dir, ...
|
as everywhere. |
Naming the same pair twice is legal but means something specific:
the two copies vary independently over the intervals, so
tda_icov(~ iv(a, b) + iv(a, b), d) is not the interval
variance (its lower end can be negative) and the self-correlation is
not fixed at 1. The functions warn when they see this. For the
variance of one interval variable use tda_ivar.
Covariance certifies at realistic sizes. Correlation certifies small
problems; beyond that the search stops at its limits, returns the
best values found, and warns – raise max_iter/max_boxes
or accept the honest inner values.
An object with $bounds.
# three observations, both variables interval-valued; small enough # that both searches certify instantly (verified against a dense # grid in the package tests) d <- data.frame(xl = c(1, 4, 6), xu = c(2, 5, 8), yl = c(3, 1, 6), yu = c(5, 2, 9)) tda_icov(~ iv(xl, xu) + iv(yl, yu), d, max_iter = 2e5, max_boxes = 1e5) tda_icorr(~ iv(xl, xu) + iv(yl, yu), d, max_iter = 2e5, max_boxes = 1e5) # a realistic size: covariance certifies, correlation warns honestly w <- tda_interval_wages() tda_icov(~ iv(school_lo, school_hi) + iv(wage_lo, wage_hi), w, max_iter = 2e5, max_boxes = 1e5)# three observations, both variables interval-valued; small enough # that both searches certify instantly (verified against a dense # grid in the package tests) d <- data.frame(xl = c(1, 4, 6), xu = c(2, 5, 8), yl = c(3, 1, 6), yu = c(5, 2, 9)) tda_icov(~ iv(xl, xu) + iv(yl, yu), d, max_iter = 2e5, max_boxes = 1e5) tda_icorr(~ iv(xl, xu) + iv(yl, yu), d, max_iter = 2e5, max_boxes = 1e5) # a realistic size: covariance certifies, correlation warns honestly w <- tda_interval_wages() tda_icov(~ iv(school_lo, school_hi) + iv(wage_lo, wage_hi), w, max_iter = 2e5, max_boxes = 1e5)
tda_idf: the distribution and density function of a continuous
interval-valued variable, as bounds at each partition point – an
interval variable does not pin down a single distribution, only a
range one is consistent with. tda_iddf is the same idea for a
discrete interval-valued variable (a finite set of possible values,
not a continuum), and, unlike idf, does take opt= for
a self-consistent distribution; idf takes only fmt=.
tda_idf( formula, data, self_consistent = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... ) tda_iddf( formula, data, self_consistent = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... )tda_idf( formula, data, self_consistent = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... ) tda_iddf( formula, data, self_consistent = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a one-sided formula naming one interval-valued variable,
|
data |
a data frame. |
self_consistent |
also compute the self-consistent distribution
( |
control |
convergence settings ( |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object carrying a table of partition points and the
distribution function's bounds and mean at each.
Other interval-valued data:
tda_bounds(),
tda_ilsreg(),
tda_imean(),
tda_imreg(),
tda_inpreg(),
tda_ivar1(),
tda_ivreg(),
tda_sddf()
set.seed(1) n <- 30 d <- data.frame(lo = round(rnorm(n, 5, 2), 1)) d$hi <- d$lo + round(runif(n, 0.5, 2), 1) fit <- tda_idf(~ iv(lo, hi), d) head(fit$table) # iddf: the discrete counterpart, with the self-consistent option idf # itself does not have fit2 <- tda_iddf(~ iv(lo, hi), d, self_consistent = TRUE) head(fit2$table)set.seed(1) n <- 30 d <- data.frame(lo = round(rnorm(n, 5, 2), 1)) d$hi <- d$lo + round(runif(n, 0.5, 2), 1) fit <- tda_idf(~ iv(lo, hi), d) head(fit$table) # iddf: the discrete counterpart, with the self-consistent option idf # itself does not have fit2 <- tda_iddf(~ iv(lo, hi), d, self_consistent = TRUE) head(fit2$table)
The response is interval-valued, the regressor a point value – unlike
tda_ivreg, where both sides are intervals. Both the slope
and the intercept come back as bounds; see tda_bounds.
tda_ilsreg( formula, data, yl, censor, options = list(), dir = tempfile("tda"), ... )tda_ilsreg( formula, data, yl, censor, options = list(), dir = tempfile("tda"), ... )
formula |
a formula using |
data |
a data frame. |
yl, censor
|
the response and censoring variables TDA requires, as names or vectors. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object of class tda_fit.
Other interval-valued data:
tda_bounds(),
tda_idf(),
tda_imean(),
tda_imreg(),
tda_inpreg(),
tda_ivar1(),
tda_ivreg(),
tda_sddf()
set.seed(2) d <- data.frame(x = round(rnorm(30), 2)) d$ylo <- 2 + 0.5 * d$x + rnorm(30, sd = 0.2) d$yhi <- d$ylo + round(runif(30, 0.3, 1), 2) tda_ilsreg(iv(ylo, yhi) ~ x, d)set.seed(2) d <- data.frame(x = round(rnorm(30), 2)) d$ylo <- 2 + 0.5 * d$x + rnorm(30, sd = 0.2) d$yhi <- d$ylo + round(runif(30, 0.3, 1), 2) tda_ilsreg(iv(ylo, yhi) ~ x, d)
The interval-valued counterparts of the ordinary summaries: a mean, a
variance and a Gini coefficient computed from (lower, upper) pairs
rather than from points. Each is reported as bounds, because an interval
variable does not have a single value for these either.
tda_imean(formula, data, options = list(), dir = tempfile("tda"), ...) tda_ivariance( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... ) tda_igini( formula, data, x = NULL, options = list(), dir = tempfile("tda"), ... )tda_imean(formula, data, options = list(), dir = tempfile("tda"), ...) tda_ivariance( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... ) tda_igini( formula, data, x = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a one-sided formula naming one interval-valued variable,
|
data |
a data frame. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
max_boxes, max_iter, tol_width, tol_fd, tol_fe
|
for
|
x |
for |
An object carrying the bounds in $bounds, and the run.
Other interval-valued data:
tda_bounds(),
tda_idf(),
tda_ilsreg(),
tda_imreg(),
tda_inpreg(),
tda_ivar1(),
tda_ivreg(),
tda_sddf()
d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_imean(~ iv(lo, hi), d) tda_ivariance(~ iv(lo, hi), d) tda_igini(~ iv(lo, hi), d)d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_imean(~ iv(lo, hi), d) tda_ivariance(~ iv(lo, hi), d) tda_igini(~ iv(lo, hi), d)
imreg: for each interval formed by the induced partition of the
regressor's bounds, the mean of the response bounds over the cases
covering it.
tda_imreg(formula, data, options = list(), dir = tempfile("tda"), ...)tda_imreg(formula, data, options = list(), dir = tempfile("tda"), ...)
formula |
a formula using |
data |
a data frame. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object carrying table, one row per partition boundary.
Other interval-valued data:
tda_bounds(),
tda_idf(),
tda_ilsreg(),
tda_imean(),
tda_inpreg(),
tda_ivar1(),
tda_ivreg(),
tda_sddf()
set.seed(3) d <- data.frame(xlo = round(rnorm(30), 2)) d$xhi <- d$xlo + round(runif(30, 0.3, 1), 2) d$ylo <- 2 + 0.5 * d$xlo + rnorm(30, sd = 0.2) d$yhi <- d$ylo + round(runif(30, 0.3, 1), 2) head(tda_imreg(iv(ylo, yhi) ~ iv(xlo, xhi), d)$table)set.seed(3) d <- data.frame(xlo = round(rnorm(30), 2)) d$xhi <- d$xlo + round(runif(30, 0.3, 1), 2) d$ylo <- 2 + 0.5 * d$xlo + rnorm(30, sd = 0.2) d$yhi <- d$ylo + round(runif(30, 0.3, 1), 2) head(tda_imreg(iv(ylo, yhi) ~ iv(xlo, xhi), d)$table)
How far two integer-valued variables are from independent: for each
subset of y's values, the largest gap between the distribution
of x within that subset and the overall distribution of
x – TDA's indep. A delta of 0 means x is
distributed identically inside and outside the subset.
tda_independence( x, y, data = NULL, partition = NULL, dir = tempfile("tda"), ... )tda_independence( x, y, data = NULL, partition = NULL, dir = tempfile("tda"), ... )
x, y
|
integer-valued vectors of equal length, or column names in
|
data |
optional data frame supplying |
partition |
optional increasing integers: the upper ends of
consecutive |
dir |
working directory. |
... |
passed to |
By default every distinct value of y is its subset. With
partition, y's range is cut into consecutive subsets:
each number is the last y value of one subset (TDA's
y=). Values must be integers; TDA works on the integer grid
from the smallest to the largest observed value.
A data frame with one row per subset: subset (its
number), values (the y values it contains, as a
comma-separated string), and delta.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_freq(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_segr(),
tda_subm()
d <- data.frame(x = c(1, 2, 3, 4, 1, 2, 3, 4), y = c(1, 1, 1, 1, 2, 2, 2, 2)) tda_independence("x", "y", data = d)d <- data.frame(x = c(1, 2, 3, 4, 1, 2, 3, 4), y = c(1, 1, 1, 1, 2, 2, 2, 2)) tda_independence("x", "y", data = d)
TDA's ineq: for each variable, the (weighted) minimum, maximum,
mean and standard deviation, the coefficient of variation (standard
deviation over mean), and the Gini coefficient – the mean absolute
difference between every pair of values, relative to twice the mean,
the standard concentration measure for incomes and similar
quantities: 0 when every value is equal, approaching 1 as the total
concentrates in one case.
tda_ineq(..., options = list(), dir = tempfile("tda"))tda_ineq(..., options = list(), dir = tempfile("tda"))
... |
a data frame, a matrix, or vectors. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
ineq treats every negative value as missing and drops
it – the manual (section 6.4.2) is explicit that only nonnegative
values enter, so cases in the result can be smaller than the
number of rows given, and a variable that legitimately runs negative
is not summarised correctly by this command. Case weights given via
a prior cwt command (options, or the weights
arguments of the model functions, set one) weight every measure.
An object carrying table: one row per variable, with
cases (nonnegative values only), minimum,
maximum, mean, sd, vcoeff and
gini.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_segr(),
tda_subm()
set.seed(29) d <- data.frame(income = round(rlnorm(80, meanlog = 8, sdlog = 0.6))) tda_ineq(d)$tableset.seed(29) d <- data.frame(income = round(rlnorm(80, meanlog = 8, sdlog = 0.6))) tda_ineq(d)$table
A kernel-smoothed fit evaluated at points you choose, both sides interval-valued.
tda_inpreg(formula, data, x, options = list(), dir = tempfile("tda"), ...)tda_inpreg(formula, data, x, options = list(), dir = tempfile("tda"), ...)
formula |
a formula using |
data |
a data frame. |
x |
the points at which to evaluate the fit. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object carrying table, one row per evaluation point.
Other interval-valued data:
tda_bounds(),
tda_idf(),
tda_ilsreg(),
tda_imean(),
tda_imreg(),
tda_ivar1(),
tda_ivreg(),
tda_sddf()
set.seed(4) d <- data.frame(xlo = round(rnorm(20), 2)) d$xhi <- d$xlo + round(runif(20, 0.3, 1), 2) d$ylo <- 2 + 0.5 * d$xlo + rnorm(20, sd = 0.2) d$yhi <- d$ylo + round(runif(20, 0.3, 1), 2) tda_inpreg(iv(ylo, yhi) ~ iv(xlo, xhi), d, x = c(-1, 0, 1))$tableset.seed(4) d <- data.frame(xlo = round(rnorm(20), 2)) d$xhi <- d$xlo + round(runif(20, 0.3, 1), 2) d$ylo <- 2 + 0.5 * d$xlo + rnorm(20, sd = 0.2) d$yhi <- d$ylo + round(runif(20, 0.3, 1), 2) tda_inpreg(iv(ylo, yhi) ~ iv(xlo, xhi), d, x = c(-1, 0, 1))$table
These take a function written in TDA's expression language, with x
as the formal argument, and evaluate it inside TDA. They are not given an R
function, because the expression is evaluated by TDA's interpreter.
tda_integrate(expr, from, to, options = list(), dir = tempfile("tda")) tda_range( expr, start = NULL, use_derivatives = FALSE, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda") ) tda_evalf(expr, options = list(), derivatives = 0, dir = tempfile("tda")) tda_minimize(expr, options = list(), dir = tempfile("tda")) tda_gmin( expr, start = NULL, use_derivatives = FALSE, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda") )tda_integrate(expr, from, to, options = list(), dir = tempfile("tda")) tda_range( expr, start = NULL, use_derivatives = FALSE, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda") ) tda_evalf(expr, options = list(), derivatives = 0, dir = tempfile("tda")) tda_minimize(expr, options = list(), dir = tempfile("tda")) tda_gmin( expr, start = NULL, use_derivatives = FALSE, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda") )
expr |
a single string, e.g. |
from, to
|
the limits of integration. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
start |
for |
use_derivatives |
for |
max_boxes, max_iter, tol_width, tol_fd, tol_fe
|
for |
derivatives |
for |
tda_evalf does not report a value at all: xf is a plotting
command, drawing the function over the range options$x names
(default 1 to 10) to a file called xplot.ps in the run's directory
– read it with tda_read_ps(x$run, which = "xplot.ps"), the same
way as any other TDA plot.
An object with the numeric result in value
(tda_integrate, tda_minimize, tda_gmin), the two
bounds in range (tda_range), or nothing structured
(tda_evalf, see above); tda_minimize/tda_gmin
also carry estimates, the parameter values at the minimum, and
the run is always in run.
Other smoothing:
tda_interp(),
tda_isotonic(),
tda_mat(),
tda_sma(),
tda_smd(),
tda_spl()
tda_integrate("x*x", 0, 1)$value # 1/3 tda_range("sin(x)")$range # [-1, 1] over its default domain tda_minimize("(x - 2)^2", options = list(xp = "0"))$estimates # gmin: a box-search-based *global* minimum, not tda_minimize's # local search -- its start=/tolerances, not tda_control(). Its # interval arithmetic does not accept ^, unlike tda_minimize's # expression -- (x-2)*(x-2), not (x-2)^2 tda_gmin("(x-2)*(x-2)", start = list(c(2, 0, 4)))$value # evalf: the function value at a point, 1.1342 tda_evalf("sin(x) + x^2", options = list(x = 0.7))$valuetda_integrate("x*x", 0, 1)$value # 1/3 tda_range("sin(x)")$range # [-1, 1] over its default domain tda_minimize("(x - 2)^2", options = list(xp = "0"))$estimates # gmin: a box-search-based *global* minimum, not tda_minimize's # local search -- its start=/tolerances, not tda_control(). Its # interval arithmetic does not accept ^, unlike tda_minimize's # expression -- (x-2)*(x-2), not (x-2)^2 tda_gmin("(x-2)*(x-2)", start = list(c(2, 0, 4)))$value # evalf: the function value at a point, 1.1342 tda_evalf("sin(x) + x^2", options = list(x = 0.7))$value
Interpolate a surface over a grid
tda_interp(x, y, z, rx, ry, options = list(), dir = tempfile("tda"))tda_interp(x, y, z, rx, ry, options = list(), dir = tempfile("tda"))
x, y, z
|
the surface: a point cloud in three variables. |
rx, ry
|
the grids to interpolate over. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
An object carrying a table: one row per grid point,
x, y and the interpolated z.
Other smoothing:
tda_integrate(),
tda_isotonic(),
tda_mat(),
tda_sma(),
tda_smd(),
tda_spl()
# a plane z = x + 2y, evaluated back on its own grid g <- expand.grid(x = 1:5, y = 1:5) g$z <- g$x + 2 * g$y head(tda_interp(g$x, g$y, g$z, rx = 1:5, ry = 1:5)$table)# a plane z = x + 2y, evaluated back on its own grid g <- expand.grid(x = 1:5, y = 1:5) g$z <- g$x + 2 * g$y head(tda_interp(g$x, g$y, g$z, rx = 1:5, ry = 1:5)$table)
A small, reproducible dataset built for trying the whole interval
family on one realistic shape: n = 40 people, schooling asked and
answered in whole years (a point value), wages reported in brackets
that widen with income, with a top-coded highest bracket – the
classic survey mix of exact and interval-valued variables. Because
the regressor is exact, tda_ivreg's exact method certifies
sharp slope bounds instantly here; widen the schooling values into
intervals yourself to watch certification get hard.
tda_interval_wages()tda_interval_wages()
The generating truth is log(wage) = 0.8 + 0.11 school + e,
which produces a wage-level slope around 1.6 over this range; any
interval method's answer should be judged against the data's
coarseness, not against that number.
Works across the family: tda_imean,
tda_ivariance (with $sd),
tda_icov, tda_icorr (which
honestly warns that it cannot certify at this size),
tda_ivreg and tda_ilsreg.
A data frame with columns wage_lo, wage_hi,
school_lo, school_hi.
d <- tda_interval_wages() tda_imean(~ iv(wage_lo, wage_hi), d) tda_ivreg(iv(wage_lo, wage_hi) ~ iv(school_lo, school_hi), d, method = "exact")d <- tda_interval_wages() tda_imean(~ iv(wage_lo, wage_hi), d) tda_ivreg(iv(wage_lo, wage_hi) ~ iv(school_lo, school_hi), d, method = "exact")
The square root of tda_ivariance's bounds – valid
because the square root is monotone. Its own function because a
variance function printing standard deviations surprised people,
reasonably.
tda_isd(formula, data, ...)tda_isd(formula, data, ...)
formula, data, ...
|
as in |
A named vector, the lower and upper standard deviation.
d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_isd(~ iv(lo, hi), d)d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_isd(~ iv(lo, hi), d)
The non-decreasing sequence closest (least squares) to y –
TDA's mmp, and with tie groups its mmp1/mmp2.
Without groups this is plain pool-adjacent-violators and
agrees with stats::isoreg exactly.
tda_isotonic( y, groups = NULL, ties = c("primary", "secondary"), dir = tempfile("tda"), ... )tda_isotonic( y, groups = NULL, ties = c("primary", "secondary"), dir = tempfile("tda"), ... )
y |
a numeric vector, in the order to be respected. |
groups |
optional vector of the same length marking tie groups by consecutive runs of equal values. |
ties |
how tie groups are treated: |
dir |
working directory. |
... |
passed to |
groups marks observations whose order among themselves is not
meaningful (ties in the ordering variable). Consecutive equal values
form one group – the grouping follows runs, exactly as TDA reads its
tie matrix, so c(1, 1, 2) is two groups but c(1, 2, 1)
is three. How a group is treated is ties:
"primary" (Kruskal's primary approach, mmp1) lets the
fitted values untie freely – the group's values are sorted, fitted,
and each observation receives its rank slot's value, so the result is
monotone only up to reordering within groups; "secondary"
(mmp2) forces one common value per group – the group mean is
fitted and broadcast back.
The fitted values, a numeric vector like y.
Other smoothing:
tda_integrate(),
tda_interp(),
tda_mat(),
tda_sma(),
tda_smd(),
tda_spl()
tda_isotonic(c(5, 3, 4, 6, 2, 7)) # rows 1-2 tied, rows 4-6 tied: tda_isotonic(c(5, 3, 4, 6, 2, 7), groups = c(1, 1, 2, 3, 3, 3), ties = "secondary")tda_isotonic(c(5, 3, 4, 6, 2, 7)) # rows 1-2 tied, rows 4-6 tied: tda_isotonic(c(5, 3, 4, 6, 2, 7), groups = c(1, 1, 2, 3, 3, 3), ties = "secondary")
Identical to tda_ivariance: TDA's ivar
branch-and-bound with tunable limits. This is the command-style
name; tda_ivar1 wraps the newer ivar1
algorithm, and all three compute the same variance bounds.
tda_ivar( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... )tda_ivar( formula, data, max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_fd = NULL, tol_fe = NULL, options = list(), dir = tempfile("tda"), ... )
formula, data, max_boxes, max_iter, tol_width, tol_fd, tol_fe, options, dir, ...
|
exactly as in |
See tda_ivariance.
d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_ivar(~ iv(lo, hi), d)d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_ivar(~ iv(lo, hi), d)
Wraps TDA's ivar1, the newer, options-less variance
algorithm. tda_ivar wraps the older tunable ivar
branch-and-bound; both compute the same variance bounds, and the
names now follow the commands.
tda_ivar1(formula, data, options = list(), dir = tempfile("tda"), ...)tda_ivar1(formula, data, options = list(), dir = tempfile("tda"), ...)
formula |
a one-sided formula naming one interval-valued variable,
|
data |
a data frame. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object of class tda_fit; see tda_bounds
for the variance bounds.
Other interval-valued data:
tda_bounds(),
tda_idf(),
tda_ilsreg(),
tda_imean(),
tda_imreg(),
tda_inpreg(),
tda_ivreg(),
tda_sddf()
d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_ivar1(~ iv(lo, hi), d)d <- data.frame(lo = c(1, 3, 5, 9), hi = c(2, 4, 8, 12)) tda_ivar1(~ iv(lo, hi), d)
tda_ivreg, tda_ivreg1 and tda_ivreg2 are TDA's three
variants of interval regression – both response and regressor are
interval-valued – and tda_ivls solves the same kind of problem as
a system of linear interval equations. All four return bounds on beta
rather than a point estimate, so coef() would be misleading; use
tda_bounds.
tda_ivreg( formula, data, method = c("two_step", "heuristic", "exact"), max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_beta = NULL, options = list(), dir = tempfile("tda"), ... ) tda_ivreg1( formula, data, search_box = list(alpha = c(-10, 10), alpha_radius = c(0, 5), beta = c(-10, 10), beta_radius = c(0, 5)), max_boxes = 4000, max_iter = 4000, tol_width = NULL, tol_beta = NULL, tol_min = 0.001, options = list(), dir = tempfile("tda"), ... ) tda_ivreg2( formula, data, method = c("direct", "search", "minimizer", "contour"), options = list(), dir = tempfile("tda"), ... ) tda_ivls(formula, data, options = list(), dir = tempfile("tda"), ...)tda_ivreg( formula, data, method = c("two_step", "heuristic", "exact"), max_boxes = NULL, max_iter = NULL, tol_width = NULL, tol_beta = NULL, options = list(), dir = tempfile("tda"), ... ) tda_ivreg1( formula, data, search_box = list(alpha = c(-10, 10), alpha_radius = c(0, 5), beta = c(-10, 10), beta_radius = c(0, 5)), max_boxes = 4000, max_iter = 4000, tol_width = NULL, tol_beta = NULL, tol_min = 0.001, options = list(), dir = tempfile("tda"), ... ) tda_ivreg2( formula, data, method = c("direct", "search", "minimizer", "contour"), options = list(), dir = tempfile("tda"), ... ) tda_ivls(formula, data, options = list(), dir = tempfile("tda"), ...)
formula |
a formula using |
data |
a data frame. |
method |
for |
max_boxes, max_iter, tol_width, tol_beta
|
for |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
search_box |
for |
tol_min |
for |
Interval-valued data is a lower and an upper bound per case, a different
thing from interval censoring, and has no equivalent in base R or
in survival. iv(lo, hi) marks such a variable in a formula,
the way Surv() marks an episode.
ivreg1 and ivreg2 are global-optimization (branch-and-bound)
searches, and each reports its bounds in its own format – ivreg2
a centre and a half-width (“Beta (center-radius): C R”, read as
[C - R, C + R]), and ivls a bare “Final bounds”
with no label at all.
ivreg1 needs a word of its own. As shipped, the command's
search domain is hard-coded – alpha in
[1, 2.5], beta in [0, 0.1], evidently the dataset it
was being developed against – so for almost any other data the
answer is simply not inside the searched box and TDA reports
“0 finally accepted boxes”. The command was left mid-study,
not broken: on data whose solution lies inside the box, the search
certifies cleanly. tda_ivreg1 therefore passes the domain in
through the package's sbox= option (a guarded addition to
the C; the standalone program is unchanged), always requests the
prot= protocol file, and reads the accepted boxes back:
boxes holds every box the protocol reports, parameters
the hull of the near-optimal ones over (alpha, alpha radius, beta,
beta radius), and beta/alpha – what
tda_bounds returns – the centre rows of that hull.
Certification follows TDA's rule: a box counts when its inclusion
lower bound is within tol_min of the best value found. The
shipped default of 1e-10 for that tolerance is unreachable
(interval arithmetic over-estimates a box's range), which is the
second reason the command always seemed to fail; tol_min
defaults to 1e-3 here instead.
An object of class tda_fit.
Other interval-valued data:
tda_bounds(),
tda_idf(),
tda_ilsreg(),
tda_imean(),
tda_imreg(),
tda_inpreg(),
tda_ivar1(),
tda_sddf()
set.seed(1) d <- data.frame(xlo = 1:20) d$xhi <- d$xlo + 2 d$ylo <- 2 + 0.5 * d$xlo + rnorm(20) d$yhi <- d$ylo + 1.5 tda_ivreg(iv(ylo, yhi) ~ iv(xlo, xhi), d) # ivreg2: converges readily even where ivreg1 often does not d2 <- data.frame(xlo = c(1, 2, 3, 4)) d2$xhi <- d2$xlo + 1 d2$ylo <- 2 + 0.5 * d2$xlo d2$yhi <- d2$ylo + 1 tda_ivreg2(iv(ylo, yhi) ~ iv(xlo, xhi), d2) # ivls: the same interval-equations idea, its bound format tda_ivls(iv(ylo, yhi) ~ iv(xlo, xhi), d2)set.seed(1) d <- data.frame(xlo = 1:20) d$xhi <- d$xlo + 2 d$ylo <- 2 + 0.5 * d$xlo + rnorm(20) d$yhi <- d$ylo + 1.5 tda_ivreg(iv(ylo, yhi) ~ iv(xlo, xhi), d) # ivreg2: converges readily even where ivreg1 often does not d2 <- data.frame(xlo = c(1, 2, 3, 4)) d2$xhi <- d2$xlo + 1 d2$ylo <- 2 + 0.5 * d2$xlo d2$yhi <- d2$ylo + 1 tda_ivreg2(iv(ylo, yhi) ~ iv(xlo, xhi), d2) # ivls: the same interval-equations idea, its bound format tda_ivls(iv(ylo, yhi) ~ iv(xlo, xhi), d2)
L1-norm regression, which fits the conditional median rather than the mean
and is therefore robust to outliers in the response.
quantreg::rq(tau = 0.5) is the R analogue.
tda_l1reg( formula, data, intercept = NULL, options = list(), residuals = FALSE, dir = tempfile("tda"), ... )tda_l1reg( formula, data, intercept = NULL, options = list(), residuals = FALSE, dir = tempfile("tda"), ... )
formula |
a two-sided formula. |
data |
a data frame. |
intercept |
whether to include an intercept. Defaults to whatever
the formula itself says ( |
options |
a named list of further TDA options, passed through. |
residuals |
also return each case's residual, as a |
dir |
working directory. |
... |
passed to |
An object of class tda_fit.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_freg(),
tda_gdf(),
tda_lsreg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
set.seed(22) d <- data.frame(x = round(rnorm(50), 3)) d$y <- round(3 - 0.8 * d$x + rnorm(50, sd = 0.4), 3) # three outliers: l1reg, fitting the median, should barely notice them d$y[c(2, 10, 30)] <- d$y[c(2, 10, 30)] + c(15, -12, 20) coef(tda_l1reg(y ~ x, d)) coef(lm(y ~ x, d)) # pulled toward the outliers fit <- tda_l1reg(y ~ x, d, residuals = TRUE) head(fitted(fit)) # equivalent to predict(fit); no newdata needed head(residuals(fit))set.seed(22) d <- data.frame(x = round(rnorm(50), 3)) d$y <- round(3 - 0.8 * d$x + rnorm(50, sd = 0.4), 3) # three outliers: l1reg, fitting the median, should barely notice them d$y[c(2, 10, 30)] <- d$y[c(2, 10, 30)] + c(15, -12, 20) coef(tda_l1reg(y ~ x, d)) coef(lm(y ~ x, d)) # pulled toward the outliers fit <- tda_l1reg(y ~ x, d, residuals = TRUE) head(fitted(fit)) # equivalent to predict(fit); no newdata needed head(residuals(fit))
Place k new (variable) points among m existing (fixed) points on a
line so that the weighted interaction costs are minimal – TDA's
gloc. Each variable point ends up at one of the fixed points;
only the order of the fixed points on the line matters, not their
spacing (verified against exhaustive search in the test suite).
tda_locate_line( fixed_weights, variable_weights = NULL, options = list(), dir = tempfile("tda"), ... )tda_locate_line( fixed_weights, variable_weights = NULL, options = list(), dir = tempfile("tda"), ... )
fixed_weights |
a k x m matrix: interaction weight between each variable point (row) and each fixed point (column, in line order). |
variable_weights |
optional symmetric k x k matrix of weights between the variable points themselves (default: none). |
options |
a named list of further TDA options for |
dir |
working directory. |
... |
passed to |
An integer vector of length k: for each variable point, the index of the fixed point it is placed at.
Other graph analysis:
plot.tda_graph(),
tda_dmet(),
tda_g(),
tda_g_analyses,
tda_graph(),
tda_ptree(),
tda_ucl()
# two facilities, four sites; facility 1 mostly serves site 2, # facility 2 site 3, and the two facilities interact vf <- rbind(c(8, 1, 1, 2), c(1, 1, 7, 3)) tda_locate_line(vf, variable_weights = rbind(c(0, 5), c(5, 0)))# two facilities, four sites; facility 1 mostly serves site 2, # facility 2 site 3, and the two facilities interact vf <- rbind(c(8, 1, 1, 2), c(1, 1, 7, 3)) tda_locate_line(vf, variable_weights = rbind(c(0, 5), c(5, 0)))
Builds the many-way contingency table TDA's loglin works from
out of the variables named in formula, and fits a log-linear
model to it. coef(), vcov(), and residuals()
work directly on the result, the same as for any other model in this
package.
tda_loglin( formula, data, weights = NULL, scale = NULL, residuals = FALSE, control = NULL, options = list(), dir = tempfile("tda") ) ## S3 method for class 'tda_loglin' coef(object, ...) ## S3 method for class 'tda_loglin' vcov(object, ...) ## S3 method for class 'tda_loglin' residuals(object, ...) ## S3 method for class 'tda_loglin' print(x, ...)tda_loglin( formula, data, weights = NULL, scale = NULL, residuals = FALSE, control = NULL, options = list(), dir = tempfile("tda") ) ## S3 method for class 'tda_loglin' coef(object, ...) ## S3 method for class 'tda_loglin' vcov(object, ...) ## S3 method for class 'tda_loglin' residuals(object, ...) ## S3 method for class 'tda_loglin' print(x, ...)
formula |
a formula (or a list of formulas) naming the table's dimensions and the model(s) to fit against it – see Details. |
data |
a data frame. |
weights, scale
|
optional case weights and a scale variable
( |
residuals |
also compute each cell's observed count, fitted
value, residual, and scale factor – |
control |
convergence settings ( |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
object, x
|
a |
... |
unused; present for S3 consistency. |
TDA's mod= syntax refers to a table's dimensions by
position – the first variable given is A, the second
B, and so on – never by the variable's name, and letters
run together ("AB") name the saturated interaction between
them (section 6.19.2 of the manual: "AB" expands to
"A+B+A.B").
This is built from an ordinary R formula instead – ~X1 + X2
(main effects only), ~X1 * X2 (main effects and their
interaction), ~X1:X2 (the interaction alone) – translated to
TDA's letters automatically via terms, so nothing
about that lettering has to be worked out or written by hand.
~X1 + X2 fits 5 coefficients, not 2, for the same reason any
other model in this package with a categorical predictor does: TDA
dummy-codes each level of a variable past its first (with 3-level
X1/X2: 1
constant + 2 dummies for X1 + 2 for X2 = 5), not one
coefficient per variable the way a table with only two dimensions
might suggest.
Give several formulas in a list to fit several models against the
same table in one call, the way TDA's repeated mod= does
(each is a separate model with its own full statistic block, not a
combined fit) – TDA's two
shipped examples (ll1.cf/ll2.cf) each fit at most one
model, so this is the less common case, not the primary interface:
coef()/vcov()/residuals() only work directly
when exactly one formula was given, and name every model by its own
deparsed formula when more than one was (fit$models[["~a * b"]]).
loglin itself never prints a log-likelihood,
only the likelihood ratio statistic comparing the fitted model
against the saturated one – in fit$lr/fit$lr_p
(fit$models[["..."]]$lr for more than one formula), not
logLik(), which has no TDA-reported value to return here.
An object carrying table (the contingency table, its
own columns named after formula's real variables and
weights – or, with no weights at all, F,
the manual's name for a plain count column – never TDA's
internal letters or a generic name) and, when exactly one
formula was given, coefficients (a data frame, at
TDA's full precision, parameter names translated back from
A/B/... to formula's variable names),
vcov, lr/lr_p/pearson/pearson_p/
f/df, and, with residuals = TRUE, residuals –
reachable directly, or through coef()/vcov()/
residuals(). With more than one formula, all of this
lives in models instead, a list named after each formula
given, one entry per model with the same fields.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_quant(),
tda_rcorr(),
tda_segr(),
tda_subm()
set.seed(1) n <- 200 d <- data.frame(a = rbinom(n, 1, 0.5) + 1, b = rbinom(n, 1, 0.5) + 1) fit <- tda_loglin(~a * b, d) coef(fit) fit$table # weighted, with a tighter iteration cap -- weights as a column name d$w <- runif(n, 0.5, 2) tda_loglin(~a * b, d, weights = "w", control = tda_control(maxit = 30))$lr # several models against the same table at once, the less common case cmp <- tda_loglin(list(~a, ~a * b), d) cmp$models[["~a"]][c("lr", "df")] # main effect of a only cmp$models[["~a * b"]]$coefficients # saturated: perfect fitset.seed(1) n <- 200 d <- data.frame(a = rbinom(n, 1, 0.5) + 1, b = rbinom(n, 1, 0.5) + 1) fit <- tda_loglin(~a * b, d) coef(fit) fit$table # weighted, with a tighter iteration cap -- weights as a column name d$w <- runif(n, 0.5, 2) tda_loglin(~a * b, d, weights = "w", control = tda_control(maxit = 30))$lr # several models against the same table at once, the less common case cmp <- tda_loglin(list(~a, ~a * b), d) cmp$models[["~a"]][c("lr", "df")] # main effect of a only cmp$models[["~a * b"]]$coefficients # saturated: perfect fit
tda_lsreg is ordinary least squares, TDA's lsreg.
tda_lsreg1 is the same method with a censored dependent variable,
TDA's lsreg1: the response is only known to lie beyond its
recorded value for the cases the censoring variable marks.
tda_lsreg( formula, data, weights = NULL, intercept = NULL, robust = FALSE, equality = NULL, inequality = NULL, dgroup = NULL, options = list(), residuals = FALSE, dir = tempfile("tda"), ... ) tda_lsreg1( formula, data, censor, id = NULL, method = c("marginal", "joint1", "joint2"), intercept = NULL, offset = NULL, n_boxes = NULL, delta = NULL, residuals = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... )tda_lsreg( formula, data, weights = NULL, intercept = NULL, robust = FALSE, equality = NULL, inequality = NULL, dgroup = NULL, options = list(), residuals = FALSE, dir = tempfile("tda"), ... ) tda_lsreg1( formula, data, censor, id = NULL, method = c("marginal", "joint1", "joint2"), intercept = NULL, offset = NULL, n_boxes = NULL, delta = NULL, residuals = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a two-sided formula, or, for multiple equations fit jointly, an (optionally named) list of them, as described above. |
data |
a data frame. |
weights |
optional case weights, as in |
intercept |
whether to include an
intercept. Defaults to whatever the formula itself says ( |
robust |
for |
equality, inequality
|
for |
dgroup |
for |
options |
a named list of further TDA options, passed through:
|
residuals |
for |
dir |
working directory. |
... |
passed to |
censor |
for |
id |
for multiple equations, the name of the column identifying
which case each row of |
method |
for multiple equations, how the censored expectations are
estimated: |
offset, n_boxes
|
for |
delta |
for |
control |
for |
Both return a tda_fit, so coef and summary work on
them as they do for the model functions. lsreg reports a standard
error, a coefficient-to-error ratio and a significance level beside each
estimate; where it shows --- it had nothing to compute them from,
which happens when the fit is exact and the residual variance is zero.
lsreg1 does not print its estimates – it writes them to the file
named by ppar= – so tda_lsreg1 always asks for that file
and reads it back.
lsreg1 estimates the marginal distribution function of the
response before fitting, which is why it iterates; with no censored case
it reproduces tda_lsreg exactly, and the estimates move away from
the least squares ones as the censored share grows.
tda_lsreg1 also fits several censored regression equations
jointly (a system of seemingly-unrelated regressions, SUR) when
formula is a list, one formula per equation, and id names
the column identifying which case each row belongs to – TDA's
grp= option. Each equation gets its own 0/1 indicator and its
own zero-padded copy of every predictor (zero outside its
equation's rows), built here automatically; this standard SUR
construction is what gives each equation its own, separate
coefficients, rather than one fit pooled across all of them.
An object of class tda_fit. With dgroup= it also
carries groups: one row per group, its case count and its
weight, which TDA prints and stores nowhere else.
summary() shows a
p-value column computed from the coefficient's test statistic with
the same reference distribution TDA itself uses (a t on the
residual degrees of freedom here), alongside the residual standard
error, R-squared, and the F statistic with its p-value. Cases with
a missing value in the response or any predictor are dropped before
TDA sees the data, with a message (see ?tdaR on missing
values).
tda_lsreg1 is experimental. TDA's lsreg1 does not print a
standard error, a C/Error ratio, a log likelihood or a convergence flag
the way the model commands do, so coef() works but
summary(), logLik() and vcov() carry NA or
NULL where the other fitting functions carry a value. This
reflects what TDA itself reports, not a parsing gap. predict()
and fitted() are not available for the multi-equation form –
coef() and summary() are.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_freg(),
tda_gdf(),
tda_l1reg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
set.seed(1) d <- data.frame(x = 1:40, z = rnorm(40)) # with an error term: fitting a response that is an exact function of the # predictors leaves no residual variance, and the standard errors come # back as "---" because there is nothing to divide by d$y <- 2 + 0.5 * d$x + d$z + rnorm(40) fit <- tda_lsreg(y ~ x + z, d) coef(fit) summary(fit) # a constrained fit: the two coefficients forced to sum to exactly 8 # (matching the true generating values, 3 and 5), a real feature of # lsreg itself (lsecon=), not a general optimiser option -- # coefficients are written in terms of x1 and x2, not TDA's # b1/b2 labels d2 <- data.frame(x1 = rnorm(60), x2 = rnorm(60)) d2$y <- 3 * d2$x1 + 5 * d2$x2 + rnorm(60, sd = 0.5) cfit <- tda_lsreg(y ~ x1 + x2, d2, intercept = FALSE, equality = "x1 + x2 = 8") coef(cfit) sum(coef(cfit)) # exactly 8, by construction # dgroup: every level of a categorical predictor estimated at once, # not one dropped as a reference -- true group effects are 1, 3, 5 set.seed(2) n <- 120 g <- sample(c("A", "B", "C"), n, replace = TRUE) d3 <- data.frame(x = rnorm(n)) eff <- c(A = 1, B = 3, C = 5)[g] d3$y <- eff + 0.5 * d3$x + rnorm(n, sd = 0.3) gfit <- tda_lsreg(y ~ x, d3, dgroup = g) coef(gfit) # intercept is the weighted grand mean; each dgroup # coefficient its level's deviation from it # fitted values and residuals: predict() with no newdata falls back to # the data the model was fit on; residuals() needs residuals = TRUE at # fit time (TDA has to be asked to write them, so it is not automatic) fit2 <- tda_lsreg(y ~ x + z, d, residuals = TRUE) head(predict(fit2)) head(residuals(fit2)) predict(fit2, newdata = data.frame(x = c(0, 20), z = c(0, 0))) # the same data with the response censored above 22: only the cases # below it are observed, the rest are known only to lie beyond d$cen <- as.integer(d$y > 22) d$yc <- pmin(d$y, 22) coef(tda_lsreg1(yc ~ x + z, d, censor = "cen")) # two censored equations, fit jointly: true coefficients are 2, 0.8 # for the first and 5, -0.5 for the second set.seed(2) n <- 60 d2 <- data.frame(id = 1:n, x1 = rnorm(n), x2 = rnorm(n)) y1 <- 2 + 0.8 * d2$x1 + rnorm(n, sd = 0.4) y2 <- 5 - 0.5 * d2$x2 + rnorm(n, sd = 0.4) d2$cen1 <- as.integer(y1 > 2.5) d2$cen2 <- as.integer(y2 > 5.5) d2$y1 <- pmin(y1, 2.5) d2$y2 <- pmin(y2, 5.5) sur <- tda_lsreg1(list(Eq1 = y1 ~ x1, Eq2 = y2 ~ x2), d2, censor = list("cen1", "cen2"), id = "id") coef(sur) coef(tda_lsreg1(list(Eq1 = y1 ~ x1, Eq2 = y2 ~ x2), d2, censor = list("cen1", "cen2"), id = "id", method = "joint1")) # a different fit, not the same # numbers under a new nameset.seed(1) d <- data.frame(x = 1:40, z = rnorm(40)) # with an error term: fitting a response that is an exact function of the # predictors leaves no residual variance, and the standard errors come # back as "---" because there is nothing to divide by d$y <- 2 + 0.5 * d$x + d$z + rnorm(40) fit <- tda_lsreg(y ~ x + z, d) coef(fit) summary(fit) # a constrained fit: the two coefficients forced to sum to exactly 8 # (matching the true generating values, 3 and 5), a real feature of # lsreg itself (lsecon=), not a general optimiser option -- # coefficients are written in terms of x1 and x2, not TDA's # b1/b2 labels d2 <- data.frame(x1 = rnorm(60), x2 = rnorm(60)) d2$y <- 3 * d2$x1 + 5 * d2$x2 + rnorm(60, sd = 0.5) cfit <- tda_lsreg(y ~ x1 + x2, d2, intercept = FALSE, equality = "x1 + x2 = 8") coef(cfit) sum(coef(cfit)) # exactly 8, by construction # dgroup: every level of a categorical predictor estimated at once, # not one dropped as a reference -- true group effects are 1, 3, 5 set.seed(2) n <- 120 g <- sample(c("A", "B", "C"), n, replace = TRUE) d3 <- data.frame(x = rnorm(n)) eff <- c(A = 1, B = 3, C = 5)[g] d3$y <- eff + 0.5 * d3$x + rnorm(n, sd = 0.3) gfit <- tda_lsreg(y ~ x, d3, dgroup = g) coef(gfit) # intercept is the weighted grand mean; each dgroup # coefficient its level's deviation from it # fitted values and residuals: predict() with no newdata falls back to # the data the model was fit on; residuals() needs residuals = TRUE at # fit time (TDA has to be asked to write them, so it is not automatic) fit2 <- tda_lsreg(y ~ x + z, d, residuals = TRUE) head(predict(fit2)) head(residuals(fit2)) predict(fit2, newdata = data.frame(x = c(0, 20), z = c(0, 0))) # the same data with the response censored above 22: only the cases # below it are observed, the rest are known only to lie beyond d$cen <- as.integer(d$y > 22) d$yc <- pmin(d$y, 22) coef(tda_lsreg1(yc ~ x + z, d, censor = "cen")) # two censored equations, fit jointly: true coefficients are 2, 0.8 # for the first and 5, -0.5 for the second set.seed(2) n <- 60 d2 <- data.frame(id = 1:n, x1 = rnorm(n), x2 = rnorm(n)) y1 <- 2 + 0.8 * d2$x1 + rnorm(n, sd = 0.4) y2 <- 5 - 0.5 * d2$x2 + rnorm(n, sd = 0.4) d2$cen1 <- as.integer(y1 > 2.5) d2$cen2 <- as.integer(y2 > 5.5) d2$y1 <- pmin(y1, 2.5) d2$y2 <- pmin(y2, 5.5) sur <- tda_lsreg1(list(Eq1 = y1 ~ x1, Eq2 = y2 ~ x2), d2, censor = list("cen1", "cen2"), id = "id") coef(sur) coef(tda_lsreg1(list(Eq1 = y1 ~ x1, Eq2 = y2 ~ x2), d2, censor = list("cen1", "cen2"), id = "id", method = "joint1")) # a different fit, not the same # numbers under a new name
Sums A's entries within each (row-group, column-group)
block – TDA's mag. row_groups/col_groups
assign each row/column of A to a group (any positive
integers; groups need not be contiguous or start at 1). The
result has one row per distinct value in row_groups and
one column per distinct value in col_groups, in ascending
order of group number.
tda_mag(A, row_groups, col_groups, dir = tempfile("tda"))tda_mag(A, row_groups, col_groups, dir = tempfile("tda"))
A |
a numeric matrix. |
row_groups |
integer group index for each row, length
|
col_groups |
integer group index for each column, length
|
dir |
working directory. |
A numeric matrix.
Other matrix reshaping:
tda_mcath(),
tda_mcvec(),
tda_mrsum(),
tda_msort(),
tda_msrow(),
tda_mtrim()
A <- matrix(1:12, 3, 4, byrow = TRUE) tda_mag(A, row_groups = c(1, 2, 1), col_groups = c(1, 1, 2, 2))A <- matrix(1:12, 3, 4, byrow = TRUE) tda_mag(A, row_groups = c(1, 2, 1), col_groups = c(1, 1, 2, 2))
Working through TDA's manual section by section, some commands have no function of their own here. None of them is missing functionality; each is covered in one of three ways.
Subsumed by R itself. The matrix definition commands
exist because TDA has no other way to get a matrix into a session;
R does. mdef (literal) is matrix(); mdefc
(constant) is matrix(d, m, n); mdefi (rectangular
identity) is diag(1, m, n); mdeff (from file) is
as.matrix(read.table(...)) or tda_read_table;
mpr (print a matrix expression) is printing the return value
of any matrix wrapper. The expression operators of section 5.2.5
– nd, ndi, td, chd, fd,
mr, ndf, poisson, negbin, bivn,
jul, july, julm, juld and relatives –
are pnorm, qnorm, pt, pchisq,
pf, the Mill's ratio dnorm(x)/(1 - pnorm(x)),
dnorm, dpois/dnbinom (TDA returns the log
density), mvtnorm::pmvnorm, and R's date arithmetic. The
engine's implementations of all of these are compared against
R's on every run of the differential fuzzer, so using either side
gives the same numbers; to evaluate one of TDA's operators
directly, pass the expression to tda_evalf.
Delivered by another wrapper. mdefg (adjacency
matrix from the current graph) is
tda_g_edges(g, format = "full_square"), with -1
marking absent edges. mbrr is tda_brr.
mple is tda_mple. mlp's raw-tableau
form is assembled internally by tda_mlp from the
objective, constraints, and bounds.
Reached through the session they belong to.
mdefb (a block of the data matrix) requires a
dblock context and is used through the commands=
argument of tda_dblock. mplog,
mppar, mpcov and mpgrad are parameters OF
estimation commands, not commands; their contents are what the
fitted objects already carry as $logLik, $estimates
and $vcov (case-specific gradients, mpgrad, can be
requested through a command's options= where supported).
Chapter 5 names that are not standalone commands:
mplog, mppar, mpcov,
mpgrad
parameters of the estimation commands that
write the log likelihood, parameters, covariance matrix or
gradient into a named TDA matrix. The R wrappers return the
same quantities directly ($logLik, $estimates,
$vcov), so these are only needed inside a hand-written
tda_run matrix pipeline, where they pass
through options= as usual.
mdef, mpr, mdefc, mdefi,
mdeff
matrix definition and printing, which R does
natively: matrix(...), print(),
matrix(d, m, n), diag(1, m, n) and
as.matrix(read.table(fname)); every matrix wrapper
accepts plain R matrices. mdefg (a graph's adjacency
matrix) does compute something and has its wrapper,
tda_mdefg.
mdefbextracts one dblock-defined block of the
data matrix into a matrix – in R, subset the data frame; in
a tda_run script it works after a
dblock command as documented.
mbrrthe manual's name for brr; see
tda_brr.
sort (command)see tda_esort and
the sort= option of pdata in
tda_read_sys.
lag, suc, snum, rank,
sort (operator)operators of TDA's expression
language, used inside nvar variable definitions –
e.g. L[6.0]=lag(Y,1), R[6.0]=rank(Y) – in a
tda_run script. snum, rank
and sort take the variable as an argument.
tda_map draws spatial objects in a geographical coordinate system
– a projection, rather than the plain x and y of plot(). TDA
builds that system with psetupg and then draws with sdpmap;
graticule adds meridians and parallels with sdpgrat, and
points adds coordinates given directly with sdpgeo.
tda_map( s, view, region, projection = 10, width = 150, graticule = list(), points = NULL, symbol = 1, newpage = TRUE, ... )tda_map( s, view, region, projection = 10, width = 150, graticule = list(), points = NULL, symbol = 1, newpage = TRUE, ... )
s |
a |
view |
centre of the projection, as longitude and latitude. |
region |
half-width and half-height of the mapped area, in degrees. |
projection |
10 cylindrical equidistant, 11 cylindrical equal-area,
12 Mercator, 20 azimuthal orthographic. For projection 20 the
longitude half-width is limited to 90 degrees, and the whole region
rectangle must fit on the projection disc, so both halves of
|
width |
width of the plot in mm. |
graticule |
a list of options for the meridians and parallels, or
|
points |
a data frame of |
symbol |
marker symbol for |
newpage |
start a new grid page. |
... |
further options for |
region is required and has no default: it is the half-width and
half-height of the mapped area in degrees, measured from view. So
view = c(-80, 35), region = c(6, 3) maps 6 degrees of longitude
and 3 of latitude either side of that point.
The map, drawn; the session is returned invisibly.
Other spatial analysis:
plot.tda_spatial(),
tda_polygons(),
tda_read_dbf(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd(),
tda_sd_analyses,
tda_sd_ps3(),
tda_spatial()
if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) tda_map(nc, view = c(-80, 35), region = c(6, 3), graticule = list(lon = "-84(2)-76", lat = "34(1)37", fsx = 2, fsy = 2)) }if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) tda_map(nc, view = c(-80, 35), region = c(6, 3), graticule = list(lon = "-84(2)-76", lat = "34(1)37", fsx = 2, fsy = 2)) }
Runs any of TDA's matrix commands on R matrices and returns R matrices.
This is a generic interface rather than one function per operation: R
already has %*%, solve and eigen, so named wrappers
would add nothing, but the whole of TDA's matrix language stays reachable.
tda_mat(op, ..., out = "R", options = list(), dir = tempfile("tda"))tda_mat(op, ..., out = "R", options = list(), dir = tempfile("tda"))
op |
the command name. TDA's matrix language has about eighty:
|
... |
input matrices, in the order the command expects. |
out |
names of the result matrices to read back. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
A matrix if one result was asked for, otherwise a named list of them.
The inputs are written as TDA matrices named A, B, ... in
order, the command is run, and every matrix named in out is read
back. TDA's convention is that results come last in the argument list, so
mmul(A,B,R) multiplies A by B into R.
tda_mat("mmul", A, B, out = "R") # A
tda_mat("mev", A, out = c("ER", "EI")) # eigenvalues, real and imaginary
Other smoothing:
tda_integrate(),
tda_interp(),
tda_isotonic(),
tda_sma(),
tda_smd(),
tda_spl()
A <- matrix(1:4, 2) B <- diag(2) tda_mat("mmul", A, B, out = "R")A <- matrix(1:4, 2) B <- diag(2) tda_mat("mmul", A, B, out = "R")
tda_mcath concatenates horizontally – TDA's mcath,
matching cbind. tda_mcatv concatenates vertically –
TDA's mcatv, matching rbind. tda_mcathv takes
the matrix direct sum: the inputs placed as block-diagonal
blocks, zero elsewhere – TDA's mcathv (all three take two
or more matrices).
tda_mcath(..., dir = tempfile("tda")) tda_mcatv(..., dir = tempfile("tda")) tda_mcathv(..., dir = tempfile("tda"))tda_mcath(..., dir = tempfile("tda")) tda_mcatv(..., dir = tempfile("tda")) tda_mcathv(..., dir = tempfile("tda"))
... |
two or more numeric matrices. |
dir |
working directory. |
A numeric matrix.
Other matrix reshaping:
tda_mag(),
tda_mcvec(),
tda_mrsum(),
tda_msort(),
tda_msrow(),
tda_mtrim()
A <- matrix(1:4, 2); B <- matrix(5:8, 2) tda_mcath(A, B) # == cbind(A, B) tda_mcatv(A, B) # == rbind(A, B) tda_mcathv(A, B) # block-diagonal direct sumA <- matrix(1:4, 2); B <- matrix(5:8, 2) tda_mcath(A, B) # == cbind(A, B) tda_mcatv(A, B) # == rbind(A, B) tda_mcathv(A, B) # block-diagonal direct sum
Lists every (i, j) with A[i, j] >= x as one row
(i, j, A[i, j]) – TDA's mcel, scanning row by row.
Refuses if no element of A reaches x (there would be
nothing to return).
tda_mcel(A, x, dir = tempfile("tda"))tda_mcel(A, x, dir = tempfile("tda"))
A |
a square numeric matrix. |
x |
the threshold; an entry is an edge when it is at least this large. |
dir |
working directory. |
A 3-column numeric matrix: i, j, and the
value A[i, j], one row per edge.
Other matrix algebra:
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
# a valued adjacency matrix; keep the edges of value 2 or more A <- matrix(c(0, 3, 0, 1, 0, 5, 0, 2, 0), 3, byrow = TRUE) tda_mcel(A, 2) # (1,2) 3, (2,3) 5, (3,2) 2 -- (2,1) 1 is dropped# a valued adjacency matrix; keep the edges of value 2 or more A <- matrix(c(0, 3, 0, 1, 0, 5, 0, 2, 0), 3, byrow = TRUE) tda_mcel(A, 2) # (1,2) 3, (2,3) 5, (3,2) 2 -- (2,1) 1 is dropped
tda_mcent subtracts each column's mean – TDA's
mcent, matching sweep(A, 2, colMeans(A)).
tda_mstand additionally divides each column by its
population standard deviation (denominator n, not
base R's sd()'s n-1) – TDA's mstand.
tda_mdcent
double-centers a symmetric matrix – TDA's mdcent, the
classical (Torgerson) transformation multidimensional scaling
uses to turn a matrix of squared distances into one whose
eigendecomposition gives point coordinates.
tda_mcent(A, dir = tempfile("tda")) tda_mstand(A, dir = tempfile("tda")) tda_mdcent(D, dir = tempfile("tda"))tda_mcent(A, dir = tempfile("tda")) tda_mstand(A, dir = tempfile("tda")) tda_mdcent(D, dir = tempfile("tda"))
A, D
|
a numeric matrix ( |
dir |
working directory. |
A numeric matrix.
Other matrix algebra:
tda_mcel(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(1, 2, 6, 10, 30, 20), 3, 2) tda_mcent(A) tda_mstand(A) D <- matrix(c(0, 3, 4, 3, 0, 5, 4, 5, 0), 3, 3) tda_mdcent(D)A <- matrix(c(1, 2, 6, 10, 30, 20), 3, 2) tda_mcent(A) tda_mstand(A) D <- matrix(c(0, 3, 4, 3, 0, 5, 4, 5, 0), 3, 3) tda_mdcent(D)
Flags each row/column index of a square matrix A where the
current index order fails a running dominance test against its
mirror image – TDA's mch (undocumented beyond "check row
and column sum conditions" in its own header; the rule below
is the loop body's, not a named textbook procedure). For each
index i, scanning outward
(j from i+1 to n, then separately from
i-1 down to 1), A[i, j] accumulates into a
running total z and its mirror A[j, i] accumulates
into a running total s; index i is flagged the first
time z falls behind s by more than a small tolerance.
In effect: is A[i, ]'s share of an outward pair always at
least as large, cumulatively, as the corresponding mirrored
entries in A[, i] – a diagnostic for whether the current
1:n ordering already respects that dominance, without
finding a better ordering the way tda_mpz/
tda_mpbl do.
tda_mch(A, dir = tempfile("tda"))tda_mch(A, dir = tempfile("tda"))
A |
a square numeric matrix. |
dir |
working directory. |
An integer vector, length nrow(A): 1 where that
index fails the test, 0 where it passes.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
# A[i, j] = 5 means i strongly precedes j. Ordered 1 < 2 < 3 the # rows dominate their columns and every index passes (0); the same # matrix with the order reversed fails everywhere (1). A <- matrix(c(0, 5, 5, 1, 0, 5, 1, 1, 0), 3, byrow = TRUE) tda_mch(A) tda_mch(A[3:1, 3:1])# A[i, j] = 5 means i strongly precedes j. Ordered 1 < 2 < 3 the # rows dominate their columns and every index passes (0); the same # matrix with the order reversed fails everywhere (1). A <- matrix(c(0, 5, 5, 1, 0, 5, 1, 1, 0), 3, byrow = TRUE) tda_mch(A) tda_mch(A[3:1, 3:1])
tda_mcross is TDA's mcross, matching base R's
crossprod(A) (t(A) %*% A). tda_mnum builds
the length-n arithmetic sequence starting at x with
step d – TDA's mnum, matching
seq(x, by = d, length.out = n).
tda_mcross(A, dir = tempfile("tda")) tda_mnum(x, d, n, dir = tempfile("tda"))tda_mcross(A, dir = tempfile("tda")) tda_mnum(x, d, n, dir = tempfile("tda"))
A |
a numeric matrix. |
dir |
working directory. |
x |
the starting value, for |
d |
the step, for |
n |
the length, for |
tda_mcross returns a matrix; tda_mnum
returns a plain numeric vector.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
tda_mcross(matrix(1:6, 3, 2)) # == crossprod(matrix(1:6, 3, 2)) tda_mnum(5, 2, 4) # == seq(5, by = 2, length.out = 4)tda_mcross(matrix(1:6, 3, 2)) # == crossprod(matrix(1:6, 3, 2)) tda_mnum(5, 2, 4) # == seq(5, by = 2, length.out = 4)
tda_mcvec stacks the columns of A into a single
vector – TDA's mcvec, the classic matrix-algebra
vec(A) operator, matching base R's as.vector(A)
(R matrices are column-major already). tda_mrvec stacks the
rows instead – TDA's mrvec, matching
as.vector(t(A)). tda_mivec is the inverse of
tda_mcvec: given a vector and a row count n, it
rebuilds an n-row matrix by filling column by column – TDA's
mivec, matching base R's matrix(x, nrow = n).
tda_mcvec(A, dir = tempfile("tda")) tda_mrvec(A, dir = tempfile("tda")) tda_mivec(x, n, dir = tempfile("tda"))tda_mcvec(A, dir = tempfile("tda")) tda_mrvec(A, dir = tempfile("tda")) tda_mivec(x, n, dir = tempfile("tda"))
A |
a numeric matrix. |
dir |
working directory. |
x |
a numeric vector, whose length must divide evenly by
|
n |
the number of rows for |
tda_mcvec/tda_mrvec return a plain numeric
vector; tda_mivec returns a matrix.
Other matrix reshaping:
tda_mag(),
tda_mcath(),
tda_mrsum(),
tda_msort(),
tda_msrow(),
tda_mtrim()
A <- matrix(1:6, 2, 3) tda_mcvec(A) # == as.vector(A) tda_mrvec(A) # == as.vector(t(A)) tda_mivec(1:6, 2) # == matrix(1:6, nrow = 2)A <- matrix(1:6, 2, 3) tda_mcvec(A) # == as.vector(A) tda_mrvec(A) # == as.vector(t(A)) tda_mivec(1:6, 2) # == matrix(1:6, nrow = 2)
TDA's mdefg: builds the adjacency matrix of the current
graph, with missing substituted for absent edges (TDA's
sc=, default -1 there; 0 here, which gives the usual
weighted adjacency matrix).
tda_mdefg(edges, missing = 0, directed = FALSE, valued = TRUE, ...)tda_mdefg(edges, missing = 0, directed = FALSE, valued = TRUE, ...)
edges |
edge list (data frame with from, to and optionally a value column). |
missing |
value written where no edge exists. |
directed, valued
|
graph type flags, as in |
... |
passed to |
the numeric adjacency matrix.
e <- data.frame(from = c(1, 1, 2), to = c(2, 3, 3), value = c(5, 2, 7)) tda_mdefg(e)e <- data.frame(from = c(1, 1, 2), to = c(2, 3, 3), value = c(5, 2, 7)) tda_mdefg(e)
tda_mdiag builds an n x n diagonal matrix from a length-n
vector – TDA's mdiag, matching base R's diag(x)
when x has length > 1. tda_mdiagd extracts the
diagonal of a matrix as a plain vector, using
min(nrow(A), ncol(A)) entries for a non-square A –
TDA's mdiagd, matching base R's diag(A).
tda_mdiag(x, dir = tempfile("tda")) tda_mdiagd(A, dir = tempfile("tda"))tda_mdiag(x, dir = tempfile("tda")) tda_mdiagd(A, dir = tempfile("tda"))
x |
a numeric vector. |
dir |
working directory. |
A |
a numeric matrix. |
tda_mdiag returns a matrix; tda_mdiagd
returns a plain numeric vector.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
tda_mdiag(c(5, 7, 9)) tda_mdiagd(matrix(1:6, 2, 3))tda_mdiag(c(5, 7, 9)) tda_mdiagd(matrix(1:6, 2, 3))
Represent a dissimilarity matrix as points in a low-dimensional space, so that the distances between the points approximate the dissimilarities.
TDA_MDS tda_mds( d, method = "classical", ndim = 2, options = list(), dir = tempfile("tda"), ... )TDA_MDS tda_mds( d, method = "classical", ndim = 2, options = list(), dir = tempfile("tda"), ... )
d |
a |
method |
one of the names in |
ndim |
number of dimensions to return. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
method = "classical" (TDA's mdsc) is the eigenvalue
decomposition also known as principal coordinates analysis – the same
method as cmdscale. TDA computes the full
solution, one dimension per positive eigenvalue, and never reads a
dimension count of its own; because the classical solution is nested,
the first ndim columns of the full solution are the
ndim-dimensional solution, so this wrapper simply keeps those.
The eigenvalues, with the share of the total each accounts for, come
back in eigenvalues – the usual guide to how many dimensions
the data support.
The other three methods fit the configuration iteratively.
"metric" (mdsm) minimizes the raw stress, the sum of
squared differences between dissimilarities and fitted distances,
with TDA's general minimizer; it fits two dimensions only, and errors
for any other ndim. "nonmetric" (mdsn) minimizes
Kruskal's stress-1, preserving only the rank order of the
dissimilarities, by Kruskal's (1964) gradient method with his step
length adaptation; it reaches the same or lower stress than
isoMDS on the usual test data, but its default
mxit = 100 iterations is often not enough – pass
options = list(mxit = 300), and ns = random restarts to
guard against local minima. "minmax" (mdsx) fits a
minmax criterion; TDA labels that command experimental and its output
is left as it comes. Check stress before trusting any
iterative configuration.
An object carrying points, the coordinates (one row per
object, one column per dimension), and, for "classical",
eigenvalues (a data frame of each eigenvalue and its
percentage of the total); for the iterative methods, stress,
the criterion value at the returned configuration.
Other clustering:
TDA_CLUSTER,
tda_conjoint(),
tda_cutree(),
tda_dma(),
tda_pdatd()
set.seed(34) pts <- rbind(matrix(rnorm(10, 0), 5, 2), matrix(rnorm(10, 6), 5, 2)) m <- tda_mds(dist(pts), method = "classical", ndim = 2) m$points # recovers the two clusters as two groups of coordinates m$eigenvalues # two dominant dimensions, as builtset.seed(34) pts <- rbind(matrix(rnorm(10, 0), 5, 2), matrix(rnorm(10, 6), 5, 2)) m <- tda_mds(dist(pts), method = "classical", ndim = 2) m$points # recovers the two clusters as two groups of coordinates m$eigenvalues # two dominant dimensions, as built
TDA's mdsn1 (Kruskal) on a distance matrix.
tda_mdsn( d, ties = c("ignore", "primary", "secondary"), max_iterations = 100, restarts = 5, ... )tda_mdsn( d, ties = c("ignore", "primary", "secondary"), max_iterations = 100, restarts = 5, ... )
d |
symmetric distance matrix. |
ties |
tie handling. Only |
max_iterations |
iteration cap. |
restarts |
random starting configurations, TDA's |
... |
passed to |
with direct exports enabled, a list with stress,
configuration (n x 2) and output; otherwise the
printed output lines.
d <- as.matrix(dist(cbind(c(0, 0, 3, 3), c(0, 2, 0, 2)))) tda_mdsn(d)d <- as.matrix(dist(cbind(c(0, 0, 3, 3), c(0, 2, 0, 2)))) tda_mdsn(d)
TDA's mdsr: regresses external variables onto a
two-dimensional configuration to draw interpretable axes.
tda_mdsr(config, x, ...)tda_mdsr(config, x, ...)
config |
two-column matrix, the configuration. |
x |
matrix of external variables (same row count). |
... |
passed to |
the printed output.
cfg <- cbind(c(0, 1, 2, 3), c(0, 1, 0, 1)) r <- tda_mdsr(cfg, x = cbind(v = c(1, 2, 3, 4))) cat(head(tda_payload(r), 12), sep = "\n")cfg <- cbind(c(0, 1, 2, 3), c(0, 1, 0, 1)) r <- tda_mdsr(cfg, x = cbind(v = c(1, 2, 3, 4))) cat(head(tda_payload(r), 12), sep = "\n")
Eigenvalues and eigenvectors of a square matrix that need not be
symmetric, so eigenvalues and eigenvectors may be complex – TDA's
mev. t_mat.c's dispatch comment understates this
command's arity (mev(A,ER,EI,EV), four arguments); what
m_mev actually parses is five (mev(A,ER,EI,EVR,EVI)),
splitting the eigenvector matrix into separate real and imaginary
parts, as eigen1's header lists them. Column
i of the result, EVR[, i] + 1i * EVI[, i], is the
right eigenvector for eigenvalue ER[i] + 1i * EI[i], i.e.
A %*% v == lambda * v – the same convention and ordering
as base R's eigen(A), confirmed on two matrices, one
with real eigenvalues and one with an asymmetric complex
pair (not simply plus/minus of each other, which the first,
simpler test matrix happened to have and which turned out to mask
a construction mistake in an earlier verification attempt –
recorded here because it is exactly the kind of false confirmation
a too-simple or too-symmetric test case can produce, the same
lesson tda_mevs needed).
tda_mev(A, dir = tempfile("tda"))tda_mev(A, dir = tempfile("tda"))
A |
a square numeric matrix. |
dir |
working directory. |
TDA's mev(A, ER, EI, EVR, EVI) requires all four
output operands (none are optional); the wrapper supplies
them and folds the real and imaginary parts into complex
$values and $vectors.
A list: values, a complex vector of eigenvalues;
vectors, a complex matrix whose columns are the
corresponding right eigenvectors.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
tda_mev(matrix(c(0, -1, 1, 0), 2, 2)) # eigenvalues +-itda_mev(matrix(c(0, -1, 1, 0), 2, 2)) # eigenvalues +-i
Eigenvalues and eigenvectors of a symmetric matrix – TDA's
mevs. Eigenvalues come back in descending order,
same as base R's eigen(A, symmetric = TRUE). The
eigenvectors come back as the columns of vectors,
same convention as eigen()$vectors (column i satisfies
A %*% vectors[, i] == values[i] * vectors[, i]); an
initial 2x2 test matrix was checked first and satisfied this
equally well as rows, which turned out to be a coincidence of
that specific matrix's eigenvector matrix happening to be
symmetric, not a real property of TDA's convention – worth
recording since it is exactly the kind of false confirmation a
too-simple test case can produce. As with any eigenvector, the
sign of each one is arbitrary; TDA's and R's choices need not
agree.
tda_mevs(A, dir = tempfile("tda"))tda_mevs(A, dir = tempfile("tda"))
A |
a symmetric numeric matrix (only the lower triangle is read). |
dir |
working directory. |
A list: values, the eigenvalues in descending
order; vectors, a matrix whose columns are the
corresponding unit-norm eigenvectors.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(4, 1, 0, 1, 3, 1, 0, 1, 2), 3) e <- tda_mevs(A) e$values # descending, as eigen(A)$values A %*% e$vectors[, 1] - e$values[1] * e$vectors[, 1] # zero: an eigenpairA <- matrix(c(4, 1, 0, 1, 3, 1, 0, 1, 2), 3) e <- tda_mevs(A) e$values # descending, as eigen(A)$values A %*% e$vectors[, 1] - e$values[1] * e$vectors[, 1] # zero: an eigenpair
Given a sample of intervals [lower_i, upper_i] (each
interval containing an unobserved exact value), estimates the
distribution function of that unobserved value – TDA's midf
(undocumented beyond "calculates distribution function DM, and
lower/upper bounds" in its own header, which also understates the
command's arity: it lists three outputs, midf(XL,XU,DL,DU,DM),
but m_midf actually returns four,
midf(XL,XU,PT,DL,DU,DM) – the breakpoints themselves,
PT, are a result too). Evaluated at every distinct
interval endpoint (the
“induced partition” breakpoints): lower_bound
counts only intervals entirely below that point (a sure lower bound
on the true CDF); upper_bound counts every interval that
could be below it (a sure upper bound); cdf is a
point estimate in between, assuming each interval's unobserved
value is uniformly distributed within it. Every interval must have
positive width (lower < upper, swapped automatically if
given in the other order). Confirmed cell-for-cell by hand on a
3-interval example.
tda_midf(lower, upper, dir = tempfile("tda"))tda_midf(lower, upper, dir = tempfile("tda"))
lower, upper
|
numeric vectors, the same length, with
|
dir |
working directory. |
A list: breakpoints, the sorted distinct interval
endpoints; lower_bound, upper_bound, cdf,
each the same length as breakpoints.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
# five observations known only to intervals: [0,2], [1,3], [2,4], [3,5], [1,2] lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # at each endpoint: the share of intervals surely below it (lower # bound), possibly below it (upper bound), and the estimate between tda_midf(lo, up)# five observations known only to intervals: [0,2], [1,3], [2,4], [3,5], [1,2] lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # at each endpoint: the share of intervals surely below it (lower # bound), possibly below it (upper bound), and the estimate between tda_midf(lo, up)
The same uniform-within-interval distribution function estimate as
tda_midf's cdf, but evaluated at each
observation's lower[i] rather than at every distinct
breakpoint – TDA's midf1.
tda_midf1(lower, upper, dir = tempfile("tda"))tda_midf1(lower, upper, dir = tempfile("tda"))
lower, upper
|
numeric vectors, the same length, with
|
dir |
working directory. |
A numeric vector, the same length as lower, in the
original (unsorted) order.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # the estimated distribution function at each interval's own position tda_midf1(lo, up)lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # the estimated distribution function at each interval's own position tda_midf1(lo, up)
For each observation, the conditional mean of the unobserved value
given that it exceeds that observation's lower[i] –
– estimated by
integrating a piecewise-uniform density built from
tda_midf's CDF estimate over the induced partition –
TDA's midf2: it builds the CDF at every
breakpoint, then integrates the resulting piecewise-constant density
from each observation's value onward, normalizing by the
survival probability there.
tda_midf2(lower, upper, dir = tempfile("tda"))tda_midf2(lower, upper, dir = tempfile("tda"))
lower, upper
|
numeric vectors, the same length, with
|
dir |
working directory. |
A numeric vector, the same length as lower, in the
original (unsorted) order.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # the expected value of each observation given that it lies in its # interval, under the estimated distribution tda_midf2(lo, up)lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # the expected value of each observation given that it lies in its # interval, under the estimated distribution tda_midf2(lo, up)
For each interval i, averages the lower endpoints of every
interval (itself included) whose lower endpoint falls within
[lower[i], upper[i]], and separately averages the upper
endpoints falling in that same range – TDA's midf3. A
local smoothing of nearby endpoints, not a distribution estimate
like tda_midf/tda_midf1/
tda_midf2.
tda_midf3(lower, upper, dir = tempfile("tda"))tda_midf3(lower, upper, dir = tempfile("tda"))
lower, upper
|
numeric vectors, the same length. |
dir |
working directory. |
A list, both the same length as lower, in the
original order: lower_avg, the average nearby lower
endpoint; upper_avg, the average nearby upper endpoint.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # for each interval, the mean lower and upper endpoint of the # intervals overlapping it tda_midf3(lo, up)lo <- c(0, 1, 2, 3, 1) up <- c(2, 3, 4, 5, 2) # for each interval, the mean lower and upper endpoint of the # intervals overlapping it tda_midf3(lo, up)
Three different things, despite the similar names – read the one
you need. tda_minvs is the actual matrix inverse of a
symmetric positive-definite matrix (TDA's minvs, via a
Cholesky-based algorithm; refuses if not positive definite).
tda_minvd inverts only the diagonal elements of A,
element by element – not a matrix inverse at all, and
off-diagonal entries are ignored entirely (TDA's minvd; a
zero diagonal entry is silently left as 0 rather than inverted).
tda_mginv is the Moore-Penrose pseudoinverse, requiring at
least as many rows as columns and full column rank (TDA's
mginv; prints the pseudorank as a side effect, discarded
here – read it from attr(x, "run")$output if needed).
tda_minvs(A, dir = tempfile("tda")) tda_minvd(A, dir = tempfile("tda")) tda_mginv(A, dir = tempfile("tda"))tda_minvs(A, dir = tempfile("tda")) tda_minvd(A, dir = tempfile("tda")) tda_mginv(A, dir = tempfile("tda"))
A |
a numeric matrix: square for |
dir |
working directory. |
A numeric matrix.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(4, 2, 2, 3), 2) tda_minvs(A) # == solve(A) for symmetric positive-definite A tda_minvd(matrix(c(2, 1, 4, 5, 3, 8, 9, 7, 1), 3)) # diag(1/diag(.)) tda_mginv(matrix(c(1, 1, 1, 1, 2, 3), 3))A <- matrix(c(4, 2, 2, 3), 2) tda_minvs(A) # == solve(A) for symmetric positive-definite A tda_minvd(matrix(c(2, 1, 4, 5, 3, 8, 9, 7, 1), 3)) # diag(1/diag(.)) tda_mginv(matrix(c(1, 1, 1, 1, 2, 3), 3))
Pairwise Kemeny (Kendall-tau-with-ties) distance between every
pair of rows of A, each row a ranking (or score) over the
same set of items – TDA's mkmet. For two rankings, each
pair of items contributes 0 if both rankings order (or tie) the
pair the same way, 1 if one ranking ties the pair and the other
doesn't, or 2 if the rankings strictly disagree on the pair's
order.
tda_mkmet(A, dir = tempfile("tda"))tda_mkmet(A, dir = tempfile("tda"))
A |
a numeric matrix, one ranking per row. |
dir |
working directory. |
A symmetric numeric matrix with zero diagonal, the Kemeny distance between every pair of rows.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
# four rankings of the same four items: b swaps the last two of a, # c reverses a, d ties items in pairs R <- rbind(a = c(1, 2, 3, 4), b = c(1, 2, 4, 3), c = c(4, 3, 2, 1), d = c(1, 1, 2, 2)) tda_mkmet(R) # a-b: 2 (one pair reversed); a-c: 12 (all six pairs)# four rankings of the same four items: b swaps the last two of a, # c reverses a, d ties items in pairs R <- rbind(a = c(1, 2, 3, 4), b = c(1, 2, 4, 3), c = c(4, 3, 2, 1), d = c(1, 1, 2, 2)) tda_mkmet(R) # a-b: 2 (one pair reversed); a-c: 12 (all six pairs)
TDA's mkp, matching base R's kronecker(A, B)
exactly.
tda_mkp(A, B, dir = tempfile("tda"))tda_mkp(A, B, dir = tempfile("tda"))
A, B
|
numeric matrices. |
dir |
working directory. |
A numeric matrix, nrow(A)*nrow(B) by
ncol(A)*ncol(B).
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
tda_mkp(matrix(1:4, 2), matrix(5:8, 2))tda_mkp(matrix(1:4, 2), matrix(5:8, 2))
Maximize (or minimize) a linear objective subject to linear
inequality and/or equality constraints – TDA's mlp and
mlp1 (Salazar & Sen's MINIT, CACM algorithm 333).
tda_mlp takes only inequality constraints, matching
mlp(T,X,Y); tda_mlp1 adds equality constraints,
matching mlp1(T,p,X,Y) – the two are the same underlying
call with p fixed at 0 for tda_mlp. The problem solved,
after negating the objective internally for direction =
"min", is
with the dual (this is all stated directly in
lpf1's header in t_lp.c; nothing here was
guessed). Equality-constraint rows report a dual value of 0 –
TDA's convention, not something this wrapper computes. Verified
by hand for a plain and an equality instance, and against
brute-force vertex enumeration in test-r-comparisons.R.
tda_mlp( objective, constraints, bounds, direction = c("max", "min"), dir = tempfile("tda"), ... ) tda_mlp1( objective, constraints = NULL, bounds = NULL, equalities = NULL, equalities_bounds = NULL, direction = c("max", "min"), dir = tempfile("tda"), ... )tda_mlp( objective, constraints, bounds, direction = c("max", "min"), dir = tempfile("tda"), ... ) tda_mlp1( objective, constraints = NULL, bounds = NULL, equalities = NULL, equalities_bounds = NULL, direction = c("max", "min"), dir = tempfile("tda"), ... )
objective |
coefficients |
constraints |
the inequality constraint matrix |
bounds |
the right-hand sides |
direction |
|
dir |
working directory. |
... |
passed to |
equalities |
an equality constraint matrix |
equalities_bounds |
the right-hand sides |
tda_mlp also accepts TDA's single-tableau form,
mlp(T, X, Y): the first row is the objective
(c, 0) and the remaining rows are the constraints
[A, b], exactly the layout the solver documents.
tda_mlp(T) decomposes it accordingly.
The manual's Box example writes mlp(T, X, Y, 1) with a
fourth operand. That form does not exist in this source tree:
the shipped 6.4q parser (checked against a pristine copy of the
upstream source) accepts exactly mlp(T, X, Y) and
mlp1(T, p, X, Y), so the box was produced by a different
release. On the box's problem the three-operand form gives
the same value (1) and the same dual vector (1, 0); only the
primal solution differs – (1, 0) here against the manual's
(1, 1) – and both are vertices of the same optimal face, since
maximising x1 under x1 <= 1, x2 <= 1 leaves x2 free at the
optimum. Nothing disagrees beyond the tie-break.
A list: value, the objective at the optimum;
x, the primal solution; y, the dual solution (one
entry per constraint row, inequalities then equalities, equality
rows always 0).
Other optimization:
tda_boolean_min(),
tda_mlpi(),
tda_mls(),
tda_mqap(),
tda_mqp()
# maximize 3x1 + 2x2 s.t. x1 + x2 <= 4, x1 + 3x2 <= 6 tda_mlp(c(3, 2), rbind(c(1, 1), c(1, 3)), c(4, 6)) # same, plus x1 + x2 = 3 exactly tda_mlp1(c(3, 2), rbind(c(1, 3)), c(6), equalities = rbind(c(1, 1)), equalities_bounds = 3)# maximize 3x1 + 2x2 s.t. x1 + x2 <= 4, x1 + 3x2 <= 6 tda_mlp(c(3, 2), rbind(c(1, 1), c(1, 3)), c(4, 6)) # same, plus x1 + x2 = 3 exactly tda_mlp1(c(3, 2), rbind(c(1, 3)), c(6), equalities = rbind(c(1, 1)), equalities_bounds = 3)
Maximize a linear objective over 0-1 variables under linear
constraints – TDA's mlpi (CACM algorithm 449). The problem
solved is
with integer coefficients (negative ones are fine). The command's
source states no objective; this is what it computes, established
against exhaustive search – see examples/coverage/mlpiops.cf.
tda_mlpi( objective, constraints, bounds, constant = 0, max_solutions = 100, dir = tempfile("tda"), ... )tda_mlpi( objective, constraints, bounds, constant = 0, max_solutions = 100, dir = tempfile("tda"), ... )
objective |
integer coefficients |
constraints |
the constraint matrix |
bounds |
the right-hand sides |
constant |
|
max_solutions |
how many optimal solutions to return at most. |
dir |
working directory. |
... |
passed to |
A list: value, the maximum; solutions, a matrix
with one optimal 0-1 vector per row.
Other optimization:
tda_boolean_min(),
tda_mlp(),
tda_mls(),
tda_mqap(),
tda_mqp()
# maximize 2 x1 - 3 x2 + 4 x3 + x4 s.t. sum(x) >= 2, # -x1 + 2 x2 + x4 >= 1 tda_mlpi(c(2, -3, 4, 1), rbind(c(1, 1, 1, 1), c(-1, 2, 0, 1)), bounds = c(2, 1))# maximize 2 x1 - 3 x2 + 4 x3 + x4 s.t. sum(x) >= 2, # -x1 + 2 x2 + x4 >= 1 tda_mlpi(c(2, -3, 4, 1), rbind(c(1, 1, 1, 1), c(-1, 2, 0, 1)), bounds = c(2, 1))
The within-group pairwise design matrix TDA's mldes builds for
MLRC models: for objects with attribute rows z and a grouping
in consecutive runs, the row for the ordered pair (kk, k) holds the
products z[k, i1] * z[kk, i2] (i2-major) plus an indicator for
k == kk when both objects are in the same group, and zeros otherwise.
Semantics established against the source and verified cell-for-cell;
see examples/coverage/mldesops.cf.
tda_mlrc_design(z, groups, dir = tempfile("tda"), ...)tda_mlrc_design(z, groups, dir = tempfile("tda"), ...)
z |
an n x q matrix, one row per object. |
groups |
length-n vector; consecutive equal values form groups. |
dir |
working directory. |
... |
passed to |
The n^2 x (q^2 + 1) design matrix.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_freg(),
tda_gdf(),
tda_l1reg(),
tda_lsreg(),
tda_mreg(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
z <- rbind(c(1, 2), c(3, 4), c(5, 6)) tda_mlrc_design(z, groups = c(1, 1, 2))z <- rbind(c(1, 2), c(3, 4), c(5, 6)) tda_mlrc_design(z, groups = c(1, 1, 2))
Least squares with optional linear equality constraints, linear
inequality constraints, and non-negativity – TDA's mls,
mlse, mlsi, mlsei, mlsei1, and
mnls, each as its thin wrapper sharing one
implementation. The problem solved is
These are TDA's documented semantics (tda.hlp, entries
##mls/##mlse/##mlsi/##mlsei/##mnls):
an earlier working note had assumed mlse/mlsi took
their constraint counts, which the source does not support –
tda_mlse and tda_mls turn out to make the identical
call (confirmed empirically: an overdetermined, inconsistent
instance returns the plain least-squares fit rather than an error),
and tda_mlsi treats its entire input as inequality rows.
tda_mlsei and tda_mlsei1 solve the same general
equality+least-squares+inequality problem via two different TDA
algorithms (Lawson-Hanson vs. an undocumented active-set QP,
confirmed to agree to solver tolerance on two independent
instances, not merely assumed from the similar name). tda_mnls
is the only one of the six with non-negativity, applied to every
variable (TDA's k split point fixed at 0) and cannot be
combined with inequalities (mnls has no general
inequality block of its own).
tda_mls(A, b, dir = tempfile("tda"), ...) tda_mlse(A, b, dir = tempfile("tda"), ...) tda_mlsi(inequalities, inequalities_bounds, dir = tempfile("tda"), ...) tda_mlsei( A = NULL, b = NULL, equalities = NULL, equalities_bounds = NULL, inequalities = NULL, inequalities_bounds = NULL, dir = tempfile("tda"), ... ) tda_mlsei1( A = NULL, b = NULL, equalities = NULL, equalities_bounds = NULL, inequalities = NULL, inequalities_bounds = NULL, dir = tempfile("tda"), ... ) tda_mnls( A, b, equalities = NULL, equalities_bounds = NULL, dir = tempfile("tda"), ... )tda_mls(A, b, dir = tempfile("tda"), ...) tda_mlse(A, b, dir = tempfile("tda"), ...) tda_mlsi(inequalities, inequalities_bounds, dir = tempfile("tda"), ...) tda_mlsei( A = NULL, b = NULL, equalities = NULL, equalities_bounds = NULL, inequalities = NULL, inequalities_bounds = NULL, dir = tempfile("tda"), ... ) tda_mlsei1( A = NULL, b = NULL, equalities = NULL, equalities_bounds = NULL, inequalities = NULL, inequalities_bounds = NULL, dir = tempfile("tda"), ... ) tda_mnls( A, b, equalities = NULL, equalities_bounds = NULL, dir = tempfile("tda"), ... )
A |
the least-squares data matrix ( |
b |
the target vector for |
dir |
working directory. |
... |
passed to |
inequalities |
an inequality constraint matrix
|
inequalities_bounds |
the right-hand sides for
|
equalities |
an equality constraint matrix
|
equalities_bounds |
the right-hand sides for |
tda_mls, tda_mlse and tda_mlsi also accept the
manual's single-matrix form,
mls(S, B) with S = [X, y]: when the right-hand
side is not given, the last column of the first argument is
split off as y.
A list: x, the solution; residual, the
Euclidean norm of A %*% x - b (NA when A
is absent), computed directly in R from A, x and
b rather than trusted from TDA's text, since
tda_mlsei1 prints no residual at all; rank, the
reported rank of A (NA for tda_mnls and
tda_mlsei1, neither of which report one).
Other optimization:
tda_boolean_min(),
tda_mlp(),
tda_mlpi(),
tda_mqap(),
tda_mqp()
# unconstrained: fit x1, x2 to two noisy targets tda_mls(diag(2), c(2.1, 2.9)) # the manual's augmented form S = [X, y] works too tda_mls(cbind(diag(2), c(2.1, 2.9))) # x1 + x2 = 3, x1 close to 2, x2 close to 3 tda_mlsei(diag(2), c(2, 3), equalities = rbind(c(1, 1)), equalities_bounds = 3)# unconstrained: fit x1, x2 to two noisy targets tda_mls(diag(2), c(2.1, 2.9)) # the manual's augmented form S = [X, y] works too tda_mls(cbind(diag(2), c(2.1, 2.9))) # x1 + x2 = 3, x1 close to 2, x2 close to 3 tda_mlsei(diag(2), c(2, 3), equalities = rbind(c(1, 1)), equalities_bounds = 3)
tda_mmul multiplies any number of matrices in order
(A1 %*% A2 %*% ... %*% Ak) – TDA's mmul.
tda_mtransp transposes – TDA's mtransp.
tda_mchol returns the lower-triangular Cholesky factor
L such that L %*% t(L) == A (i.e. t(chol(A))
in base R terms; base R's chol returns the upper
factor) – TDA's mchol, requiring a positive-definite
A.
tda_mmul(..., dir = tempfile("tda")) tda_mtransp(A, dir = tempfile("tda")) tda_mchol(A, dir = tempfile("tda"))tda_mmul(..., dir = tempfile("tda")) tda_mtransp(A, dir = tempfile("tda")) tda_mchol(A, dir = tempfile("tda"))
... |
for |
dir |
working directory. |
A |
a numeric matrix. |
A numeric matrix.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
tda_mmul(matrix(1:4, 2), diag(2)) tda_mtransp(matrix(1:6, 2)) tda_mchol(matrix(c(4, 2, 2, 3), 2))tda_mmul(matrix(1:4, 2), diag(2)) tda_mtransp(matrix(1:6, 2)) tda_mchol(matrix(c(4, 2, 2, 3), 2))
Sets A[i,j] to 0 wherever the chosen comparison against
x holds, leaving every other element unchanged – TDA's
mnc (documented in tda.hlp). test chooses the
comparison: "<=", "<", ">=", ">"
(against the raw value), or the same four prefixed "abs"
(against abs(A[i,j])).
tda_mnc( A, x, test = c("<=", "<", ">=", ">", "abs<=", "abs<", "abs>=", "abs>"), dir = tempfile("tda") )tda_mnc( A, x, test = c("<=", "<", ">=", ">", "abs<=", "abs<", "abs>=", "abs>"), dir = tempfile("tda") )
A |
a numeric matrix. |
x |
the threshold. |
test |
which comparison zeroes an element; see above. |
dir |
working directory. |
A numeric matrix.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(1, 5, 3, -2, 4, 6), 2, 3) tda_mnc(A, 3, "<=") # zero out every element <= 3A <- matrix(c(1, 5, 3, -2, 4, 6), 2, 3) tda_mnc(A, 3, "<=") # zero out every element <= 3
Scalar summaries of a matrix – TDA's mnrow, mncol,
mnorm (max absolute element), mnorm1 (sum of
absolute elements), mnorm2 (Frobenius/Euclidean norm,
sqrt(sum(A^2))), and mtrace (sum(diag(A)),
using min(nrow(A), ncol(A)) diagonal elements for a
non-square A, same as base R's sum(diag(A))).
Each returns a plain number, not a 1x1 matrix.
tda_mnrow(A, dir = tempfile("tda")) tda_mncol(A, dir = tempfile("tda")) tda_mnorm(A, dir = tempfile("tda")) tda_mnorm1(A, dir = tempfile("tda")) tda_mnorm2(A, dir = tempfile("tda")) tda_mtrace(A, dir = tempfile("tda"))tda_mnrow(A, dir = tempfile("tda")) tda_mncol(A, dir = tempfile("tda")) tda_mnorm(A, dir = tempfile("tda")) tda_mnorm1(A, dir = tempfile("tda")) tda_mnorm2(A, dir = tempfile("tda")) tda_mtrace(A, dir = tempfile("tda"))
A |
a numeric matrix. |
dir |
working directory. |
A single number.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(2, 1, 4, 5, 3, 8, 9, 7, 1), 3) tda_mnrow(A); tda_mncol(A) tda_mnorm(A); tda_mnorm1(A); tda_mnorm2(A); tda_mtrace(A)A <- matrix(c(2, 1, 4, 5, 3, 8, 9, 7, 1), 3) tda_mnrow(A); tda_mncol(A) tda_mnorm(A); tda_mnorm1(A); tda_mnorm2(A); tda_mtrace(A)
Finds a symmetric permutation that puts a square matrix into
block lower-triangular (tda_mpbl) or block upper-triangular
(tda_mpbu) form (Duff & Reid, CACM 529) – TDA's
mpbl/mpbu. B[i, j] == A[p[i], p[j]] for
every i, j; block
gives, for each row/column of B, which block it belongs to
(blocks numbered in the order B is arranged, so entries
between an earlier and a later block are always zero on the side
tda_mpbl/tda_mpbu promises – confirmed on an
instance with cross-block coupling, not one where every
block trivially has size 1).
tda_mpbl(A, dir = tempfile("tda")) tda_mpbu(A, dir = tempfile("tda"))tda_mpbl(A, dir = tempfile("tda")) tda_mpbu(A, dir = tempfile("tda"))
A |
a square numeric matrix. |
dir |
working directory. |
A list: B, the permuted, block-triangular matrix;
p, the permutation (B == A[p, p]); block,
an integer vector the same length as p giving each
position's block number.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 3, 0, 0, 0, 1), 4, 4) r <- tda_mpbl(A) r$BA <- matrix(c(1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 3, 0, 0, 0, 1), 4, 4) r <- tda_mpbl(A) r$B
Adjusts a table A so its row and column sums match
prescribed targets while preserving cross-product ratios (the
RAS/IPF algorithm) – TDA's mpfit. A must
be non-negative with strictly positive row and column sums, as
must the target row_sums/col_sums, and their totals
should agree (TDA warns but does not refuse otherwise).
tda_mpfit( A, row_sums, col_sums, max_iter = 100, eps = 1e-06, dir = tempfile("tda") )tda_mpfit( A, row_sums, col_sums, max_iter = 100, eps = 1e-06, dir = tempfile("tda") )
A |
a non-negative numeric matrix (n x m). |
row_sums |
target row sums, length n. |
col_sums |
target column sums, length m. |
max_iter |
maximum number of iterations. |
eps |
convergence tolerance on the maximum deviation between the fitted and target sums. |
dir |
working directory. |
A list: B, the fitted table; iterations, how
many were used; accuracy, the final deviation reached.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
tda_mpfit(matrix(c(10, 20, 30, 40), 2, 2, byrow = TRUE), row_sums = c(45, 55), col_sums = c(40, 60))tda_mpfit(matrix(c(10, 20, 30, 40), 2, 2, byrow = TRUE), row_sums = c(45, 55), col_sums = c(40, 60))
TDA's mpinv: given a permutation p of 1:n,
returns q such that q[p[i]] == i – matching base
R's order(p).
tda_mpinv(p, dir = tempfile("tda"))tda_mpinv(p, dir = tempfile("tda"))
p |
an integer permutation of |
dir |
working directory. |
An integer vector, the inverse permutation.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
tda_mpinv(c(3, 1, 4, 2)) # == order(c(3, 1, 4, 2))tda_mpinv(c(3, 1, 4, 2)) # == order(c(3, 1, 4, 2))
Projects an age-structured population forward using a Leslie
matrix – TDA's mpit/mpit1. Row i of
fertility_survival holds (fertility[i], survival[i]):
fertility[i] is the birth rate contributed by age class
i (used only for class 1 of the next generation);
survival[i] is the fraction of age class i that
survives into age class i + 1 (survival[n], the
last row, is unused). tda_mpit1 adds a constant vector
immigration to every age class after each projection step.
tda_mpit(fertility_survival, population, iterations, dir = tempfile("tda")) tda_mpit1( fertility_survival, population, immigration, iterations, dir = tempfile("tda") )tda_mpit(fertility_survival, population, iterations, dir = tempfile("tda")) tda_mpit1( fertility_survival, population, immigration, iterations, dir = tempfile("tda") )
fertility_survival |
an n x 2 numeric matrix, columns
|
population |
the initial population vector, length n. |
iterations |
how many projection steps to take. |
dir |
working directory. |
immigration |
for |
A matrix with iterations + 1 rows (the initial
population, then one row per step) and n columns.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
F <- rbind(c(0, 0), c(2, 0.5), c(1, 0.3)) tda_mpit(F, c(100, 50, 20), iterations = 3)F <- rbind(c(0, 0), c(2, 0.5), c(1, 0.3)) tda_mpit(F, c(100, 50, 20), iterations = 3)
The product-limit (Kaplan-Meier) estimate of the CDF for a vector
of possibly right-censored event times – TDA's mple, via
Efron's redistribute-to-the-right algorithm, applied one
observation at a time in sorted order (events before censoring at
the same time). When no two events fall at exactly the same time,
this matches the standard product-limit CDF exactly – confirmed
against survival::survfit across random instances (events
may still tie with a censored observation; only ties among
events are excluded). When two or more events tie,
processing them one at a time rather than as a single simultaneous
risk-set reduction means only the last observation
processed within that tied group reaches the value standard
Kaplan-Meier software reports for that time – earlier ones in the
same group show smaller, order-dependent intermediate values.
Two events tied at time = 2 out of 3
total observations give F = (1/3, 2/3, 1) here, where
standard Kaplan-Meier reports F(2) = 2/3 for both tied
observations. This is a property of the algorithm as TDA
implements it, not a bug and not this wrapper's choice to make.
Separately: F always reaches exactly 1 at the
highest-time observation, even when that observation is
censored – redistribution only moves probability mass to later
observations, never destroys it, and the highest-time observation
has nothing later to redistribute its share to, so all of the
mass ends up accounted for there by construction. Standard
Kaplan-Meier software instead leaves the survival curve at
whatever value it last reached, undefined beyond a censored tail.
time = c(1, 2, 3),
censored = c(0, 0, 1) gives F = (1/3, 2/3, 1) here.
This is the low-level building block behind TDA's
tda_ple, which most users want instead – this one
works directly on plain vectors, with no grouping, formula
interface, or standard errors.
tda_mple(time, censored, dir = tempfile("tda"))tda_mple(time, censored, dir = tempfile("tda"))
time |
a numeric vector of event/censoring times. |
censored |
a numeric vector the same length as |
dir |
working directory. |
A list, both the same length as time, in the
original (unsorted) order: F, the estimated CDF at each
observation; jumps, the increase in F at each
observation (0 for a censored observation).
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
# six durations, two of them censored (still running at 3 and 7) t <- c(2, 3, 3, 5, 7, 8) cen <- c(0, 0, 1, 0, 1, 0) pl <- tda_mple(t, cen) pl$F # the Kaplan-Meier distribution function at each observation pl$jumps # its increase there; 0 at the censored ones# six durations, two of them censored (still running at 3 and 7) t <- c(2, 3, 3, 5, 7, 8) cen <- c(0, 0, 1, 0, 1, 0) pl <- tda_mple(t, cen) pl$F # the Kaplan-Meier distribution function at each observation pl$jumps # its increase there; 0 at the censored ones
TDA's mproc: rotates configuration Y to best match X.
Verified in the suite against the closed-form solution from the
singular value decomposition.
tda_mproc(x, y, ...)tda_mproc(x, y, ...)
x, y
|
n-by-m matrices. |
... |
passed to |
the rotated configuration as a matrix.
x <- cbind(c(0, 1, 0), c(0, 0, 1)) th <- 0.7; R <- rbind(c(cos(th), -sin(th)), c(sin(th), cos(th))) round(tda_mproc(x, x %*% R), 6)x <- cbind(c(0, 1, 0), c(0, 0, 1)) th <- 0.7; R <- rbind(c(cos(th), -sin(th)), c(sin(th), cos(th))) round(tda_mproc(x, x %*% R), 6)
Finds a row permutation that gives a square matrix a zero-free
diagonal wherever one exists (Duff's algorithm, ACM 575) – TDA's
mpz. p satisfies A[p[i], i] != 0 for every
i (the exact contract m_rperm's header states),
and B is built as the gather B[i, ] == A[p[i], ], so
diag(B)[i] == A[p[i], i] by construction. An earlier version
of TDA's C code built B as the opposite (a scatter,
B[p[i], ] == A[i, ]) despite p itself already
satisfying the gather contract – confirmed wrong on a 3x3 matrix
with a unique, forced perfect matching (a pure permutation matrix,
one nonzero per row and column): the scatter form returned an
all-zero diagonal even though TDA's diagnostic confirmed a
complete matching was found. Fixed at the source
(m_mpz, t_matc.c), not worked around here.
If A is structurally singular, some diagonal entries of
B may still be zero – check all(diag(B) != 0) if
that matters, rather than assuming a full match always exists.
tda_mpz(A, dir = tempfile("tda"))tda_mpz(A, dir = tempfile("tda"))
A |
a square numeric matrix. |
dir |
working directory. |
A list: B, the permuted matrix; p, the
permutation, with A[p[i], i] != 0 for every i
where that is achievable.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(0, 3, 0, 1, 0, 5, 2, 4, 0), 3, 3) r <- tda_mpz(A) r$p all(diag(r$B) != 0)A <- matrix(c(0, 3, 0, 1, 0, 5, 2, 4, 0), 3, 3) r <- tda_mpz(A) r$p all(diag(r$B) != 0)
Approximate solution of the quadratic assignment problem – TDA's
mqap, adapted from CACM algorithm 608 (D.H. West). Tries to
find a permutation p of 1:n minimizing
This is a heuristic, not an exact solver: the value returned is an
upper bound on the true minimum, and need not be optimal for larger
n (see examples/coverage/mqapops.cf for the objective
and small hand-verified instances). flows and distances
must have a zero main diagonal; a nonzero diagonal is silently reset
to zero with a warning from TDA itself.
tda_mqap(flows, distances, costs = NULL, dir = tempfile("tda"), ...)tda_mqap(flows, distances, costs = NULL, dir = tempfile("tda"), ...)
flows |
the flow matrix |
distances |
the distance matrix |
costs |
the fixed placement cost matrix |
dir |
working directory. |
... |
passed to |
A list: value, the objective at the returned
permutation; permutation, integer vector p with
p[i] the location assigned to facility i.
Other optimization:
tda_boolean_min(),
tda_mlp(),
tda_mlpi(),
tda_mls(),
tda_mqp()
F <- matrix(c(0,5,2,4, 5,0,3,0, 2,3,0,0, 4,0,0,0), 4, 4, byrow = TRUE) D <- matrix(c(0,8,15,13, 8,0,9,10, 15,9,0,17, 13,10,17,0), 4, 4, byrow = TRUE) tda_mqap(F, D)F <- matrix(c(0,5,2,4, 5,0,3,0, 2,3,0,0, 4,0,0,0), 4, 4, byrow = TRUE) D <- matrix(c(0,8,15,13, 8,0,9,10, 15,9,0,17, 13,10,17,0), 4, 4, byrow = TRUE) tda_mqap(F, D)
Minimize a convex quadratic subject to box bounds and/or linear
equality/inequality constraints – TDA's mqp, mqpb,
and mqpc (undocumented in tda.hlp; identified from
qld's header, the Powell/Schittkowski active-set solver
ZQPCVX shared with tda_mlsei1). The problem
solved is
tda_mqp is unconstrained (box bounds fixed at +-huge
internally by TDA); tda_mqpb adds box bounds; tda_mqpc
adds general equality/inequality constraints instead of bounds –
no single TDA command accepts both bounds and general constraints.
The suite checks all three commands against hand-solved instances: an
unconstrained case, a box-clipped case, and a mixed
equality+inequality case – see examples/coverage/mqpops2.cf.
tda_mqp(C, d, dir = tempfile("tda"), ...) tda_mqpb(C, d, lower, upper, dir = tempfile("tda"), ...) tda_mqpc( C, d, equalities = NULL, equalities_bounds = NULL, inequalities = NULL, inequalities_bounds = NULL, dir = tempfile("tda"), ... )tda_mqp(C, d, dir = tempfile("tda"), ...) tda_mqpb(C, d, lower, upper, dir = tempfile("tda"), ...) tda_mqpc( C, d, equalities = NULL, equalities_bounds = NULL, inequalities = NULL, inequalities_bounds = NULL, dir = tempfile("tda"), ... )
C |
the symmetric objective matrix (n x n). |
d |
the linear objective term, length n. |
dir |
working directory. |
... |
passed to |
lower, upper
|
box bounds, each length n. |
equalities |
an equality constraint matrix
|
equalities_bounds |
the right-hand sides for |
inequalities |
an inequality constraint matrix
|
inequalities_bounds |
the right-hand sides for
|
A list: x, the solution; value, the objective
d'x + 0.5 x'Cx at x, computed directly in R since
this command family prints no value of its own.
Other optimization:
tda_boolean_min(),
tda_mlp(),
tda_mlpi(),
tda_mls(),
tda_mqap()
# minimize x1^2 + x2^2 - 2x1 - 4x2 (unconstrained optimum (1, 2)) tda_mqp(diag(c(2, 2)), c(-2, -4)) tda_mqpb(diag(c(2, 2)), c(-2, -4), lower = c(0, 0), upper = c(0.5, 0.5))# minimize x1^2 + x2^2 - 2x1 - 4x2 (unconstrained optimum (1, 2)) tda_mqp(diag(c(2, 2)), c(-2, -4)) tda_mqpb(diag(c(2, 2)), c(-2, -4), lower = c(0, 0), upper = c(0.5, 0.5))
Rather than assume the response is already on an interval scale,
mreg finds the monotone rescaling of it that fits a linear model
best – Kruskal's non-metric approach, the same idea non-metric MDS uses.
It reports a coefficient table but no standard errors: mreg does
not compute them (no pcov= in its own TDA implementation), so
vcov() and confint() are always NA here, honestly
reflecting what TDA itself reports rather than a parsing gap.
tda_mreg( formula, data, ties = c("ignore", "primary", "secondary"), control = NULL, options = list(), dir = tempfile("tda"), ... )tda_mreg( formula, data, ties = c("ignore", "primary", "secondary"), control = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a two-sided formula. |
data |
a data frame. |
ties |
how to handle tied response values: |
control |
convergence settings from |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
predict() (and fitted(), its default with no
newdata) is well defined here – the coefficients describe a
linear model, just of the rescaled response rather than the
original one – but the numbers it returns are on that rescaled
(“disparity”) scale, not the original response's units or
levels. This is the same idea as predict.glm(type = "link")
returning the linear predictor rather than a probability.
An object of class tda_fit.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_freg(),
tda_gdf(),
tda_l1reg(),
tda_lsreg(),
tda_mlrc_design(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
set.seed(52) d <- data.frame(x = round(rnorm(50), 2)) # y is an ordinal rank (1-5), not an interval scale, driven by a linear # score plus noise -- exactly the case mreg is meant for score <- 1 + 2 * d$x + rnorm(50, sd = 0.4) d$y <- as.integer(cut(score, quantile(score, seq(0, 1, 0.2)), include.lowest = TRUE)) fit <- tda_mreg(y ~ x, d) coef(fit) # y is heavily tied by construction (5 ordinal ranks) -- ties= selects # how mreg's algorithm resolves that; see Details for a directly # verified case where it changes the fit's stress coef(tda_mreg(y ~ x, d, ties = "secondary")) # fitted values, on the rescaled response -- not the original 1-5 scale, # but increasing with x the way the underlying score was predict(fit) predict(fit, newdata = data.frame(x = c(-1, 0, 1)))set.seed(52) d <- data.frame(x = round(rnorm(50), 2)) # y is an ordinal rank (1-5), not an interval scale, driven by a linear # score plus noise -- exactly the case mreg is meant for score <- 1 + 2 * d$x + rnorm(50, sd = 0.4) d$y <- as.integer(cut(score, quantile(score, seq(0, 1, 0.2)), include.lowest = TRUE)) fit <- tda_mreg(y ~ x, d) coef(fit) # y is heavily tied by construction (5 ordinal ranks) -- ties= selects # how mreg's algorithm resolves that; see Details for a directly # verified case where it changes the fit's stress coef(tda_mreg(y ~ x, d, ties = "secondary")) # fitted values, on the rescaled response -- not the original 1-5 scale, # but increasing with x the way the underlying score was predict(fit) predict(fit, newdata = data.frame(x = c(-1, 0, 1)))
tda_mrsum/tda_mcsum are TDA's mrsum/
mcsum, matching base R's rowSums/colSums.
tda_mdrow/tda_mdcol return the same sums as a
diagonal matrix instead of a vector – TDA's mdrow/
mdcol, matching diag(rowSums(A))/
diag(colSums(A)); useful for building a graph's degree
matrix from its adjacency matrix.
tda_mrsum(A, dir = tempfile("tda")) tda_mcsum(A, dir = tempfile("tda")) tda_mdrow(A, dir = tempfile("tda")) tda_mdcol(A, dir = tempfile("tda"))tda_mrsum(A, dir = tempfile("tda")) tda_mcsum(A, dir = tempfile("tda")) tda_mdrow(A, dir = tempfile("tda")) tda_mdcol(A, dir = tempfile("tda"))
A |
a numeric matrix. |
dir |
working directory. |
tda_mrsum/tda_mcsum return a plain numeric
vector; tda_mdrow/tda_mdcol return a diagonal
matrix.
Other matrix reshaping:
tda_mag(),
tda_mcath(),
tda_mcvec(),
tda_msort(),
tda_msrow(),
tda_mtrim()
A <- matrix(1:6, 2, 3) tda_mrsum(A); tda_mcsum(A) tda_mdrow(A); tda_mdcol(A)A <- matrix(1:6, 2, 3) tda_mrsum(A); tda_mcsum(A) tda_mdrow(A); tda_mdcol(A)
Divides every element of A by the sum of all its
elements – TDA's mscal1, matching A / sum(A).
tda_mscal1(A, dir = tempfile("tda"))tda_mscal1(A, dir = tempfile("tda"))
A |
a numeric matrix whose elements do not sum to zero. |
dir |
working directory. |
A numeric matrix.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_msqrtd(),
tda_msvd(),
tda_mwvec()
A <- matrix(c(1, 2, 3, 4), 2) tda_mscal1(A) # A / sum(A): the cells now sum to oneA <- matrix(c(1, 2, 3, 4), 2) tda_mscal1(A) # A / sum(A): the cells now sum to one
tda_msort sorts the rows of X ascending by the
columns named in by, first column first – TDA's
msort, matching
X[do.call(order, as.data.frame(X[, by])), ].
tda_msort1 does the same and then drops consecutive
duplicate rows (comparing every column, not just by) –
TDA's msort1, matching unique(sorted_X).
tda_mrank – despite the name – is not a
linear-algebra matrix rank (no TDA command returns one as a
matrix value; tda_mginv prints a pseudorank as a
side effect, but never returns it). It returns the sort
permutation itself: an integer vector p such that
X[p, ] is sorted by by – TDA's mrank,
which equals base R's
order(X[, by[1]], X[, by[2]], ...), not rank().
tda_msort(X, by, dir = tempfile("tda")) tda_msort1(X, by, dir = tempfile("tda")) tda_mrank(X, by, dir = tempfile("tda"))tda_msort(X, by, dir = tempfile("tda")) tda_msort1(X, by, dir = tempfile("tda")) tda_mrank(X, by, dir = tempfile("tda"))
X |
a numeric matrix. |
by |
which columns to sort by, in order (1-based, at least one). |
dir |
working directory. |
tda_msort/tda_msort1 return a matrix;
tda_mrank returns an integer vector, the same length as
nrow(X).
Other matrix reshaping:
tda_mag(),
tda_mcath(),
tda_mcvec(),
tda_mrsum(),
tda_msrow(),
tda_mtrim()
X <- rbind(c(30, 1), c(10, 1), c(20, 1), c(40, 1)) tda_msort(X, 1) tda_mrank(X, 1) # == order(X[, 1]), i.e. c(2, 3, 1, 4)X <- rbind(c(30, 1), c(10, 1), c(20, 1), c(40, 1)) tda_msort(X, 1) tda_mrank(X, 1) # == order(X[, 1]), i.e. c(2, 3, 1, 4)
Given a square matrix A, returns a diagonal matrix (zero
off-diagonal) built from its diagonal – TDA's msqrtd
(diag(sqrt(diag(A))); refuses a negative diagonal element)
and msqrti (diag(1/sqrt(diag(A))); refuses an
(almost) zero diagonal element). Off-diagonal entries of A
are ignored entirely, same as tda_minvd.
tda_msqrtd(A, dir = tempfile("tda")) tda_msqrti(A, dir = tempfile("tda"))tda_msqrtd(A, dir = tempfile("tda")) tda_msqrti(A, dir = tempfile("tda"))
A |
a square numeric matrix. |
dir |
working directory. |
A diagonal numeric matrix.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msvd(),
tda_mwvec()
tda_msqrtd(matrix(c(4, 1, 1, 9), 2)) # diag(2, 3) tda_msqrti(matrix(c(4, 1, 1, 9), 2)) # diag(0.5, 1/3)tda_msqrtd(matrix(c(4, 1, 1, 9), 2)) # diag(2, 3) tda_msqrti(matrix(c(4, 1, 1, 9), 2)) # diag(0.5, 1/3)
tda_msrow/tda_mscol select (and may reorder or
repeat) rows/columns by index – TDA's msrow/mscol,
matching X[rows, ]/X[, cols]. tda_mprow/
tda_mpcol/tda_mpsym permute rows, columns, or both
by the same permutation – TDA's mprow/mpcol/
mpsym, matching A[p, ]/A[, p]/A[p, p]
(m_mperm's header states the convention,
b(i,j)=a(p(i),j) etc.).
mprow/mpcol require a permutation of
1:nrow(A)/1:ncol(A), so unlike msrow/
mscol they cannot repeat or drop indices; mpsym
additionally requires A to be square.
tda_msrow(X, rows, dir = tempfile("tda")) tda_mscol(X, cols, dir = tempfile("tda")) tda_mprow(A, p, dir = tempfile("tda")) tda_mpcol(A, p, dir = tempfile("tda")) tda_mpsym(A, p, dir = tempfile("tda"))tda_msrow(X, rows, dir = tempfile("tda")) tda_mscol(X, cols, dir = tempfile("tda")) tda_mprow(A, p, dir = tempfile("tda")) tda_mpcol(A, p, dir = tempfile("tda")) tda_mpsym(A, p, dir = tempfile("tda"))
X, A
|
a numeric matrix. |
rows, cols
|
integer indices (1-based; |
dir |
working directory. |
p |
an integer permutation of |
A numeric matrix.
Other matrix reshaping:
tda_mag(),
tda_mcath(),
tda_mcvec(),
tda_mrsum(),
tda_msort(),
tda_mtrim()
A <- matrix(1:9, 3, 3) tda_msrow(A, c(2, 1)) # == A[c(2, 1), ] tda_mprow(A, c(2, 3, 1)) # == A[c(2, 3, 1), ] tda_mpsym(A, c(2, 3, 1)) # == A[c(2, 3, 1), c(2, 3, 1)]A <- matrix(1:9, 3, 3) tda_msrow(A, c(2, 1)) # == A[c(2, 1), ] tda_mprow(A, c(2, 3, 1)) # == A[c(2, 3, 1), ] tda_mpsym(A, c(2, 3, 1)) # == A[c(2, 3, 1), c(2, 3, 1)]
tda_msvd returns just the singular values – TDA's
msvd. tda_msvd1 returns the full decomposition
A = U %*% diag(d) %*% t(V) – TDA's msvd1,
matching base R's svd() convention exactly (singular
vectors as columns of u/v). A must have at
least as many rows as columns for either. As with any singular
vector, each column's sign is arbitrary and need not match
svd()'s choice.
tda_msvd(A, dir = tempfile("tda")) tda_msvd1(A, dir = tempfile("tda"))tda_msvd(A, dir = tempfile("tda")) tda_msvd1(A, dir = tempfile("tda"))
A |
a numeric matrix with at least as many rows as columns. |
dir |
working directory. |
tda_msvd returns a plain numeric vector of
singular values. tda_msvd1 returns a list: d, the
singular values; u, v, the singular vectors as
columns.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_mwvec()
A <- matrix(c(1, 3, 5, 2, 4, 7), 3, 2) tda_msvd(A) # == svd(A)$d tda_msvd1(A) # == svd(A), up to per-column signA <- matrix(c(1, 3, 5, 2, 4, 7), 3, 2) tda_msvd(A) # == svd(A)$d tda_msvd1(A) # == svd(A), up to per-column sign
Deletes or adds whole rows/columns at the edges of A –
TDA's mtrim. A positive count deletes that many rows or
columns from that edge; a negative count adds that many zero
rows/columns instead. leading_cols/trailing_cols
act on the first and last columns, leading_rows/
trailing_rows on the first and last rows.
tda_mtrim( A, leading_cols = 0, leading_rows = 0, trailing_cols = 0, trailing_rows = 0, dir = tempfile("tda") )tda_mtrim( A, leading_cols = 0, leading_rows = 0, trailing_cols = 0, trailing_rows = 0, dir = tempfile("tda") )
A |
a numeric matrix. |
leading_cols, trailing_cols, leading_rows, trailing_rows
|
integer counts (default 0); positive deletes, negative pads with zeros. |
dir |
working directory. |
A numeric matrix.
Other matrix reshaping:
tda_mag(),
tda_mcath(),
tda_mcvec(),
tda_mrsum(),
tda_msort(),
tda_msrow()
A <- matrix(1:4, 2) tda_mtrim(A, leading_cols = 1) # drop the first column tda_mtrim(A, leading_cols = -1) # add a zero column in frontA <- matrix(1:4, 2) tda_mtrim(A, leading_cols = 1) # drop the first column tda_mtrim(A, leading_cols = -1) # add a zero column in front
For each position i, averages a[j] weighted by
weights[j] over every later position (tda_mwvec:
every j > i; tda_mwvec1: every j with
t[j] > t[i], letting an arbitrary order vector t
stand in for position – tda_mwvec is the special case
t = seq_along(a)) – TDA's mwvec/mwvec1.
Falls back to a[i] unchanged wherever the weights beyond
i sum to zero (including the last position, which always
has nothing after it). No base-R builtin matches this directly.
tda_mwvec(a, weights, dir = tempfile("tda")) tda_mwvec1(a, weights, t, dir = tempfile("tda"))tda_mwvec(a, weights, dir = tempfile("tda")) tda_mwvec1(a, weights, t, dir = tempfile("tda"))
a, weights
|
numeric vectors of the same length. |
dir |
working directory. |
t |
for |
A numeric vector, the same length as a.
Other matrix algebra:
tda_mcel(),
tda_mcent(),
tda_mch(),
tda_mcross(),
tda_mdiag(),
tda_mev(),
tda_mevs(),
tda_midf(),
tda_midf1(),
tda_midf2(),
tda_midf3(),
tda_minvs(),
tda_mkmet(),
tda_mkp(),
tda_mmul(),
tda_mnc(),
tda_mnrow(),
tda_mpbl(),
tda_mpfit(),
tda_mpinv(),
tda_mpit(),
tda_mple(),
tda_mpz(),
tda_mscal1(),
tda_msqrtd(),
tda_msvd()
a <- c(10, 20, 30, 40) w <- c(1, 1, 1, 1) # position 1 averages 20, 30, 40; position 3 averages 40 alone; # the last position has nothing after it and keeps its own value tda_mwvec(a, w) # with an order vector, "later" means a larger t: positions 1 and 2 # share t = 1, so both average the values at t = 2 and t = 3 tda_mwvec1(a, w, t = c(1, 1, 2, 3))a <- c(10, 20, 30, 40) w <- c(1, 1, 1, 1) # position 1 averages 20, 30, 40; position 3 averages 40 alone; # the last position has nothing after it and keeps its own value tda_mwvec(a, w) # with an order vector, "later" means a larger t: positions 1 and 2 # share t = 1, so both average the values at t = 2 and t = 3 tda_mwvec1(a, w, t = c(1, 1, 2, 3))
TDA's ndvar: expands variables into dummies. Verified in
the suite against model.matrix.
tda_ndvar(data, ...)tda_ndvar(data, ...)
data |
data frame of integer-valued variables. |
... |
passed to |
the printed output describing the created dummies.
# one dummy per observed level of edu, named edu_1, edu_2, edu_3 tda_ndvar(data.frame(edu = c(1, 2, 3, 2, 1)))# one dummy per observed level of edu, named edu_1, edu_2, edu_3 tda_ndvar(data.frame(edu = c(1, 2, 3, 2, 1)))
TDA's niset: sets tolerance and subdivision options used by
the int operator within the same run; exposed for pipeline
use.
tda_niset(rel_error = 1e-04, method = 1, commands = character(), ...)tda_niset(rel_error = 1e-04, method = 1, commands = character(), ...)
rel_error |
relative error target for the integrator. |
method |
integration algorithm 1-5 (TDA's rhs of
|
commands |
further command lines to run under the setting. |
... |
passed to |
the printed output, invisibly.
out <- tda_niset(rel_error = 1e-6, commands = "int(ab=0,1, fmt=12.8) = sin(x);") grep("Approximation", out, value = TRUE) # 1 - cos(1)out <- tda_niset(rel_error = 1e-6, commands = "int(ab=0,1, fmt=12.8) = sin(x);") grep("Approximation", out, value = TRUE) # 1 - cos(1)
tda_npreg is a non-parametric regression evaluated at points you
choose: TDA's npreg, a kernel-smoothed mean, quantile or
frequency.
tda_npreg( formula, data, x, method = c("mean", "quantile", "frequency", "lowess", "midmeans"), kernel = c("uniform", "triangle", "quartic", "epanechnikov"), bandwidth = NULL, select = NULL, options = list(), dir = tempfile("tda"), ... )tda_npreg( formula, data, x, method = c("mean", "quantile", "frequency", "lowess", "midmeans"), kernel = c("uniform", "triangle", "quartic", "epanechnikov"), bandwidth = NULL, select = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a two-sided formula. |
data |
a data frame. |
x |
for |
method |
see Details; |
kernel |
the smoothing kernel, only meaningful for
|
bandwidth |
the kernel bandwidth ( |
select |
a case-selection expression, TDA's |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
method picks which: "mean" (the default), a
kernel-smoothed mean at each point in x; "quantile",
smoothed quantiles; "frequency", smoothed frequencies. Only
these three exist. npreg names the columns for
method "mean"
and "quantile", which tda_npreg reproduces;
"frequency" writes columns that depend on the data (the
distinct response categories) and are returned as TDA numbered them,
V1, V2, ...
An object carrying the fitted values as table.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_freg(),
tda_gdf(),
tda_l1reg(),
tda_lsreg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_zreg()
set.seed(19) d <- data.frame(x = round(rnorm(60), 3)) d$y <- round(1 + sin(d$x) + rnorm(60, sd = 0.2), 3) np <- tda_npreg(y ~ x, d, x = seq(-2, 2, 0.5)) np$table # a triangle kernel, wider bandwidth np2 <- tda_npreg(y ~ x, d, x = seq(-2, 2, 0.5), kernel = "triangle", bandwidth = 0.5) np2$tableset.seed(19) d <- data.frame(x = round(rnorm(60), 3)) d$y <- round(1 + sin(d$x) + rnorm(60, sd = 0.2), 3) np <- tda_npreg(y ~ x, d, x = seq(-2, 2, 0.5)) np$table # a triangle kernel, wider bandwidth np2 <- tda_npreg(y ~ x, d, x = seq(-2, 2, 0.5), kernel = "triangle", bandwidth = 0.5) np2$table
Most wrappers accept an options = list(...) argument that is
passed straight through to the TDA command they build. TDA has
several hundred options and promoting each to a named R argument
would be unreadable, so the named arguments cover what is needed in
ordinary use and options= reaches the rest.
TDA's manual is installed with the package and is the
authoritative list. tda_help prints the section for any
command, including its full option table:
tda_help("rate") # every option the rate command takes
tda_help("sdgshhs") # the GSHHS reader's options
The name in options= is TDA's name, exactly as that table
spells it, so options = list(grp = "SEX") becomes
grp = SEX, in the generated command.
Where a wrapper has both, options= goes to the TDA
command and ... goes to tda_run (working
directory, echo, and so on). Passing a TDA option in ... is
therefore an error rather than a silent no-op:
tda_rate(..., grp = "SEX") # unused argument tda_rate(..., options = list(grp = "SEX")) # reaches the command
A few readers – tda_read_gshhs and the other spatial
readers among them – have no separate options= and forward
... into the command directly, so for those
tda_read_gshhs(f, opt = 2) is right.
An option reaching the command is not the same as the option
working. TDA validates its parameters and some are only
meaningful for particular models: grp= on rate, for
instance, reaches the command and is accepted, but the fit then
returns nothing unless the model is one of the stratified ones.
Check the run's output when an option seems to have no effect.
# what does the GSHHS reader accept? tda_help("sdgshhs") # opt = 2 keeps longitudes on 0..360, which stops dateline-crossing # polygons being drawn straight across a world map ## Not run: tda_read_gshhs("gshhs_i.b", opt = 2, level = 1) ## End(Not run)# what does the GSHHS reader accept? tda_help("sdgshhs") # opt = 2 keeps longitudes on 0..360, which stops dateline-crossing # polygons being drawn straight across a world map ## Not run: tda_read_gshhs("gshhs_i.b", opt = 2, level = 1) ## End(Not run)
tda_estimates returns the coefficient table, reading the column
layout from TDA's header so that it works for the rate models
(SN/Org/Des/MT), qreg (Cat/Term) and fml (Parameter/Value)
alike. A parameter TDA held fixed, printed as ---, comes back
NA. tda_output prints everything TDA wrote.
tda_output(x) tda_estimates(x)tda_output(x) tda_estimates(x)
x |
a run or fitted model. |
A data frame, a list of data frames, or NULL.
Other TDA infrastructure:
tda_ccnt(),
tda_help(),
tda_read_table(),
tda_run(),
tda_write_data()
set.seed(38) d <- data.frame(x = rnorm(100)) d$y <- rbinom(100, 1, plogis(0.2 + 0.7 * d$x)) f <- tda_qreg(y ~ x, d) tda_estimates(f) tda_output(f) # everything TDA printed, not just the coefficient tableset.seed(38) d <- data.frame(x = rnorm(100)) d$y <- rbinom(100, 1, plogis(0.2 + 0.7 * d$x)) f <- tda_qreg(y ~ x, d) tda_estimates(f) tda_output(f) # everything TDA printed, not just the coefficient table
Classifies each line of output as blank, boilerplate, an echo
of the inputs, an optimiser-settings line, content the fitted object
stores, content also delivered through the direct-export channel, or
unaccounted. The last category is the point: it lists what
would be lost if the printed output were ever discarded, and the
package's tests require it to be empty for a corpus of fits.
tda_output_audit(x)tda_output_audit(x)
x |
a |
a data frame with columns line and class, one
row per output line, with a summary attribute counting each
class.
d <- data.frame(x = 1:8, y = (1:8) * 2 + rnorm(8)) f <- tda_lsreg(y ~ x, d) a <- tda_output_audit(f) attr(a, "summary") subset(a, class == "UNACCOUNTED")d <- data.frame(x = 1:8, y = (1:8) * 2 + rnorm(8)) f <- tda_lsreg(y ~ x, d) a <- tda_output_audit(f) attr(a, "summary") subset(a, class == "UNACCOUNTED")
TDA's protocol is structured: a header, then each command's echo
followed by its result, with separator lines between commands.
tda_payload returns the result section of the last command
(or the n-th from the end), without the surrounding
protocol, which is what an example or a quick look usually wants.
tda_payload(output, n = 1L)tda_payload(output, n = 1L)
output |
a character vector of protocol lines, or a
|
n |
which command's section, counted from the end; default 1, the last command. |
the lines of that section, invisibly empty if the output has no separator structure.
r <- tda_run("int(ab=0,1, fmt=12.8) = x*x;") cat(tda_payload(r), sep = "\n") # the integral, 1/3r <- tda_run("int(ab=0,1, fmt=12.8) = x*x;") cat(tda_payload(r), sep = "\n") # the integral, 1/3
TDA's pcyc: each record of the given integer variables is a
permutation; the command reports its cycle decomposition. Verified
in the suite against a direct R cycle count.
tda_pcyc(perm, ...)tda_pcyc(perm, ...)
perm |
a matrix or data frame, one permutation per row. |
... |
passed to |
the output file's lines (one cycle report per record).
# each row is a permutation of 1..4, written as where each element # goes; the last column of the output is its cycle decomposition tda_pcyc(rbind(c(2, 3, 1, 4), # (1,2,3)(4) c(1, 2, 3, 4), # the identity, four fixed points c(2, 1, 4, 3))) # (1,2)(3,4)# each row is a permutation of 1..4, written as where each element # goes; the last column of the output is its cycle decomposition tda_pcyc(rbind(c(2, 3, 1, 4), # (1,2,3)(4) c(1, 2, 3, 4), # the identity, four fixed points c(2, 1, 4, 3))) # (1,2)(3,4)
pdatd: builds a case-by-case distance matrix directly from a
data matrix, the way dist does – Euclidean or
city-block distance, the count of variables on which two cases differ,
or a dissimilarity index. The result feeds directly into
tda_cluster or tda_mds. Verified against
dist for Euclidean and city-block (Manhattan)
distance: exact match.
tda_pdatd( data, measure = 1, variables = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... )tda_pdatd( data, measure = 1, variables = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... )
data |
a data frame or matrix, one row per case. |
measure |
the distance measure: |
variables |
optional subset of |
weights |
optional positive per-variable weights, one per (selected) variable, all distinct – see Details for TDA's parser constraint and the exact weighting convention. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
As with tda_dma, TDA's v= needs variable names
that start uppercase to be referenced correctly; variables
handles this automatically.
Per-variable weights work through weights, with one genuine
TDA quirk absorbed for you: wt= is parsed by TDA's
time-points parser, which accepts only a strictly increasing
positive list – wt=2,1,1 is a syntax error while
wt=1,2,4 is fine, which is why this option long looked dead.
Since a distance does not care about variable order, the wrapper
sends the variables sorted by ascending weight. The weighting
convention, verified against R directly: euclidean uses
(so it matches
dist(sweep(x, 2, sqrt(w), "*"))), city-block
. Tied weights cannot pass
TDA's parser at all; scale those columns yourself
( for euclidean, for city-block) and
call this unweighted – the result is identical.
A dist object.
Other clustering:
TDA_CLUSTER,
TDA_MDS,
tda_conjoint(),
tda_cutree(),
tda_dma()
set.seed(1) d <- data.frame(x1 = rnorm(5), x2 = rnorm(5)) tda_pdatd(d) tda_pdatd(d, measure = 2) # city-block, not the euclidean default tda_pdatd(d, variables = "x1") # a subset of the variablesset.seed(1) d <- data.frame(x1 = rnorm(5), x2 = rnorm(5)) tda_pdatd(d) tda_pdatd(d, measure = 2) # city-block, not the euclidean default tda_pdatd(d, variables = "x1") # a subset of the variables
TDA's pdatr: writes the kept variables for every ordered
pair of cases.
tda_pdatr(data, keep = names(data), ...)tda_pdatr(data, keep = names(data), ...)
data |
data frame. |
keep |
variables to keep (all by default). |
... |
passed to |
a data frame with one row per ordered pair of cases: the
case numbers i and j, then the kept variables of
case i (suffix .i) and of case j (suffix
.j).
# every ordered pair of cases, with x for both members of the pair tda_pdatr(data.frame(id = 1:3, x = c(10, 20, 30)), keep = "x")# every ordered pair of cases, with x for both members of the pair tda_pdatr(data.frame(id = 1:3, x = c(10, 20, 30)), keep = "x")
tda_pl reaches any of TDA's thirty-seven plot commands. The named
functions are the common ones and only spell out their arguments; anything
without a named wrapper goes through tda_pl with the command name.
tda_pl(p, cmd, ..., rhs = NULL) tda_pl_axes( p, sc = NULL, ic = NULL, lty = NULL, lw = NULL, fs = NULL, tl = NULL, fmt = NULL, ... ) tda_pl_frame(p, lty = NULL, lw = NULL, gray = NULL, ...) tda_pl_grid(p, at_x = NULL, at_y = NULL, lty = NULL, lw = NULL, ...) tda_pl_lines( p, x, y, select = NULL, by = NULL, lty = NULL, band = NULL, rows = NULL, gray = NULL, ... ) TDA_LTY tda_pl_points( p, x, y, symbol = 1, size = NULL, lty = 0, lw = NULL, gray = NULL, ... ) tda_pl_smooth(p, x, y, ns = 2, lty = NULL, gray = NULL, ...) tda_pl_circle( p, at, r = 1, angles = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_text( p, label, at, fs = NULL, rotate = NULL, white = NULL, symbol = NULL, center = NULL, ... ) tda_pl_rect(p, x, y, lty = NULL, lw = NULL, gray = NULL, rotate = NULL, ...) tda_pl_polyline(p, x, y, lty = NULL, lw = NULL, gray = NULL, ...) tda_pl_function( p, expr, range, step = NULL, lty = NULL, lw = NULL, gray = NULL, deriv = NULL, ... ) tda_ps_file(x)tda_pl(p, cmd, ..., rhs = NULL) tda_pl_axes( p, sc = NULL, ic = NULL, lty = NULL, lw = NULL, fs = NULL, tl = NULL, fmt = NULL, ... ) tda_pl_frame(p, lty = NULL, lw = NULL, gray = NULL, ...) tda_pl_grid(p, at_x = NULL, at_y = NULL, lty = NULL, lw = NULL, ...) tda_pl_lines( p, x, y, select = NULL, by = NULL, lty = NULL, band = NULL, rows = NULL, gray = NULL, ... ) TDA_LTY tda_pl_points( p, x, y, symbol = 1, size = NULL, lty = 0, lw = NULL, gray = NULL, ... ) tda_pl_smooth(p, x, y, ns = 2, lty = NULL, gray = NULL, ...) tda_pl_circle( p, at, r = 1, angles = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_text( p, label, at, fs = NULL, rotate = NULL, white = NULL, symbol = NULL, center = NULL, ... ) tda_pl_rect(p, x, y, lty = NULL, lw = NULL, gray = NULL, rotate = NULL, ...) tda_pl_polyline(p, x, y, lty = NULL, lw = NULL, gray = NULL, ...) tda_pl_function( p, expr, range, step = NULL, lty = NULL, lw = NULL, gray = NULL, deriv = NULL, ... ) tda_ps_file(x)
p |
a |
cmd |
the TDA command name, e.g. |
... |
further options for the underlying TDA command, e.g.
|
rhs |
the command's right-hand side, when it takes one. |
sc |
for |
ic |
for |
lty |
line type, either an R name – |
lw |
line width in mm, for |
fs |
font size in mm, for |
tl |
for |
fmt |
for |
gray |
for |
at_x, at_y
|
for |
x, y
|
for |
select |
draw only this level of |
by |
a grouping column in the plot's data. Without |
band |
a pair of column names holding the upper and lower bound of a
confidence band, shaded behind the line the way
|
rows |
an explicit row selection, for drawing two series of different lengths out of one frame. |
symbol |
for |
size |
symbol size. |
ns |
degree of smoothing. |
at |
where to draw it, as a pair of coordinates. |
r |
radius of a circle, in the plot's units. |
angles |
for |
label |
text to draw. |
rotate |
rotation in degrees, for |
white |
for |
center |
for |
expr |
an expression in TDA's language. |
range, step
|
for |
deriv |
for |
The session, with the command added.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
set.seed(1) d <- data.frame(v = rnorm(60, 50, 10)) p <- tda_ps(d, xlim = c(0, 100), ylim = c(0, 0.05)) p <- tda_pl_axes(p) # plotd (a density plot) has no named wrapper -- it needs an evaluation # grid (x=) and exactly one variable on the right-hand side, which is not # the R column name but the internal one tda_ps() assigned; look it up in # the session's xlab/xname the same way the named wrappers do vname <- p$xname[p$xlab == "v"] p <- tda_pl(p, "plotd", x = "0(5)100", rhs = vname) p # every named wrapper, on one plot, so each one is a working example # rather than a bare signature -- x/y take a column name or a number # everywhere, and every one of these actually draws something d2 <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p2 <- tda_ps(d2, xlim = c(0, 6), ylim = c(0, 12), width = 90, height = 70) p2 <- tda_pl_axes(p2) # tick marks and their numbers p2 <- tda_pl_frame(p2) # a box around the plotting area p2 <- tda_pl_grid(p2, lw = 0.15) # TDA's default (lw = 0.05mm) is # thin to the point of illegible on a # modern screen; heavier here on purpose p2 <- tda_pl_lines(p2, "x", "y") # the data, joined point to point p2 <- tda_pl_points(p2, "x", "y", symbol = 1, size = 4) # a marker per point p2 <- tda_pl_smooth(p2, "x", "y", ns = 4, lty = "dashed") # a smoothed fit p2 <- tda_pl_circle(p2, at = c(3, 5), r = 0.3) # mark a location p2 <- tda_pl_text(p2, "peak", at = c(4.3, 9)) # a text label p2 <- tda_pl_rect(p2, x = c(4, 5), y = c(11, 11.8)) # a rectangle p2 <- tda_pl_polyline(p2, c(0.2, 1, 0.2), c(11, 11, 11.8)) # a raw shape # its row along the top, so it doesn't cross the data line below p2 <- tda_pl_function(p2, "sin(x)+11", range = c(0, 6), step = 0.2) tda_ps_file(p2) # the PostScript path, once the session has been run p2set.seed(1) d <- data.frame(v = rnorm(60, 50, 10)) p <- tda_ps(d, xlim = c(0, 100), ylim = c(0, 0.05)) p <- tda_pl_axes(p) # plotd (a density plot) has no named wrapper -- it needs an evaluation # grid (x=) and exactly one variable on the right-hand side, which is not # the R column name but the internal one tda_ps() assigned; look it up in # the session's xlab/xname the same way the named wrappers do vname <- p$xname[p$xlab == "v"] p <- tda_pl(p, "plotd", x = "0(5)100", rhs = vname) p # every named wrapper, on one plot, so each one is a working example # rather than a bare signature -- x/y take a column name or a number # everywhere, and every one of these actually draws something d2 <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p2 <- tda_ps(d2, xlim = c(0, 6), ylim = c(0, 12), width = 90, height = 70) p2 <- tda_pl_axes(p2) # tick marks and their numbers p2 <- tda_pl_frame(p2) # a box around the plotting area p2 <- tda_pl_grid(p2, lw = 0.15) # TDA's default (lw = 0.05mm) is # thin to the point of illegible on a # modern screen; heavier here on purpose p2 <- tda_pl_lines(p2, "x", "y") # the data, joined point to point p2 <- tda_pl_points(p2, "x", "y", symbol = 1, size = 4) # a marker per point p2 <- tda_pl_smooth(p2, "x", "y", ns = 4, lty = "dashed") # a smoothed fit p2 <- tda_pl_circle(p2, at = c(3, 5), r = 0.3) # mark a location p2 <- tda_pl_text(p2, "peak", at = c(4.3, 9)) # a text label p2 <- tda_pl_rect(p2, x = c(4, 5), y = c(11, 11.8)) # a rectangle p2 <- tda_pl_polyline(p2, c(0.2, 1, 0.2), c(11, 11, 11.8)) # a raw shape # its row along the top, so it doesn't cross the data line below p2 <- tda_pl_function(p2, "sin(x)+11", range = c(0, 6), step = 0.2) tda_ps_file(p2) # the PostScript path, once the session has been run p2
plotk: draws an arc, optionally ending in an arrow, between
each consecutive pair of points – a curved alternative to
tda_pl_lines for showing a directed relationship without
the line hiding what is under it. Fixed along the way: a genuine
rendering bug where a shallow arc (TDA's technique for one – a
small slice of a large-radius circle) was measured by the full
circle's radius when sizing the plot, inflating the bounding box to
fit an almost entirely off-screen circle and shrinking everything
else into a corner; the fix (using the arc segment's actual
extent) is general, not specific to this function.
tda_pl_arc(p, x, y, curvature = 0, arrow = NULL, lty = NULL, lw = NULL, ...)tda_pl_arc(p, x, y, curvature = 0, arrow = NULL, lty = NULL, lw = NULL, ...)
p |
a |
x, y
|
coordinates the arcs connect, in order; at least two points. |
curvature |
how much the arc bows out, as a fraction of the
distance between the two points; |
arrow |
size of an arrowhead at the end of each arc, as
|
lty, lw
|
line type and line width in mm for the arc. |
... |
further options for the command. |
The session, with the command added.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
p <- tda_ps(xlim = c(0, 10), ylim = c(0, 10)) p <- tda_pl_frame(p) p <- tda_pl_arc(p, c(2, 8), c(2, 8), curvature = 3, arrow = c(1.5, 1)) plot(p)p <- tda_ps(xlim = c(0, 10), ylim = c(0, 10)) p <- tda_pl_frame(p) p <- tda_pl_arc(p, c(2, 8), c(2, 8), curvature = 3, arrow = c(1.5, 1)) plot(p)
tda_pl_axes draws both axes together, at the plot's boundary.
tda_pl_axis draws one axis at a time and, via at, can place
it anywhere in the plot rather than only at the boundary – TDA's
technique for a second x or y axis (e.g. a top axis in different units
from the bottom one), which tda_pl_axes alone cannot reach.
tda_pl_axis( p, which = c("x", "y"), sc = NULL, ic = NULL, lty = NULL, lw = NULL, fs = NULL, tl = NULL, fmt = NULL, at = NULL, dir = NULL, ... )tda_pl_axis( p, which = c("x", "y"), sc = NULL, ic = NULL, lty = NULL, lw = NULL, fs = NULL, tl = NULL, fmt = NULL, at = NULL, dir = NULL, ... )
p |
a |
which |
|
sc, ic, lty, lw, fs, tl, fmt
|
as in |
at |
the axis line's endpoints, |
dir |
which side of the axis line the tick labels are written on
(TDA's |
... |
further options for |
The session, with the command added.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
p <- tda_ps(xlim = c(-2, 2), ylim = c(0, 1)) p <- tda_pl_axis(p, "x", sc = 1, ic = 2) p <- tda_pl_axis(p, "y", sc = 0.5, ic = 0) # a second x axis, drawn at y = 1 instead of the plot's bottom edge p <- tda_pl_axis(p, "x", sc = 1, ic = 5, dir = 1, at = c(-1, 1, 1, 1))p <- tda_ps(xlim = c(-2, 2), ylim = c(0, 1)) p <- tda_pl_axis(p, "x", sc = 1, ic = 2) p <- tda_pl_axis(p, "y", sc = 0.5, ic = 0) # a second x axis, drawn at y = 1 instead of the plot's bottom edge p <- tda_pl_axis(p, "x", sc = 1, ic = 5, dir = 1, at = c(-1, 1, 1, 1))
plg is TDA's graph drawing command, and a different thing from
pltree: it takes the node coordinates and the edges and draws them,
with control over node shape and shading, edge curvature and arrowheads.
pltree by contrast computes a tree layout and draws edges only.
tda_pl_graph(p, nodes, edges = NULL, ...)tda_pl_graph(p, nodes, edges = NULL, ...)
p |
a |
nodes |
a data frame with the node positions. It needs |
edges |
a data frame of edges with |
... |
further options for |
The session, with the command added.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
nodes <- data.frame(x = c(1, 3, 1, 3), y = c(2, 2, 1, 1)) edges <- data.frame(from = c(1, 1), to = c(2, 3)) p <- tda_ps(xlim = c(0, 4), ylim = c(0, 3), width = 40, height = 30) p <- tda_pl_graph(p, nodes, edges)nodes <- data.frame(x = c(1, 3, 1, 3), y = c(2, 2, 1, 1)) edges <- data.frame(from = c(1, 1), to = c(2, 3)) p <- tda_ps(xlim = c(0, 4), ylim = c(0, 3), width = 40, height = 30) p <- tda_pl_graph(p, nodes, edges)
Named wrappers for the plot commands that take arguments worth spelling
out. Everything else is reachable with tda_pl.
tda_pl_density( p, x, at, bandwidth = NULL, kernel = c("uniform", "triangle", "quartic", "epanechnikov"), scale = NULL, clip = TRUE, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_histogram( p, x, breaks, weights = NULL, scale = NULL, closed = c("left", "right"), vertical_lines = TRUE, clip = TRUE, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_contour( p, expr, levels, resolution = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_curve( p, x, y, symbol = NULL, size = NULL, lty = NULL, lw = NULL, gray = NULL, smooth = NULL, ... ) tda_pl_ellipse( p, at, axes = c(1, 0.5), rotate = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_labels( p, label, which = c("title", "x", "y"), sc = NULL, fs = NULL, ... ) tda_pl_grid_lines(p, ...)tda_pl_density( p, x, at, bandwidth = NULL, kernel = c("uniform", "triangle", "quartic", "epanechnikov"), scale = NULL, clip = TRUE, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_histogram( p, x, breaks, weights = NULL, scale = NULL, closed = c("left", "right"), vertical_lines = TRUE, clip = TRUE, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_contour( p, expr, levels, resolution = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_curve( p, x, y, symbol = NULL, size = NULL, lty = NULL, lw = NULL, gray = NULL, smooth = NULL, ... ) tda_pl_ellipse( p, at, axes = c(1, 0.5), rotate = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_labels( p, label, which = c("title", "x", "y"), sc = NULL, fs = NULL, ... ) tda_pl_grid_lines(p, ...)
p |
a |
x, y
|
variables in the session's data, or coordinates. |
at |
evaluation points for a density, or a pair of coordinates. |
bandwidth |
kernel bandwidth for |
kernel |
kernel shape for |
scale |
for |
clip |
for |
lty, lw, gray
|
line type, line width in mm, and grey level from 0
(black) to 1 (white), for |
... |
further options for the underlying TDA command – look them
up with |
breaks |
interval boundaries for a histogram. |
weights |
for |
closed |
for |
vertical_lines |
for |
expr |
an expression in TDA's language. |
levels |
contour levels for |
resolution |
for |
symbol |
marker symbol, for |
size |
marker size in mm, for |
smooth |
the number of intervals for Akima smoothing of a convex
hull's outline; TDA's |
axes |
for |
rotate |
rotation in degrees, for |
label |
the text |
which |
which label to set: |
sc |
for |
fs |
font size in mm, for |
The session, with the command added.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
set.seed(1) d <- data.frame(v = round(rnorm(60) * 10 + 50, 1)) # ploth's bars are density-scaled (each bar's area, not its height, is # its share of the cases), not raw counts -- ylim has to fit that # small scale or the bars are real but too short to see p <- tda_ps(d, xlim = c(0, 100), ylim = c(0, 0.05)) p <- tda_pl(p, "plxa", sc = 20, ic = 1) # ploth takes the interval boundaries with breaks=, not tp=: passing tp= # is silently ignored and every bar comes out flat. tda_pl_histogram(p, "v", breaks = seq(0, 100, 10)) # plotd is a kernel density estimate, and at= are the points it is # evaluated at rather than the intervals of a histogram. tda_pl_density(p, "v", at = seq(0, 100, 5)) # a curve through data, a contour of an expression in two variables, an # ellipse, a grid of light lines at the axis ticks, and a title d2 <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p2 <- tda_ps(d2, xlim = c(0, 6), ylim = c(0, 10)) p2 <- tda_pl_axes(p2) p2 <- tda_pl_curve(p2, "x", "y") p2 <- tda_pl_contour(p2, "x^2+y^2", levels = c(10, 30, 50)) p2 <- tda_pl_ellipse(p2, at = c(3, 5), axes = c(1.5, 0.8)) p2 <- tda_pl_grid(p2, lw = 0.15) p2 <- tda_pl_labels(p2, "my plot title") p2set.seed(1) d <- data.frame(v = round(rnorm(60) * 10 + 50, 1)) # ploth's bars are density-scaled (each bar's area, not its height, is # its share of the cases), not raw counts -- ylim has to fit that # small scale or the bars are real but too short to see p <- tda_ps(d, xlim = c(0, 100), ylim = c(0, 0.05)) p <- tda_pl(p, "plxa", sc = 20, ic = 1) # ploth takes the interval boundaries with breaks=, not tp=: passing tp= # is silently ignored and every bar comes out flat. tda_pl_histogram(p, "v", breaks = seq(0, 100, 10)) # plotd is a kernel density estimate, and at= are the points it is # evaluated at rather than the intervals of a histogram. tda_pl_density(p, "v", at = seq(0, 100, 5)) # a curve through data, a contour of an expression in two variables, an # ellipse, a grid of light lines at the axis ticks, and a title d2 <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p2 <- tda_ps(d2, xlim = c(0, 6), ylim = c(0, 10)) p2 <- tda_pl_axes(p2) p2 <- tda_pl_curve(p2, "x", "y") p2 <- tda_pl_contour(p2, "x^2+y^2", levels = c(10, 30, 50)) p2 <- tda_pl_ellipse(p2, at = c(3, 5), axes = c(1.5, 0.8)) p2 <- tda_pl_grid(p2, lw = 0.15) p2 <- tda_pl_labels(p2, "my plot title") p2
TDA can lay out more than one plot on a single page by calling
psetup again, at a different physical position (psorg=) –
this is that, reachable with the same xlim/ylim/
width/height vocabulary tda_ps itself uses to
start the first one, rather than a raw, hand-built psetup block.
Every tda_pl_* command after this one draws into the new panel;
the commands already added stay in the first (or previous) panel.
tda_pl_panel( p, origin, width = NULL, height = NULL, xlim = NULL, ylim = NULL, ... )tda_pl_panel( p, origin, width = NULL, height = NULL, xlim = NULL, ylim = NULL, ... )
p |
a |
origin |
the new panel's position relative to the
previous panel's own (the session's
|
width, height
|
size of the new panel, in mm (TDA's |
xlim, ylim
|
the new panel's coordinate range; default to the same range the session itself started with. |
... |
further |
The session, with the new panel started.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
p <- tda_ps(xlim = c(0, 6), ylim = c(-1, 1), width = 50, height = 40) p <- tda_pl_axes(p, sc = 1) p <- tda_pl_function(p, "sin(x1)", range = c(0, 6)) p <- tda_pl_text(p, "Plot 1", at = c(4, 0.2)) # 50 (the previous panel's width) plus a real gap, or its own # tick labels collide with this new panel's own. p <- tda_pl_panel(p, origin = c(65, 0), width = 50, height = 30) p <- tda_pl_axes(p, sc = 1) p <- tda_pl_function(p, "sin(x1)", range = c(0, 6)) p <- tda_pl_text(p, "Plot 2", at = c(4, 0.2))p <- tda_ps(xlim = c(0, 6), ylim = c(-1, 1), width = 50, height = 40) p <- tda_pl_axes(p, sc = 1) p <- tda_pl_function(p, "sin(x1)", range = c(0, 6)) p <- tda_pl_text(p, "Plot 1", at = c(4, 0.2)) # 50 (the previous panel's width) plus a real gap, or its own # tick labels collide with this new panel's own. p <- tda_pl_panel(p, origin = c(65, 0), width = 50, height = 30) p <- tda_pl_axes(p, sc = 1) p <- tda_pl_function(p, "sin(x1)", range = c(0, 6)) p <- tda_pl_text(p, "Plot 2", at = c(4, 0.2))
tda_pl_regression draws the fitted curve that TDA's screen-only
xreg command used to add to an X11 scatterplot – the X11 front
end was never part of this source tree, so the three fits it offered
are reproduced here and drawn through the ordinary PostScript
session: a lowess curve, a least-squares line, or an L1-norm
(least-absolute-deviations) line, one per group. The lowess curve is
TDA's, drawn by scplot – the same one
tda_pl_scatter draws, and the one xreg drew.
(npreg(opt = 4) runs the same C routine but cannot give the
same curve: it resets its band width to 1 when it is below epsilon,
before the lowess branch, so the delta shortcut is never 0, while
scplot passes 0.) The least-squares line is ordinary
regression of y on x; the L1 line is TDA's l1reg via
tda_l1reg. Like xreg, the straight-line fits are
drawn from the group's smallest x to its largest.
tda_pl_regression( p, x, y, type = c("lowess", "least_squares", "l1"), by = NULL, bandwidth = 0.5, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_hull( p, x, y, by = NULL, lty = NULL, lw = NULL, gray = NULL, symbol = NULL, size = NULL, smooth = NULL, expand = NULL, ... )tda_pl_regression( p, x, y, type = c("lowess", "least_squares", "l1"), by = NULL, bandwidth = 0.5, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_hull( p, x, y, by = NULL, lty = NULL, lw = NULL, gray = NULL, symbol = NULL, size = NULL, smooth = NULL, expand = NULL, ... )
p |
A plot session started with |
x, y
|
Column names in the session's data. |
type |
The fit: |
by |
Optional name of a grouping column; one fit (or hull) per group. Without it, all points are one group. |
bandwidth |
The lowess span, |
lty, lw, gray
|
Line type, width (mm), and gray level for the drawn curve. |
... |
Further options passed to the drawing command. |
symbol, size
|
for |
smooth |
the number of intervals for Akima smoothing of the
hull's outline; |
expand |
a margin added to a smoothed hull, in millimetres;
TDA's |
tda_pl_hull is xconh: the convex hull of each group's
points, drawn as a closed outline.
The third screen command, xplotf, plotted values straight from
a file; tda_pl_scatter and tda_pl_lines
with raw vectors already do that.
The session, with the curve(s) added. The fitted coefficients
(for the straight-line types) or curves are kept in
p$fits, one entry per call and group.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
set.seed(1) d <- data.frame(x = round(runif(40, 0, 10), 2)) d$y <- round(1 + 0.8 * d$x + rnorm(40), 2) p <- tda_ps(d, xlim = c(0, 10), ylim = c(0, 12)) p <- tda_pl_frame(p) p <- tda_pl_scatter(p, "x", "y", symbol = 1) p <- tda_pl_regression(p, "x", "y", type = "least_squares", lty = "dashed") p$fitsset.seed(1) d <- data.frame(x = round(runif(40, 0, 10), 2)) d$y <- round(1 + 0.8 * d$x + rnorm(40), 2) p <- tda_ps(d, xlim = c(0, 10), ylim = c(0, 12)) p <- tda_pl_frame(p) p <- tda_pl_scatter(p, "x", "y", symbol = 1) p <- tda_pl_regression(p, "x", "y", type = "least_squares", lty = "dashed") p$fits
scplot: three related ways of showing an x/y relationship, all
in one command via type – plain symbols (the default), a
sunflower plot (symbol density shown as petal count, for data too
crowded for plain symbols to read), or a lowess-smoothed curve.
tda_pl_scatter( p, x, y, type = c("points", "sunflower", "lowess"), symbol = NULL, size = NULL, grid = NULL, bandwidth = NULL, select = NULL, clip = TRUE, lty = NULL, lw = NULL, ... )tda_pl_scatter( p, x, y, type = c("points", "sunflower", "lowess"), symbol = NULL, size = NULL, grid = NULL, bandwidth = NULL, select = NULL, clip = TRUE, lty = NULL, lw = NULL, ... )
p |
a |
x, y
|
variables in the session's data, or coordinates. |
type |
|
symbol |
marker symbol, for |
size |
marker (or, for |
grid |
for |
bandwidth |
for |
select |
a case-selection expression, TDA's |
clip |
clip points to the plot's declared range (the
default); |
lty, lw
|
line type and width for |
... |
further options for the command, e.g. |
The session, with the command added.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_plot_ps(),
tda_ps(),
tda_ps3(),
tda_read_ps()
set.seed(1) d <- data.frame(x = round(runif(30, 0, 10), 1), y = round(runif(30, 0, 10), 1)) p <- tda_ps(d, xlim = c(0, 10), ylim = c(0, 10)) p <- tda_pl_frame(p) p <- tda_pl_scatter(p, "x", "y", symbol = 1) plot(p) # a lowess-smoothed curve instead, on data with a real nonlinear trend d2 <- data.frame(x = sort(round(runif(30, 0, 10), 1))) d2$y <- round(0.5 * d2$x^1.5 + rnorm(30, sd = 1), 2) p2 <- tda_ps(d2, xlim = c(0, 10), ylim = c(0, 20)) p2 <- tda_pl_frame(p2) p2 <- tda_pl_scatter(p2, "x", "y", type = "lowess", bandwidth = 0.6, lty = "dashed") plot(p2)set.seed(1) d <- data.frame(x = round(runif(30, 0, 10), 1), y = round(runif(30, 0, 10), 1)) p <- tda_ps(d, xlim = c(0, 10), ylim = c(0, 10)) p <- tda_pl_frame(p) p <- tda_pl_scatter(p, "x", "y", symbol = 1) plot(p) # a lowess-smoothed curve instead, on data with a real nonlinear trend d2 <- data.frame(x = sort(round(runif(30, 0, 10), 1))) d2$y <- round(0.5 * d2$x^1.5 + rnorm(30, sd = 1), 2) p2 <- tda_ps(d2, xlim = c(0, 10), ylim = c(0, 20)) p2 <- tda_pl_frame(p2) p2 <- tda_pl_scatter(p2, "x", "y", type = "lowess", bandwidth = 0.6, lty = "dashed") plot(p2)
TDA's plcirc3 on a psetup3 system.
tda_plcirc3(radius, center = c(0, 0, 0), normal = c(0, 0, 1), ...)tda_plcirc3(radius, center = c(0, 0, 0), normal = c(0, 0, 1), ...)
radius |
circle radius. |
center |
xyz center. |
normal |
direction vector of the circle plane. |
... |
passed to |
path of the PostScript file, invisibly.
# a unit circle in the xy plane, drawn on its own psetup3 system f <- tda_plcirc3(1, center = c(0, 0, 0), normal = c(0, 0, 1)) tda_plot_ps(tda_read_ps(f)) # the same command added to a session, so it can share a plot with # other 3-d commands: TDA's own option names, xyz= and dvec= p <- tda_ps3(xlim = c(-2, 2), ylim = c(-2, 2), zlim = c(-2, 2)) p <- tda_pl(p, "plcirc3", xyz = "0,0,0", dvec = "0,0,1", rhs = 1) p <- tda_pl(p, "plcirc3", xyz = "0,0,0", dvec = "0,1,0", rhs = 1) plot(p)# a unit circle in the xy plane, drawn on its own psetup3 system f <- tda_plcirc3(1, center = c(0, 0, 0), normal = c(0, 0, 1)) tda_plot_ps(tda_read_ps(f)) # the same command added to a session, so it can share a plot with # other 3-d commands: TDA's own option names, xyz= and dvec= p <- tda_ps3(xlim = c(-2, 2), ylim = c(-2, 2), zlim = c(-2, 2)) p <- tda_pl(p, "plcirc3", xyz = "0,0,0", dvec = "0,0,1", rhs = 1) p <- tda_pl(p, "plcirc3", xyz = "0,0,0", dvec = "0,1,0", rhs = 1) plot(p)
TDA's plglob3: longitude/latitude grid on a sphere.
tda_plglob3(radius, lon = seq(-150, 150, 30), lat = seq(-60, 60, 30), ...)tda_plglob3(radius, lon = seq(-150, 150, 30), lat = seq(-60, 60, 30), ...)
radius |
sphere radius. |
lon, lat
|
grid sequences (degrees). |
... |
passed to |
path of the PostScript file, invisibly.
# a globe with meridians every 30 degrees and parallels at -60..60 f <- tda_plglob3(1) tda_plot_ps(tda_read_ps(f)) # a coarser grid, as one command of a session p <- tda_ps3(xlim = c(-2, 2), ylim = c(-2, 2), zlim = c(-2, 2)) p <- tda_pl(p, "plglob3", lon = "-90,0,90", lat = "-45,0,45", rhs = 1) plot(p)# a globe with meridians every 30 degrees and parallels at -60..60 f <- tda_plglob3(1) tda_plot_ps(tda_read_ps(f)) # a coarser grid, as one command of a session p <- tda_ps3(xlim = c(-2, 2), ylim = c(-2, 2), zlim = c(-2, 2)) p <- tda_pl(p, "plglob3", lon = "-90,0,90", lat = "-45,0,45", rhs = 1) plot(p)
Replays what tda_read_ps parsed onto the current grid device,
so a plot TDA produced appears in an R graphics device rather than only in
a .ps file.
tda_plot_ps(x, newpage = TRUE, cex = NULL, ...)tda_plot_ps(x, newpage = TRUE, cex = NULL, ...)
x |
a path, a TDA run, or the result of |
newpage |
start a new page before drawing. |
cex |
character expansion for the text, relative to the size TDA
asked for. The sizes in the file are PostScript points against a plot of
perhaps 80mm; drawn into a device several times that, they come out
small, so the default scales them with the drawing, times
|
... |
passed to |
The parsed operations, invisibly.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_ps(),
tda_ps3(),
tda_read_ps()
# a PostScript file with something in it: five points on a quadratic. # psetup needs its ranges -- axes alone draw nothing, and tda_plot_ps # then has nothing to render. r <- tda_run(c("nvar(noc = 5, X = case, Y = case * case);", "psfile = p.ps;", "psetup(pxlen = 90, pylen = 50, pxa = 0,6, pya = 0,30);", "plxa(sc = 1); plya(sc = 10); plframe;", "plot = X,Y;", "psclose;")) p <- tda_plot_ps(file.path(r$dir, "p.ps"))# a PostScript file with something in it: five points on a quadratic. # psetup needs its ranges -- axes alone draw nothing, and tda_plot_ps # then has nothing to render. r <- tda_run(c("nvar(noc = 5, X = case, Y = case * case);", "psfile = p.ps;", "psetup(pxlen = 90, pylen = 50, pxa = 0,6, pya = 0,30);", "plxa(sc = 1); plya(sc = 10); plframe;", "plot = X,Y;", "psclose;")) p <- tda_plot_ps(file.path(r$dir, "p.ps"))
TDA's plotcm over a value matrix at the given levels.
tda_plotcm(z, levels, ...)tda_plotcm(z, levels, ...)
z |
value matrix. |
levels |
contour levels. |
... |
passed to |
path of the PostScript file, invisibly.
# a bowl-shaped surface over an 8 x 8 grid: contours at three heights z <- outer(1:8, 1:8, function(i, j) (i - 4)^2 + (j - 4)^2) f <- tda_plotcm(z, levels = c(2, 6, 12)) tda_plot_ps(tda_read_ps(f))# a bowl-shaped surface over an 8 x 8 grid: contours at three heights z <- outer(1:8, 1:8, function(i, j) (i - 4)^2 + (j - 4)^2) f <- tda_plotcm(z, levels = c(2, 6, 12)) tda_plot_ps(tda_read_ps(f))
TDA's plotr.
tda_plotr(z, grey_range = c(0, 1), ...)tda_plotr(z, grey_range = c(0, 1), ...)
z |
value matrix. |
grey_range |
two greys mapped to the value extremes. |
... |
passed to |
path of the PostScript file, invisibly.
# cells shaded from white (smallest value) to black (largest) f <- tda_plotr(outer(1:5, 1:5, "+")) tda_plot_ps(tda_read_ps(f))# cells shaded from white (smallest value) to black (largest) f <- tda_plotr(outer(1:5, 1:5, "+")) tda_plot_ps(tda_read_ps(f))
TDA's plotsp.
tda_plotsp(x, y, ...)tda_plotsp(x, y, ...)
x, y
|
coordinates. |
... |
passed to |
path of the PostScript file, invisibly.
# a smooth curve through five points that zigzag between 0 and 1 f <- tda_plotsp(x = c(0, 1, 2, 3, 4), y = c(0, 1, 0, 1, 0)) tda_plot_ps(tda_read_ps(f))# a smooth curve through five points that zigzag between 0 and 1 f <- tda_plotsp(x = c(0, 1, 2, 3, 4), y = c(0, 1, 0, 1, 0)) tda_plot_ps(tda_read_ps(f))
TDA's plsurf3: x, y, z as expressions in u and v.
tda_plsurf3( fx, fy, fz, u_range = c(-1, 1, 5, 10), v_range = c(-1, 1, 5, 10), ... )tda_plsurf3( fx, fy, fz, u_range = c(-1, 1, 5, 10), v_range = c(-1, 1, 5, 10), ... )
fx, fy, fz
|
coordinate expressions in |
u_range, v_range
|
c(from, to, grid_lines, points_per_line). |
... |
passed to |
path of the PostScript file, invisibly.
# z = sin(u) cos(v) over a 5 x 5 grid of lines, 12 points each f <- tda_plsurf3(fx = "u", fy = "v", fz = "sin(u) * cos(v)", u_range = c(-2, 2, 5, 12), v_range = c(-2, 2, 5, 12)) tda_plot_ps(tda_read_ps(f)) # tda_pl_surface3() adds the same surface to a tda_ps3() session# z = sin(u) cos(v) over a 5 x 5 grid of lines, 12 points each f <- tda_plsurf3(fx = "u", fy = "v", fz = "sin(u) * cos(v)", u_range = c(-2, 2, 5, 12), v_range = c(-2, 2, 5, 12)) tda_plot_ps(tda_read_ps(f)) # tda_pl_surface3() adds the same surface to a tda_ps3() session
sdcpol takes a set of line segments, finds where they meet and
assembles the polygons they enclose. It works on a plain table of
segments rather than on a tda_spatial structure, and with
option = 3 it writes a spatial data file the rest of the family
can read.
tda_polygons(segments, option = 3, dir = tempfile("tda"), ...)tda_polygons(segments, option = 3, dir = tempfile("tda"), ...)
segments |
a data frame of four columns: the two ends of each segment, as x1, y1, x2, y2. |
option |
1 prints the node list of the graph the segments form, 2 its edge list, 3 constructs the polygons. |
dir |
working directory for the run. |
... |
further options for |
For option = 3 a tda_spatial structure; otherwise
the run, with the table in $table.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_read_dbf(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd(),
tda_sd_analyses,
tda_sd_ps3(),
tda_spatial()
sq <- data.frame(x1 = c(0, 1, 1, 0), y1 = c(0, 0, 1, 1), x2 = c(1, 1, 0, 0), y2 = c(0, 1, 1, 0)) tda_polygons(sq)sq <- data.frame(x1 = c(0, 1, 1, 0), y1 = c(0, 0, 1, 1), x2 = c(1, 1, 0, 0), y2 = c(0, 1, 1, 0)) tda_polygons(sq)
Opens a plot session. Drawing commands are added to it and it is run when the plot is drawn or its file is asked for, which mirrors how TDA works: a PostScript file is opened, a coordinate system set up, commands issued, and the file closed.
tda_ps( data = NULL, width = 100, height = 70, xlim = NULL, ylim = NULL, file = "plot.ps", origin = NULL, log = NULL, ... )tda_ps( data = NULL, width = 100, height = 70, xlim = NULL, ylim = NULL, file = "plot.ps", origin = NULL, log = NULL, ... )
data |
optional data frame the drawing commands may refer to. |
width, height
|
size of the plotting area in millimetres. |
xlim, ylim
|
ranges of the coordinate system. |
file |
name for the PostScript file. |
origin |
the session's physical position on the page, |
log |
which axes are logarithmic (TDA's |
... |
further options for |
A tda_ps session.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps3(),
tda_read_ps()
d <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p <- tda_ps(d, xlim = c(0, 6), ylim = c(0, 10)) p <- tda_pl_axes(p) p <- tda_pl_lines(p, "x", "y") pd <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p <- tda_ps(d, xlim = c(0, 6), ylim = c(0, 10)) p <- tda_pl_axes(p) p <- tda_pl_lines(p, "x", "y") p
Reopens a PostScript file that TDA wrote (xopen) and lists the
plot objects in it (xlog1). TDA numbers each thing it draws –
an axis, a series, a convex hull – and records the command that drew
it as a %\#N: command comment. This reports that list, which
is how you find the number to pass to a later xdelete.
tda_ps_objects(file, options = list(), dir = tempfile("tda"), ...)tda_ps_objects(file, options = list(), dir = tempfile("tda"), ...)
file |
a PostScript file written by TDA. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
The coordinate system and bounding box come back as attributes, because they are what decide whether a second plot can be added to this file at all.
A data frame with object, the number, and
command, the command that drew it – zero rows if the file
holds none. attr(x, "xlim"), attr(x, "ylim") and
attr(x, "bbox") carry the coordinate system;
attr(x, "run") carries the run.
d <- data.frame(X = 1:10, Y = c(2, 4, 3, 6, 5, 8, 7, 10, 9, 12)) p <- tda_ps(d, file = "p.ps", xlim = c(0, 11), ylim = c(0, 13)) tda_ps_objects(tda_ps_file(p))d <- data.frame(X = 1:10, Y = c(2, 4, 3, 6, 5, 8, 7, 10, 9, 12)) p <- tda_ps(d, file = "p.ps", xlim = c(0, 11), ylim = c(0, 13)) tda_ps_objects(tda_ps_file(p))
tda_ps3 opens a plot session using psetup3, TDA's
three-dimensional coordinate setup, and the rest add to it: points, text,
a polyline and a surface, each taking three coordinates where their
two-dimensional counterparts take two. Note that the 3-D commands are the only ones that emit
rotate and scale, which tda_read_ps does not
yet interpret, so the replayed picture may be positioned wrongly even
where the PostScript itself is correct.
tda_ps3( data = NULL, width = 100, xlim = c(0, 100), ylim = c(0, 100), zlim = c(0, 100), file = "plot.ps", ... ) tda_pl_points3( p, x, y, z, symbol = NULL, size = NULL, lty = 0, lw = NULL, gray = NULL, arrow = NULL, ... ) tda_pl_text3( p, label, at, fs = NULL, rotate = NULL, center = NULL, symbol = NULL, white = NULL, ... ) tda_pl_surface3( p, ru, rv, f1, f2, f3, contour = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_curve3(p, rx, f1, f2, f3, lty = NULL, lw = NULL, gray = NULL, ...) tda_pl_lines3( p, x, y, z, symbol = NULL, size = NULL, lty = NULL, lw = NULL, gray = NULL, arrow = NULL, ... )tda_ps3( data = NULL, width = 100, xlim = c(0, 100), ylim = c(0, 100), zlim = c(0, 100), file = "plot.ps", ... ) tda_pl_points3( p, x, y, z, symbol = NULL, size = NULL, lty = 0, lw = NULL, gray = NULL, arrow = NULL, ... ) tda_pl_text3( p, label, at, fs = NULL, rotate = NULL, center = NULL, symbol = NULL, white = NULL, ... ) tda_pl_surface3( p, ru, rv, f1, f2, f3, contour = NULL, lty = NULL, lw = NULL, gray = NULL, ... ) tda_pl_curve3(p, rx, f1, f2, f3, lty = NULL, lw = NULL, gray = NULL, ...) tda_pl_lines3( p, x, y, z, symbol = NULL, size = NULL, lty = NULL, lw = NULL, gray = NULL, arrow = NULL, ... )
data |
a data frame, or nothing. Coordinates can also be handed to the drawing commands as plain vectors, which are folded into the session's data as they arrive. |
width |
size of the plotting area in millimetres. |
xlim, ylim, zlim
|
ranges of the three axes. |
file |
name for the PostScript file. |
... |
further options for the command. |
p |
a |
x, y, z
|
coordinates, either as numbers or as names of columns in the
session's data. |
symbol, size, lty, lw, gray, arrow
|
for |
label |
text to draw. |
at |
where to draw it, as a triple of coordinates. |
fs |
font size in mm, for |
rotate |
rotation in degrees, for |
center |
for |
white |
for |
ru, rv
|
for |
f1, f2, f3
|
the x, y and z coordinate as expressions in the
curve's or surface's parameter(s) ( |
contour |
for |
rx |
for |
A tda_ps session, with the command added.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_read_ps()
x <- c(1, 3, 5, 7) y <- c(2, 6, 3, 8) z <- c(1, 4, 2, 6) # no data frame needed: the vectors are folded in as they are used p <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p <- tda_pl_points3(p, x, y, z, symbol = 4) p <- tda_pl_lines3(p, x, y, z) p <- tda_pl_text3(p, "a corner", at = c(1, 2, 1)) # column names work too, resolved against the session's data d <- data.frame(x = x, y = y, z = z) p2 <- tda_ps3(d, xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p2 <- tda_pl_points3(p2, "x", "y", "z", symbol = 4) # a surface, defined parametrically over a u,v grid rather than from # data -- plsurf3 needs all three coordinate functions and both # ranges explicitly, not a single z = f(x,y) expression p3 <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p3 <- tda_pl_surface3(p3, ru = "0,8,30,10", rv = "0,10,30,10", f1 = "u", f2 = "v", f3 = "u*v/8") # shaded, with internal contour lines -- n kept small (5, not 30) since # gray= shades every grid cell individually; see the ru/rv argument p3b <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p3b <- tda_pl_surface3(p3b, ru = "0,8,5,5", rv = "0,10,5,5", f1 = "u", f2 = "v", f3 = "u*v/8", gray = 0.9, contour = TRUE) # a parametric curve -- rx takes TDA's step notation (a(step)b), # not the comma form the surface's ru/rv take p4 <- tda_ps3(xlim = c(-2, 2), ylim = c(-2, 2), zlim = c(-2, 2)) p4 <- tda_pl_curve3(p4, rx = "0(0.1)6.28", f1 = "cos(x)", f2 = "sin(x)", f3 = "x/3-1", lty = "dotted", lw = 0.6) # a single point: plotp3 (what tda_pl_points3 calls) rejects one triple # outright, so this duplicates it -- the same marker drawn twice at the # same place, joined by an invisible zero-length line, looks identical # to drawing it once p4 <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p4 <- tda_pl_points3(p4, 4, 5, 3, symbol = 5, size = 3) # a rotated, centred label on a white background, next to a bounding # line -- a lone label with nothing else in the plot has no coordinate # range to size the plot from and would come out unreadably small p5 <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p5 <- tda_pl_points3(p5, c(0, 8), c(0, 10), c(0, 8), symbol = 1, size = 0.1) p5 <- tda_pl_text3(p5, "hello", at = c(4, 5, 4), fs = 4, rotate = 30, center = TRUE, white = TRUE)x <- c(1, 3, 5, 7) y <- c(2, 6, 3, 8) z <- c(1, 4, 2, 6) # no data frame needed: the vectors are folded in as they are used p <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p <- tda_pl_points3(p, x, y, z, symbol = 4) p <- tda_pl_lines3(p, x, y, z) p <- tda_pl_text3(p, "a corner", at = c(1, 2, 1)) # column names work too, resolved against the session's data d <- data.frame(x = x, y = y, z = z) p2 <- tda_ps3(d, xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p2 <- tda_pl_points3(p2, "x", "y", "z", symbol = 4) # a surface, defined parametrically over a u,v grid rather than from # data -- plsurf3 needs all three coordinate functions and both # ranges explicitly, not a single z = f(x,y) expression p3 <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p3 <- tda_pl_surface3(p3, ru = "0,8,30,10", rv = "0,10,30,10", f1 = "u", f2 = "v", f3 = "u*v/8") # shaded, with internal contour lines -- n kept small (5, not 30) since # gray= shades every grid cell individually; see the ru/rv argument p3b <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p3b <- tda_pl_surface3(p3b, ru = "0,8,5,5", rv = "0,10,5,5", f1 = "u", f2 = "v", f3 = "u*v/8", gray = 0.9, contour = TRUE) # a parametric curve -- rx takes TDA's step notation (a(step)b), # not the comma form the surface's ru/rv take p4 <- tda_ps3(xlim = c(-2, 2), ylim = c(-2, 2), zlim = c(-2, 2)) p4 <- tda_pl_curve3(p4, rx = "0(0.1)6.28", f1 = "cos(x)", f2 = "sin(x)", f3 = "x/3-1", lty = "dotted", lw = 0.6) # a single point: plotp3 (what tda_pl_points3 calls) rejects one triple # outright, so this duplicates it -- the same marker drawn twice at the # same place, joined by an invisible zero-length line, looks identical # to drawing it once p4 <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p4 <- tda_pl_points3(p4, 4, 5, 3, symbol = 5, size = 3) # a rotated, centred label on a white background, next to a bounding # line -- a lone label with nothing else in the plot has no coordinate # range to size the plot from and would come out unreadably small p5 <- tda_ps3(xlim = c(0, 8), ylim = c(0, 10), zlim = c(0, 8)) p5 <- tda_pl_points3(p5, c(0, 8), c(0, 10), c(0, 8), symbol = 1, size = 0.1) p5 <- tda_pl_text3(p5, "hello", at = c(4, 5, 4), fs = 4, rotate = 30, center = TRUE, white = TRUE)
ptree: the same tree plot.tda_graph draws (via
pltree), but as data rather than a picture – one row per node,
its parent, its first child, and its next sibling, the linked-list
representation TDA itself builds internally to draw one.
tda_ptree(g, root = NULL, options = list(), dir = tempfile("tda"), ...)tda_ptree(g, root = NULL, options = list(), dir = tempfile("tda"), ...)
g |
a |
root |
which node to treat as the root; the first node in
|
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
TDA's gn= (which graph, when more than one is open) is not
optional here in practice: ptree, unlike pltree, never
calls the setup step that gives it a safe default, so leaving it out
reliably fails with “current graph is not a tree” even for a
graph that unambiguously is one (pltree accepts the identical
graph) – gn = 1 is always sent explicitly to work around
it.
A data frame: node, edge_from, edge_to,
value, parent, first_child, next_sibling
(0 where a node has none).
Other graph analysis:
plot.tda_graph(),
tda_dmet(),
tda_g(),
tda_g_analyses,
tda_graph(),
tda_locate_line(),
tda_ucl()
e <- data.frame(from = c(1, 1, 2), to = c(2, 3, 4), value = 1) g <- tda_graph(e, directed = FALSE) # 4 nodes, 3 edges: a tree tda_ptree(g, root = 1)e <- data.frame(from = c(1, 1, 2), to = c(2, 3, 4), value = 1) g <- tda_graph(e, directed = FALSE) # 4 nodes, 3 edges: a tree tda_ptree(g, root = 1)
Binary, ordinal and multinomial logit and probit models, conditional logit and simultaneous probit.
TDA_QRMODELS tda_qreg( formula, data, model = "logit", nq = NULL, waves = NULL, min_waves = NULL, intercept = NULL, control = NULL, nintegral = NULL, tol_integral = NULL, parameterization = NULL, standardized = FALSE, predictions = FALSE, constraints = NULL, start = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... )TDA_QRMODELS tda_qreg( formula, data, model = "logit", nq = NULL, waves = NULL, min_waves = NULL, intercept = NULL, control = NULL, nintegral = NULL, tol_integral = NULL, parameterization = NULL, standardized = FALSE, predictions = FALSE, constraints = NULL, start = NULL, weights = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a two-sided formula. |
data |
a data frame. |
model |
a name from |
nq |
number of categories, for models 5 and 6. Filled in from the data if not given. |
waves, min_waves
|
the number of waves and, of those, the minimum
with valid data required per case ( |
intercept |
whether to include an intercept. Defaults to whatever
the formula itself says ( |
control |
convergence settings from |
nintegral, tol_integral
|
for models needing numerical integration
(6-8), the integration control and its accuracy ( |
parameterization |
for models 6-8, how the between-wave
correlation matrix is parameterised during estimation – |
standardized |
for a binary logit or probit model
( |
predictions |
also write out each case's fitted probabilities –
|
constraints |
for model 6 ( |
start |
optional starting values, in TDA's parameter order
(the same order |
weights |
optional case weights, a column name in |
options |
a named list of further TDA options, passed through: the output files. |
dir |
working directory. |
... |
passed to |
An object of class tda_fit. For the multivariate and
simultaneous probits (models 6 and 8) it carries correlation,
the estimated correlation matrix among the latent equations, which
TDA computes only when asked for a parameter file. It additionally
carries categories, the (weighted) count and percentage of each
response category as qreg itself tabulates them before
estimating. Cases with missing values are dropped before the fit,
with a message (see ?tdaR).
model takes a name from TDA_QRMODELS, matched partially, or a
TDA model number:
| 1 | logit |
binary logit |
| 2 | probit |
binary probit |
| 3 | ordinal_logit |
needs three or more categories |
| 4 | ordinal_probit |
needs three or more categories |
| 5 | multinomial_logit |
needs nq |
| 6 | multivariate_probit |
needs nq |
| 7 | conditional_logit |
panel: needs waves (2+)
and cbind() terms -- see
Panel models |
| 8 | simultaneous_probit |
panel: needs waves (2+)
and cbind() terms -- see
Panel models
|
Models 7 and 8 are TDA's panel models, taking each variable once per
wave in a horizontal layout. Write each variable's per-wave columns as
cbind(): cbind(y1, y2) ~ cbind(x1, x2) with
waves = 2. A term with a single column is a time-constant
predictor and is repeated across waves for you. Both models are fit
without an intercept option (TDA's design; model 8 estimates one
intercept per wave anyway, printed against Term = "W <k>",
with the between-wave correlations as Sigma rows).
Missing data follows TDA's unbalanced-panel rule: a case whose
response is missing in a wave simply has that wave dropped
from its likelihood contribution (min_waves – TDA's
pmin= – then sets how many valid waves a case needs to be
used at all), while a missing predictor value has no such
rule and drops the case, with a message.
conditional_logit is Chamberlain's fixed-effects logit; on
two-wave data it agrees with survival::clogit stratified by
case to full printed precision (pinned in the tests).
simultaneous_probit fits one binary probit per wave with
free cross-wave error correlations – for two waves, a bivariate
probit.
TDA's help text for this is incomplete: it names only model 5 as
needing nq, though models 5 and 6 both require it, and it
lists only the first five models, though eight are implemented – the
table above is the full set. The binary models agree with glm:
a binary logit is a binomial glm with a logit link, a binary probit
one with a probit link.
Other regression:
TDA_FAMILIES,
tda_freg(),
tda_gdf(),
tda_l1reg(),
tda_lsreg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_npreg(),
tda_zreg()
set.seed(23) d <- data.frame(x = round(rnorm(200), 3)) d$y <- rbinom(200, 1, plogis(-0.5 + 1.4 * d$x)) qf <- tda_qreg(y ~ x, d, model = "logit") coef(qf) coef(glm(y ~ x, d, family = binomial())) # matches: a binary logit is a # binomial glm with a logit link head(predict(qf)) # fitted values, no newdata neededset.seed(23) d <- data.frame(x = round(rnorm(200), 3)) d$y <- rbinom(200, 1, plogis(-0.5 + 1.4 * d$x)) qf <- tda_qreg(y ~ x, d, model = "logit") coef(qf) coef(glm(y ~ x, d, family = binomial())) # matches: a binary logit is a # binomial glm with a logit link head(predict(qf)) # fitted values, no newdata needed
tda_quant computes quantiles, tda_atab aggregates a variable
into classes, which is how TDA makes a histogram, and tda_freq1
gives a one-way frequency table. All three describe the distribution of
one variable at a time and return a table in the shape
... came in, one row per variable or class – unlike
tda_freq2 (a cross-tabulation of two variables, a matrix
rather than a table) or tda_loglin (a many-way contingency
table for model fitting), which need their pages.
tda_quant(..., options = list(), dir = tempfile("tda")) tda_atab( ..., breaks, open = c("right", "left"), nonempty_only = FALSE, options = list(), dir = tempfile("tda") )tda_quant(..., options = list(), dir = tempfile("tda")) tda_atab( ..., breaks, open = c("right", "left"), nonempty_only = FALSE, options = list(), dir = tempfile("tda") )
... |
a data frame, a matrix, or vectors. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
breaks |
for |
open |
for |
nonempty_only |
for |
tda_quant reports a fixed set of orders – 0.1 through 0.9 in
steps of 0.1, plus the quartiles 0.25 and 0.75 – interpolated on the
sorted values at position (the manual, section 6.2.3,
gives the exact rule). That is the same definition as R's
quantile(x, type = 6), and the two agree to the last digit;
stats::quantile's default (type = 7) is a different
interpolation and will not match.
An object carrying a table: for tda_quant, one
row per variable with the eleven quantiles p10..p90;
for tda_atab, one row per class with its boundaries, count
and percentage; for tda_freq1, one row per distinct value
with count, percent and their cumulated versions.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_rcorr(),
tda_segr(),
tda_subm()
set.seed(1) d <- data.frame(x = sample(1:5, 60, replace = TRUE, prob = c(0.1, 0.2, 0.4, 0.2, 0.1))) tda_quant(d) tda_atab(d, breaks = seq(0, 5, 1)) tda_freq1(d)set.seed(1) d <- data.frame(x = sample(1:5, 60, replace = TRUE, prob = c(0.1, 0.2, 0.4, 0.2, 0.1))) tda_quant(d) tda_atab(d, breaks = seq(0, 5, 1)) tda_freq1(d)
tda_rank_orders enumerates every rank order of size
objects, including all ways of tying them. For three objects there
are 13: six strict orders, six with one pair tied, and one with all
three tied.
tda_rank_orders(size = 2, options = list(), dir = tempfile("tda"), ...)tda_rank_orders(size = 2, options = list(), dir = tempfile("tda"), ...)
size |
number of objects to rank, 2 or more. |
options |
a named list of further TDA options, passed through.
|
dir |
working directory. |
... |
passed to |
Useful as the sample space for a rank-order model – the set of outcomes a distribution over rankings has to sum over – which is otherwise fiddly to generate because of the ties.
A data frame with one row per rank order: ties, the
number of tie groups, then one column per object (r1,
r2, ...) giving its rank. attr(x, "run") carries the
run.
r <- tda_rank_orders(3) nrow(r) # 13 head(r) table(r$ties) # 1 all tied, 6 one pair tied, 6 strictr <- tda_rank_orders(3) nrow(r) # 13 head(r) table(r$ties) # 1 all tied, 6 one pair tied, 6 strict
TDA's rap: builds age-period tables from starting time,
cohort, ending time and destination variables.
tda_rap(cohort, entry_year, exit_year, destination, years, ages, ...)tda_rap(cohort, entry_year, exit_year, destination, years, ages, ...)
cohort, entry_year, exit_year, destination
|
integer vectors, one entry per case: birth year, year of entry into observation, year of exit, and the destination code (0 censored). The engine requires cohort <= entry_year <= exit_year. |
years, ages
|
length-2 table ranges. |
... |
passed to |
table, the rate table TDA wrote, and output.
# three subjects born 1960/1961, observed 1980-1986: the risk # table fills along the Lexis diagonals r <- tda_rap(cohort = c(60, 61, 60), entry_year = c(80, 82, 83), exit_year = c(85, 86, 86), destination = c(1, 1, 0), years = c(80, 86), ages = c(18, 26)) r$risk# three subjects born 1960/1961, observed 1980-1986: the risk # table fills along the Lexis diagonals r <- tda_rap(cohort = c(60, 61, 60), entry_year = c(80, 82, 83), exit_year = c(85, 86, 86), destination = c(1, 1, 0), years = c(80, 86), ages = c(18, 26)) r$risk
The companion to tda_survivor: the rate a model implies,
with the same column names whichever model produced it. prate = at
fit time is what asks TDA to compute it.
tda_rates(x)tda_rates(x)
x |
A data frame with group, time, rate,
survivor and density, or NULL if the fit carries no
rate table. For a Cox fit rate is the baseline rate at each
event time and cumrate the cumulative baseline rate beside
it (already cumulative: TDA's CumRate column).
Other rate models:
tda_constrain(),
tda_control(),
tda_dple(),
tda_split(),
tda_survivor(),
tda_transitions(),
vcov.tda_fit()
d <- tda_rrdat() f <- tda_rate(Surv(TFP, DES) ~ 1, d, prate = "0(10)300") head(tda_rates(f))d <- tda_rrdat() f <- tda_rate(Surv(TFP, DES) ~ 1, d, prate = "0(10)300") head(tda_rates(f))
rcorr: Kendall's tau rank correlation between every pair of a
set of variables. Verified against cor(method =
"kendall"): exact match.
tda_rcorr(data, variables = NULL, options = list(), dir = tempfile("tda"), ...)tda_rcorr(data, variables = NULL, options = list(), dir = tempfile("tda"), ...)
data |
a data frame or matrix. |
variables |
optional subset of |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
A matrix, Kendall's tau between each pair of variables, with
1 on the diagonal.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_segr(),
tda_subm()
set.seed(1) d <- data.frame(x1 = rnorm(20), x2 = rnorm(20), x3 = rnorm(20)) tda_rcorr(d) tda_rcorr(d, variables = c("x1", "x2"))set.seed(1) d <- data.frame(x1 = rnorm(20), x2 = rnorm(20), x3 = rnorm(20)) tda_rcorr(d) tda_rcorr(d, variables = c("x1", "x2"))
TDA's rcsv: parses a csv file and writes a whitespace
table. Verified in the suite as a round trip against
read.csv.
tda_rcsv(file, sep = ";", ...)tda_rcsv(file, sep = ";", ...)
file |
csv input. TDA's reader splits on SEMICOLONS (the
European dialect); with |
sep |
the input file's separator. |
... |
passed to |
a data frame of TDA's parse when the export layer is on; otherwise the rendered lines.
With the export layer on (the default), the engine hands back each
raw semicolon-bounded line of the converted file and the result is
TDA's parse as a data frame, first line as header. Without it,
only TDA's padded rendering exists; it carries no separator
guarantee (adjacent one-character entries can touch), so the
rendered lines are returned as they are. The engine accepts a
df= option for this command but does not write to it.
f <- tempfile(fileext = ".csv") write.csv(data.frame(a = 1:3, b = c(2.5, 1, 4)), f, row.names = FALSE) tda_rcsv(f, sep = ",") # a data frame under the export layerf <- tempfile(fileext = ".csv") write.csv(data.frame(a = 1:3, b = c(2.5, 1, 4)), f, row.names = FALSE) tda_rcsv(f, sep = ",") # a data frame under the export layer
rd()/rdn()
The R-side equivalent of what nvar()'s X = rd(0, 3)
or Y = sin(X) + rd would generate inside TDA: tda_rd(n, a,
b) is uniform on [a, b] (rd's two-argument form,
a + random1() * (b - a)),
and tda_rd(n) alone – rd with no arguments –
is uniform on [0, 1], not the wider, arbitrary range a
hand-rolled substitute might reach for. tda_rdn is the same
idea for rdn, a standard normal.
tda_rd(n, a = 0, b = 1) tda_rdn(n, mean = 0, sd = 1)tda_rd(n, a = 0, b = 1) tda_rdn(n, mean = 0, sd = 1)
n |
how many values to draw. |
a, b
|
the range, for |
mean, sd
|
the normal distribution's parameters, for
|
These use R's random number generator, not tda_runif's
reproduction of TDA's exact stream – for building a data frame to
pass to TDA (rather than reproducing an existing TDA example's
numbers bit for bit), R's generator is what set.seed()
already controls.
A numeric vector of length n.
set.seed(1) x <- tda_rd(200, 0, 3) # nvar()'s X = rd(0, 3) y <- sin(x) + tda_rd(200) # nvar()'s Y = sin(X) + rd round(c(mean = mean(x), sd = sd(x)), 2) # near 0 and 3set.seed(1) x <- tda_rd(200, 0, 3) # nvar()'s X = rd(0, 3) y <- sin(x) + tda_rd(200) # nvar()'s Y = sin(X) + rd round(c(mean = mean(x), sd = sd(x)), 2) # near 0 and 3
tda_read_dbf reads a dBase file through TDA's rdbf and
returns it as a data frame. Character fields come back as character,
numeric ones as numeric, taken from the field types the file itself
declares.
tda_read_dbf(file, options = list(), dir = tempfile("tda"), ...)tda_read_dbf(file, options = list(), dir = tempfile("tda"), ...)
file |
path to a |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
This is the attribute half of a shapefile. tda_read_shapefile
reads the geometry; the .dbf beside it holds one row per shape
with whatever columns the data has, which for real data is usually
where the names live. tda_read_shapefile attaches it as
attr(x, "attributes").
A data frame; attr(x, "run") carries the run.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_polygons(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd(),
tda_sd_analyses,
tda_sd_ps3(),
tda_spatial()
# a shapefile's .dbf, which sf ships alongside nc.shp if (requireNamespace("sf", quietly = TRUE)) { f <- sub("[.]shp$", ".dbf", system.file("shape/nc.shp", package = "sf")) head(tda_read_dbf(f)[, c("NAME", "AREA")]) }# a shapefile's .dbf, which sf ships alongside nc.shp if (requireNamespace("sf", quietly = TRUE)) { f <- sub("[.]shp$", ".dbf", system.file("shape/nc.shp", package = "sf")) head(tda_read_dbf(f)[, c("NAME", "AREA")]) }
Parses the PostScript a plot command writes into a table of drawing operations: line segments, polygons, symbols and text, with the graphics state that applied to each.
tda_read_ps(file, which = NULL)tda_read_ps(file, which = NULL)
file |
a |
which |
when |
A list with ops, the drawing operations, and bbox,
the bounding box TDA declared. Each operation carries the plot command
that produced it, taken from the %# annotations TDA writes into
the stream.
Other plotting:
plot.tda_ple(),
tda_check_ps(),
tda_pl(),
tda_pl_arc(),
tda_pl_axis(),
tda_pl_graph(),
tda_pl_hist,
tda_pl_panel(),
tda_pl_regression(),
tda_pl_scatter(),
tda_plot_ps(),
tda_ps(),
tda_ps3()
d <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p <- tda_ps(d, xlim = c(0, 6), ylim = c(0, 10)) p <- tda_pl_axes(p) p <- tda_pl_lines(p, "x", "y") pdf(NULL) # plot() runs the session and draws it; capture the run p <- plot(p) dev.off() ps <- tda_read_ps(p$run, which = p$file) ps$bbox ps$ops[[3]]$opd <- data.frame(x = 1:5, y = c(2, 4, 5, 8, 9)) p <- tda_ps(d, xlim = c(0, 6), ylim = c(0, 10)) p <- tda_pl_axes(p) p <- tda_pl_lines(p, "x", "y") pdf(NULL) # plot() runs the session and draws it; capture the run p <- plot(p) dev.off() ps <- tda_read_ps(p$run, which = p$file) ps$bbox ps$ops[[3]]$op
sdshp reads an ESRI shapefile – the .shp, its .shx
index and the .dbf of attributes – and writes TDA's spatial
data file, which is what the rest of the spatial commands work on.
tda_read_shapefile(file, dir = tempfile("tda"), ...)tda_read_shapefile(file, dir = tempfile("tda"), ...)
file |
path to the shapefile, with or without the |
dir |
working directory for the run. |
... |
further options for |
A tda_spatial object, as tda_spatial
returns.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_polygons(),
tda_read_dbf(),
tda_read_spatial,
tda_sd(),
tda_sd_analyses,
tda_sd_ps3(),
tda_spatial()
if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) print(tda_sd_info(nc)) plot(nc) }if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) print(tda_sd_info(nc)) plot(nc) }
The same shape as tda_read_shapefile: TDA reads the file
and writes its spatial data file, which the rest of the family works
on. tda_read_e00 reads an uncompressed ARC/INFO export,
tda_read_gshhs a GSHHS coastline file, and tda_read_dcw a
Digital Chart of the World polygon point file.
tda_read_e00(file, dir = tempfile("tda"), ...) tda_read_gshhs( file, level = NULL, centre = c("greenwich", "pacific"), dir = tempfile("tda"), ... ) tda_read_dcw(file, dir = tempfile("tda"), ...)tda_read_e00(file, dir = tempfile("tda"), ...) tda_read_gshhs( file, level = NULL, centre = c("greenwich", "pacific"), dir = tempfile("tda"), ... ) tda_read_dcw(file, dir = tempfile("tda"), ...)
file |
path to the input file. |
dir |
working directory for the run. |
... |
further options for the command. |
level |
for Antarctica appears twice in a 2.3.x file, once as level 5 and once as level 6, and they are about six degrees of latitude apart near the dateline. Keeping all levels draws both, which is why a world map shows two near-parallel southern coastlines; GSHHG intends you to pick one. Neither is an artefact – the ice front runs along roughly 78 degrees south there (the Ross Ice Shelf edge, near-straight) and the grounding line along roughly 84. |
centre |
for |
All three target older formats from GIS's pre-shapefile era, and only shapefile really remains in wide, current use – e00 and DCW were both effectively superseded by it, and DCW's distribution site has been gone for years, which is worth knowing going in:
tda_read_e00 works, tested against a real ARC/INFO
export (a point coverage).
tda_read_dcw works, tested against a .pnt file
rebuilt from a real DCW coverage read via the sf package
(st_read() on the original coverage directory, coordinates
regrouped into rings and written out in the plain text form
sddcwp expects). Coordinates round-trip exactly: the
intermediate this reader writes uses fmt = "24.16", not
TDA's default, which would cost six digits of each one.
tda_read_gshhs reads both GSHHS header layouts: the
pre-2.2 one and GSHHG 2.x, which is what you would download
today. The layout is detected from the file itself and the
version reported in the run's output.
Straight lines across a world map would come from the dateline; that is handled for you, and there is nothing to configure. GSHHS stores the polygons that span the dateline with longitudes running past 180 (Eurasia reaches 190). Those are cut at the dateline and come back as separate objects, so each piece is drawn where it belongs and nothing is drawn between them; a polygon that does not span it is untouched. The Antarctic coastline, which runs from one edge of the map to the other, is returned as a line rather than a closed area for the same reason – closing it would draw a straight segment back across the world.
This is what the GSHHG maintainers do in their own shapefile distribution, where the dateline-straddling polygons – the Antarctic cap chief among them – are split into east and west components. The native binary files are left unsplit for the reader to handle.
centre = "pacific" cuts the map at Greenwich instead,
giving longitudes on 0..360; the splitting then happens at that
seam rather than at the dateline. Either way no polygon is drawn
across the map.
A tda_spatial structure.
Anything else these commands accept can be passed through ...
under TDA's option name. tda_help("sdshp"),
tda_help("sde00"), tda_help("sddcwp") and
tda_help("sdgshhs") print the full lists. One worth knowing is
nc, which tells the DCW reader that the input has no comment
lines.
df=, dtda= and fmt= are set by the reader
itself: the first two name the intermediate files it writes and reads
back, and fmt is fixed at "24.16" so that no
coordinate is rounded on the way through.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_polygons(),
tda_read_dbf(),
tda_read_shapefile(),
tda_sd(),
tda_sd_analyses,
tda_sd_ps3(),
tda_spatial()
# nc.shp ships with sf, so this one runs where sf is installed. # The .dbf beside the geometry holds the attribute table -- county # names and areas -- and is attached as $attributes. if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) head(nc$attributes[, c("NAME", "AREA")]) } ## Not run: # the other readers need files that do not ship with any package tda_read_e00("world.e00") tda_read_gshhs("gshhs_f.b", level = 1) # either header layout tda_read_dcw("polygon.pnt", nc = TRUE) ## End(Not run)# nc.shp ships with sf, so this one runs where sf is installed. # The .dbf beside the geometry holds the attribute table -- county # names and areas -- and is attached as $attributes. if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) head(nc$attributes[, c("NAME", "AREA")]) } ## Not run: # the other readers need files that do not ship with any package tda_read_e00("world.e00") tda_read_gshhs("gshhs_f.b", level = 1) # either header layout tda_read_dcw("polygon.pnt", nc = TRUE) ## End(Not run)
tda_read_spss reads an SPSS system file (.sav, TDA's
rspss1) or a portable file (.por, TDA's rspss) and
returns its data as a data frame. The format is taken from the file
extension unless portable says otherwise.
tda_read_spss( file, portable = grepl("\\.por$", file, ignore.case = TRUE), options = list(), dir = tempfile("tda"), ... )tda_read_spss( file, portable = grepl("\\.por$", file, ignore.case = TRUE), options = list(), dir = tempfile("tda"), ... )
file |
path to a |
portable |
read as a portable ( |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
These two commands were in TDA all along but had no wrapper, and no
test: the only case in the suite fed rspss1 a text file and
pinned its refusal. Both are now checked against real files written by
readspss, and both round-trip their values exactly.
String columns do come through: rspss/rspss1
create real TDA string variables (type 1) and pdata prints
them, so a character column arrives as text rather than a code. This
is one of the few ways to get a string variable into TDA at all –
tda_run refuses a character column in a data frame,
because TDA's data-frame path has no type for it.
Two consequences worth knowing. TDA renames any variable whose name
does not start with a capital (see Variable names must start
with a capital), so a lowercase SPSS name comes back as
VAR1, VAR2, ...; write the file with capitalised names
if you need them preserved. And once a string variable exists, TDA's
string operators work on it in a later nvar block of the same
run – strlen(S), strsp(S) (the alphabetical sort
position, matching R's rank), strv(S) and
strvp(S,n,m).
For value labels and missing-value codes, use readspss directly: TDA keeps the data and the names, so a label or a user-missing code is lost on the way in, and this wrapper does not pretend otherwise.
A data frame, with attr(x, "run") carrying the run.
Other data:
tda_read_xls(),
tda_strings()
# readspss can write the fixture, so this runs where it is installed if (requireNamespace("readspss", quietly = TRUE)) { f <- file.path(tempdir(), "example.sav") readspss::write.sav(data.frame(ID = 1:3, X = c(1.5, 2.5, 3.5), S = c("a", "bb", "ccc")), f) tda_read_spss(f) }# readspss can write the fixture, so this runs where it is installed if (requireNamespace("readspss", quietly = TRUE)) { f <- file.path(tempdir(), "example.sav") readspss::write.sav(data.frame(ID = 1:3, X = c(1.5, 2.5, 3.5), S = c("a", "bb", "ccc")), f) tda_read_spss(f) }
Reads a Stata .dta file through TDA's rstata, which
supports releases 4, 6, 7 and 10 – the same set
tda_write_stata writes, so a file written here reads
back here.
tda_read_stata( file, n_records = NULL, missing = NULL, upper_names = FALSE, options = list(), dir = tempfile("tda"), ... )tda_read_stata( file, n_records = NULL, missing = NULL, upper_names = FALSE, options = list(), dir = tempfile("tda"), ... )
file |
path to the |
n_records |
number of records to read. |
missing |
value to substitute for Stata's system missing. TDA's default is -5. |
upper_names |
translate variable names to upper case
( |
options |
a named list of further TDA options, passed through.
The reader also accepts, through |
dir |
working directory. |
... |
passed to |
A data frame. attr(x, "run") carries the run.
tda_write_stata, tda_read_spss
d <- data.frame(id = 1:4, y = c(1.5, 2, 2.5, 3)) f <- tempfile(fileext = ".dta") tda_write_stata(d, f) tda_read_stata(f)d <- data.frame(id = 1:4, y = c(1.5, 2, 2.5, 3)) f <- tempfile(fileext = ".dta") tda_write_stata(d, f) tda_read_stata(f)
Reads a system file written by tda_write_sys. A system
file carries the data matrix and the variable definitions together,
so the frame comes back with its column names without an nvar
block being repeated.
tda_read_sys(file, options = list(), dir = tempfile("tda"), ...)tda_read_sys(file, options = list(), dir = tempfile("tda"), ...)
file |
path to the system file. |
options |
a named list of further TDA options, passed through.
The underlying |
dir |
working directory. |
... |
passed to |
A data frame. attr(x, "run") carries the run.
d <- data.frame(id = 1:4, y = c(1.5, 2, 2.5, 3)) f <- tempfile(fileext = ".sys") tda_write_sys(d, f) tda_read_sys(f)d <- data.frame(id = 1:4, y = c(1.5, 2, 2.5, 3)) f <- tempfile(fileext = ".sys") tda_write_sys(d, f) tda_read_sys(f)
tda_read_table reads one table, taking column names from the
comment header where they can be matched to the columns.
tda_read_blocks splits a file holding several tables, which is what
a life table writes when there are groups. tda_file and
tda_blocks do the same relative to a run's directory, and report
what TDA said if the file is missing.
tda_read_table(file, col_names = NULL) tda_read_blocks(file, col_names = NULL) tda_blocks(x, file, ...) tda_file(x, file, ...)tda_read_table(file, col_names = NULL) tda_read_blocks(file, col_names = NULL) tda_blocks(x, file, ...) tda_file(x, file, ...)
file |
a file name. |
col_names |
column names to apply; a list for |
x |
a run or fitted model. |
... |
passed on. |
A data frame, or a list of them.
Other TDA infrastructure:
tda_ccnt(),
tda_help(),
tda_output(),
tda_run(),
tda_write_data()
set.seed(39) d <- data.frame(income = round(rlnorm(30, 8, 0.5))) fit <- tda_ineq(d) # tda_file() reads a named output file relative to the run's directory tda_file(fit, "out.txt", col_names = c("index", "cases", "min", "max", "mean", "sd", "vcoeff", "gini")) # tda_blocks(): a life table with groups writes several tables into one # file -- counts, then a survivor/density/rate table, once per group set.seed(1) d2 <- data.frame(t = c(4, 3, 1, 5, 8, 2), s = c(1, 1, 0, 1, 1, 1), g = c(1, 1, 1, 2, 2, 2)) lt <- tda_ltb(Surv(t, s) ~ as.factor(g), d2, tp = seq(0, 10, 2)) length(tda_blocks(lt, "out.ltb")) # 4: two groups, two tables each # tda_read_blocks(): the same thing from a raw file path, when there is # no fit object to resolve one from path <- file.path(lt$run$dir, "out.ltb") length(tda_read_blocks(path))set.seed(39) d <- data.frame(income = round(rlnorm(30, 8, 0.5))) fit <- tda_ineq(d) # tda_file() reads a named output file relative to the run's directory tda_file(fit, "out.txt", col_names = c("index", "cases", "min", "max", "mean", "sd", "vcoeff", "gini")) # tda_blocks(): a life table with groups writes several tables into one # file -- counts, then a survivor/density/rate table, once per group set.seed(1) d2 <- data.frame(t = c(4, 3, 1, 5, 8, 2), s = c(1, 1, 0, 1, 1, 1), g = c(1, 1, 1, 2, 2, 2)) lt <- tda_ltb(Surv(t, s) ~ as.factor(g), d2, tp = seq(0, 10, 2)) length(tda_blocks(lt, "out.ltb")) # 4: two groups, two tables each # tda_read_blocks(): the same thing from a raw file path, when there is # no fit object to resolve one from path <- file.path(lt$run$dir, "out.ltb") length(tda_read_blocks(path))
Reads a UCINET dataset through TDA's rucinet. UCINET stores a
dataset as a pair of files, a header .##h and the data
.##d; name the one you want read.
tda_read_ucinet( file, n_columns = NULL, form = c("matrix", "edges"), options = list(), dir = tempfile("tda"), ... )tda_read_ucinet( file, n_columns = NULL, form = c("matrix", "edges"), options = list(), dir = tempfile("tda"), ... )
file |
path to the UCINET file, usually the |
n_columns |
number of columns. |
form |
|
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
# begins a comment in TDA's command language, so a file called
something.##d truncates the command that names it and TDA
reports "Command file ends with an incomplete command". The file is
therefore copied to a #-free name for the run – which is why
this takes a path rather than leaving the caller to discover that.
A data frame of the values TDA read. attr(x, "run")
carries the run.
# a Ucinet ##d file is packed 4-byte floats, row-major M <- rbind(c(0, 2, 0), c(2, 0, 1), c(0, 1, 0)) f <- tempfile(fileext = ".##d") con <- file(f, "wb") writeBin(as.numeric(t(M)), con, size = 4); close(con) tda_read_ucinet(f, n_columns = 3) tda_read_ucinet(f, n_columns = 3, form = "edges")# a Ucinet ##d file is packed 4-byte floats, row-major M <- rbind(c(0, 2, 0), c(2, 0, 1), c(0, 1, 0)) f <- tempfile(fileext = ".##d") con <- file(f, "wb") writeBin(as.numeric(t(M)), con, size = 4); close(con) tda_read_ucinet(f, n_columns = 3) tda_read_ucinet(f, n_columns = 3, form = "edges")
tda_read_xls reads a BIFF .xls workbook through TDA's
rxls and returns the numeric table it extracts. Every sheet is
stacked into one frame with a leading sheet column.
tda_read_xls( file, skip_unknown = TRUE, numeric_only = FALSE, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )tda_read_xls( file, skip_unknown = TRUE, numeric_only = FALSE, protocol = FALSE, options = list(), dir = tempfile("tda"), ... )
file |
path to a |
skip_unknown |
skip record types TDA does not know (default
|
numeric_only |
keep only columns TDA classed as numerical
(TDA's |
protocol |
also return the workbook's string table, as
|
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
Unknown record types are skipped by default
(skip_unknown = TRUE, TDA's ni=1). Excel 2007 and later
write records into BIFF8 that TDA's table does not list – XFCRC
(0x087c), STYLEEXT (0x0892) and others – so with
TDA's default any .xls saved this century stops at
“unknown record type” before reaching a single cell. A BIFF
record carries its length, so skipping one is safe; naming them
individually is not, because the list keeps growing. Pass
skip_unknown = FALSE for TDA's original behaviour.
Text columns come back as codes. A column of text becomes an
integer index into the workbook's string table, not the text. TDA
reports which columns those are (the “Column / New / Type”
table in the run's output), and protocol = TRUE writes the
strings themselves. This is TDA's design, not a fault, but it means a
column can come back as plausible small integers that are codes: the
cyl column of readxl's datasets.xls is stored as
text and arrives as 1, 2, 3 where the values are 4, 6, 8. For
anything where that matters, readxl reads the workbook directly.
A data frame; attr(x, "run") carries the run.
Other data:
tda_read_spss(),
tda_strings()
# readxl ships these workbooks, so this runs where readxl is installed if (requireNamespace("readxl", quietly = TRUE)) { x <- tda_read_xls(readxl::readxl_example("datasets.xls")) # three sheets of different widths, stacked with a `sheet` column; # each is also available with its own column types head(attr(x, "sheets")[[1]]) }# readxl ships these workbooks, so this runs where readxl is installed if (requireNamespace("readxl", quietly = TRUE)) { x <- tda_read_xls(readxl::readxl_example("datasets.xls")) # three sheets of different widths, stacked with a `sheet` column; # each is also available with its own column types head(attr(x, "sheets")[[1]]) }
TDA's recode: replaces variable values by expressions over
the current matrix. Verified in the suite against plain R
recoding.
tda_recode(data, ..., options = list())tda_recode(data, ..., options = list())
data |
data frame. |
... |
named recode expressions in TDA syntax, e.g.
|
options |
list passed to |
the recoded data frame.
d <- data.frame(age = c(17, 25, 40), inc = c(1, 2, 3)) # TDA's expression language: ge() is >=, so age becomes an adult flag tda_recode(d, age = "ge(age, 18)", inc = "inc * 1000")d <- data.frame(age = c(17, 25, 40), inc = c(1, 2, 3)) # TDA's expression language: ge() is >=, so age becomes an adult flag tda_recode(d, age = "ge(age, 18)", inc = "inc * 1000")
TDA's repsel with a matrix expression giving, per block,
the repetition count.
tda_repsel(data, by, times, commands = character(), ...)tda_repsel(data, by, times, commands = character(), ...)
data |
data frame. |
by |
block-defining column. |
times |
matrix expression (TDA syntax) of dimension blocks x 1. |
commands |
further command lines run under the replicated case structure. Column names are TDA-sanitised (upper-cased) first, so refer to them in that form. |
... |
passed to |
the printed output, invisibly.
# blocks by G, block 1 twice and block 2 once: cases become # X = 1,2,1,2,3, and the statistics confirm it (mean 1.8, sum 9) out <- tda_repsel(data.frame(G = c(1, 1, 2), X = 1:3), by = "G", times = "<2, 1>", commands = "dstat = X;") grep("^X", out, value = TRUE)# blocks by G, block 1 twice and block 2 once: cases become # X = 1,2,1,2,3, and the statistics confirm it (mean 1.8, sum 9) out <- tda_repsel(data.frame(G = c(1, 1, 2), X = 1:3), by = "G", times = "<2, 1>", commands = "dstat = X;") grep("^X", out, value = TRUE)
TDA's rfit: finds the relations with the requested
properties closest to the graph, via linear programming.
tda_rfit( d, properties = c("symmetric", "transitive"), max_solutions = 10, variant = c("standard", "experimental"), ... )tda_rfit( d, properties = c("symmetric", "transitive"), max_solutions = 10, variant = c("standard", "experimental"), ... )
d |
symmetric matrix (proximities). |
properties |
character subset of "reflexive", "symmetric", "antisymmetric", "transitive", "complete". |
max_solutions |
cap on the number of equally good relations TDA
keeps ( |
variant |
"standard" runs rfit; "experimental" runs the rfit1 sibling (same syntax, alternative implementation). |
... |
passed to |
relations, one fitted relation matrix per solution,
and output.
d <- rbind(c(0, 2, 1), c(2, 0, 2), c(1, 2, 0)) r <- tda_rfit(d) r$relations[[1]]d <- rbind(c(0, 2, 1), c(2, 0, 2), c(1, 2, 0)) r <- tda_rfit(d) r$relations[[1]]
TDA's rmod on binary item response data.
tda_rmod(x, ...)tda_rmod(x, ...)
x |
matrix of 0/1 responses, persons in rows. |
... |
passed to |
centered item parameters in $items (joint ML is
identified only up to a constant, and its item estimates carry
the known upward bias of about k/(k-1) for k items), the
pattern parameters in $patterns, and the maximised log
likelihood in $logLik.
set.seed(1) ab <- rnorm(80) x <- sapply(c(-1, 1), function(d) rbinom(80, 1, plogis(ab - d))) tda_rmod(x)$items # easier item first, harder secondset.seed(1) ab <- rnorm(80) x <- sapply(c(-1, 1), function(d) rbinom(80, 1, plogis(ab - d))) tda_rmod(x)$items # easier item first, harder second
tda_rng is a stateful generator reproducing TDA's rd/
rdn bit for bit. tda_runif/tda_rnorm are convenience
wrappers around a fresh generator, for when only one of rd/
rdn is needed; tda_rng itself is what a nvar()
block using both together needs, since they draw from one
continuous, shared stream, not two independent ones.
tda_rng(seed = 13421773) tda_runif(n, seed = 13421773) tda_rnorm(n, seed = 13421773)tda_rng(seed = 13421773) tda_runif(n, seed = 13421773) tda_rnorm(n, seed = 13421773)
seed |
the starting value. TDA's default is 13421773. |
n |
how many numbers to draw, for |
random1() is the multiplicative generator behind rd():
the seed is multiplied by 3125 modulo 2^26, in three steps of 25, 25
and 5. normal() (behind rdn(); rdn1 is a
different pseudo-variable,
backed by a different function, normal1(), not this one) draws
random1() values in a rejection loop (Marsaglia's polar method,
J.R. Bell's ACM Algorithm 334) and returns two standard normal
deviates per accepted draw, the second cached and returned on the next
call with no further random1() draws consumed – so the number
of underlying uniform draws per rdn() call varies, and cannot
be precomputed or batched independently of rd() calls
interleaved with it.
This is why nvar()'s evaluation order matters: it
evaluates one case fully, one variable at a time in
definition order, before moving to the next case – not all of one
variable's values before the next. A block defining X = rd
then E = rdn draws X's case 1, then E's case 1
(however many random1() calls that costs), then X's
case 2, and so on – tda_runif(256) followed separately by
tda_rnorm(256) does not reproduce this at all, even with the
same seed, since it draws all of X before touching E's
own share of the stream. Reproducing that exact case-by-case
interleaving is what tda_rng's stateful $rd()/$rdn()
are for: call them in the same order, one case at a time, and the
shared state advances exactly as TDA's evaluation loop would.
It matters because several of the shipped examples select a subsample
with isel = le(rd(0,1), p), or generate simulated data with
rd/rdn together (doc/npreg1.cf's worked
example, say). Reproducing their numbers needs the same stream, and
R's generators will not do – this is not a question of setting
a seed. tda_runif/tda_rnorm reproduce
random1()/normal() bit for bit.
tda_rng returns a list with two functions, $rd(n
= 1, a = 0, b = 1) and $rdn(n = 1), each drawing n
values from the shared stream (a single value by default, for
calling one at a time in an interleaved loop) and returning a
length-n numeric vector (or a single number, for the
default n = 1). $rd()'s a/b are the
range – TDA's rd(a, b); $rd() alone is
[0, 1), matching rd with no arguments.
tda_runif/tda_rnorm return a plain numeric vector of
length n directly.
tda_runif(5) # X = rd, E = rdn in the same nvar() block -- interleaved, not two # separate streams; compare doc/npreg1.cf's worked example. gen <- tda_rng() n <- 256 X <- E <- numeric(n) for (i in seq_len(n)) { X[i] <- gen$rd() E[i] <- 0.32 * gen$rdn() }tda_runif(5) # X = rd, E = rdn in the same nvar() block -- interleaved, not two # separate streams; compare doc/npreg1.cf's worked example. gen <- tda_rng() n <- 256 X <- E <- numeric(n) for (i in seq_len(n)) { X[i] <- gen$rd() E[i] <- 0.32 * gen$rdn() }
TDA's rod: rank orders per record, with options for
standardization, distances, medians, and tabulation.
tda_rod( x, statistic = c("standard", "distances", "central", "graph", "graph5", "graph6", "between", "table"), ... )tda_rod( x, statistic = c("standard", "distances", "central", "graph", "graph5", "graph6", "between", "table"), ... )
x |
matrix of rank values, one order per row. |
statistic |
one of "standard", "distances", "central", "graph", "graph5", "graph6", "between", "table". |
... |
passed to |
the rank orders as a data frame in $orders
(plus a count column for the table statistic), with the full
protocol in $output.
r <- tda_rod(rbind(c(1, 2, 3), c(2, 3, 1), c(3, 1, 2))) r$ordersr <- tda_rod(rbind(c(1, 2, 3), c(2, 3, 1), c(3, 1, 2))) r$orders
TDA's rplz: the postcode-data variant of the semicolon CSV
reader; like tda_rcsv it renders to the protocol.
tda_rplz(file, ...)tda_rplz(file, ...)
file |
the input file. |
... |
passed to |
a data frame, one row per record: id, type, place count, the three leading fields, and the place list.
# the PLZ export shape: a header line, then three semicolon fields # of metadata before the place list (commas separate places, colons # start sub-lists) f <- tempfile() writeLines(c("plz;land;kreis;orte", "01067;SN;Dresden;Dresden,Altstadt", "01069;SN;Dresden;Dresden,Suedvorstadt"), f) tda_rplz(f) # one row per record, places joined# the PLZ export shape: a header line, then three semicolon fields # of metadata before the place list (commas separate places, colons # start sub-lists) f <- tempfile() writeLines(c("plz;land;kreis;orte", "01067;SN;Dresden;Dresden,Altstadt", "01069;SN;Dresden;Dresden,Suedvorstadt"), f) tda_rplz(f) # one row per record, places joined
rrdat.1 is the data file used by nearly every example in
examples/ehhnew, the command files accompanying Blossfeld and
Rohwer, Techniques of Event History Modeling. This reads it and
names its columns as the examples do.
tda_rrdat(file = NULL, states = c(2, 4), upward = c("gt", "ge"))tda_rrdat(file = NULL, states = c(2, 4), upward = c("gt", "ge"))
file |
path to |
states |
2 for a single destination state, 4 to distinguish upward, lateral and downward job changes. |
upward |
with |
A data frame of 600 episodes.
The data are 600 job episodes of 201 randomly selected respondents
from the German Life History Study (GLHS), collected at the
Max-Planck-Institut für Bildungsforschung, Berlin, in 1981-1983 for
the birth cohorts 1929-31, 1939-41 and 1949-51 (Mayer and Brückner
1989). TDA's manual (section 3.3.3) thanks Karl Ulrich Mayer and
Hans-Peter Blossfeld for providing the data set; it has shipped with
TDA since 1994 as rrdat.1 and is the example throughout the
manual and the book.
Mayer, K. U., Brückner, E. (1989). Lebensverläufe und Wohlfahrtsentwicklung. Konzeption, Design und Methodik der Erhebung von Lebensverläufen der Geburtsjahrgänge 1929-1931, 1939-1941, 1949-1951. Berlin: Max-Planck-Institut für Bildungsforschung.
Blossfeld, H.-P., Rohwer, G. (2002). Techniques of Event History Modeling. New Approaches to Causal Analysis, 2nd ed. Mahwah, NJ: Lawrence Erlbaum.
The derived variables are the ones the examples define in their
nvar blocks:
duration of the episode, TFin - TStart + 1.
destination state. With states = 2 it is 1 for a job
change and 0 for a censored episode, which is what most of the
examples use. With states = 4 the job changes are split by
prestige: 1 upward, 2 lateral, 3 downward.
labour force experience before the episode,
TStart - TE.
number of previous jobs, NOJ - 1.
birth cohort indicators, 1939-41 and 1949-51.
d <- tda_rrdat() tda_ltb(Surv(TFP, DES) ~ 1, d, tp = seq(0, 500, by = 30))d <- tda_rrdat() tda_ltb(Surv(TFP, DES) ~ 1, d, tp = seq(0, 500, by = 30))
TDA's rsys: restores a data matrix written by wsys.
Verified in the suite as a write/read round trip.
tda_rsys(file, ...)tda_rsys(file, ...)
file |
the system file. |
... |
passed to |
the restored data as a data frame, like
tda_read_sys, which this calls.
d0 <- data.frame(id = 1:3, x = c(1.5, 2, 3)) dr <- tempfile("tda"); dir.create(dr) write.table(d0, file.path(dr, "d.dat"), row.names = FALSE, col.names = FALSE) invisible(tda_run(c("nvar(dfile=d.dat, ID[4.0]=c1, X[8.2]=c2);", "wsys = t.sys;"), dir = dr)) tda_rsys(file.path(dr, "t.sys")) # the values restoredd0 <- data.frame(id = 1:3, x = c(1.5, 2, 3)) dr <- tempfile("tda"); dir.create(dr) write.table(d0, file.path(dr, "d.dat"), row.names = FALSE, col.names = FALSE) invisible(tda_run(c("nvar(dfile=d.dat, ID[4.0]=c1, X[8.2]=c2);", "wsys = t.sys;"), dir = dr)) tda_rsys(file.path(dr, "t.sys")) # the values restored
The escape hatch: anything the typed interfaces do not cover can be written
as TDA commands and run directly. tda_run writes a data frame out and
runs a script against it; tda_run_cf runs an existing command file.
tda_run( commands, data = NULL, dir = tempfile("tda"), data_file = "data.dat", ... ) tda_run_cf( file, maxnv = 2000L, maxmat = 200L, args = character(), echo = FALSE, data = NULL )tda_run( commands, data = NULL, dir = tempfile("tda"), data_file = "data.dat", ... ) tda_run_cf( file, maxnv = 2000L, maxmat = 200L, args = character(), echo = FALSE, data = NULL )
commands |
a character vector of TDA commands. |
data |
optional data frame, written to |
dir |
working directory; TDA's output files are left there. |
data_file |
name for the written data file. |
... |
passed to |
file |
an existing command file. |
maxnv, maxmat
|
limits passed to TDA at start-up. |
args |
extra command line arguments. |
echo |
print TDA's output as it is read. |
An object of class tda_result: $output and
$stderr (the captured text), $dir, $cf and
$files (the working directory, the command file, and the
files the run produced), $commands (the command file's
lines, kept on the object), $diagnostics (every error,
warning or note line TDA printed, see tda_diagnostics),
$exports (TDA's numbers, handed
over as matrices in parallel with the printed output),
$errors (how many errors TDA reported) and $status
(TDA's exit code, which is 0 for a run that reported errors as well
– test $errors, not this).
Other TDA infrastructure:
tda_ccnt(),
tda_help(),
tda_output(),
tda_read_table(),
tda_write_data()
tda_run("mem;") # tda_run_cf: the same thing, but the command file already exists on disk f <- tempfile() writeLines("mem;", f) r <- tda_run_cf(f) cat(r$output, sep = "\n")tda_run("mem;") # tda_run_cf: the same thing, but the command file already exists on disk f <- tempfile() writeLines("mem;", f) r <- tda_run_cf(f) cat(r$output, sep = "\n")
TDA's scla on a distance matrix.
tda_scla(d, ...)tda_scla(d, ...)
d |
symmetric distance matrix. |
... |
passed to |
clusters, the rows TDA wrote (one numeric vector per
line of the separable-cluster listing), and output.
d <- as.matrix(dist(c(0, 0.1, 5, 5.1))) r <- tda_scla(d) r$clustersd <- as.matrix(dist(c(0, 0.1, 5, 5.1))) r <- tda_scla(d) r$clusters
tda_sd reaches any of TDA's spatial commands; the named functions
are the ones with an obvious meaning. The spatial data is opened with
sdnvar first, which is what the commands operate on.
tda_sd(s, cmd, options = list(), rhs = NULL, setup = character(), ...)tda_sd(s, cmd, options = list(), rhs = NULL, setup = character(), ...)
s |
a |
cmd |
the command name, e.g. |
options |
a named list of options for the command. |
rhs |
the command's right-hand side, when it takes one. |
setup |
extra commands to run before it, such as a PostScript setup. |
... |
passed to |
An object carrying the run and, where the command writes one, a
table.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_polygons(),
tda_read_dbf(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd_analyses,
tda_sd_ps3(),
tda_spatial()
d <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) r <- tda_sd(s, "sdinf") cat(r$run$output, sep = "\n")d <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) r <- tda_sd(s, "sdinf") cat(r$run$output, sep = "\n")
One function per spatial command, each a thin wrapper: the command name,
the options it takes and the table TDA writes. They all work on a
tda_spatial structure, however it was built – from a data
frame with tda_spatial, from a shapefile with
tda_read_shapefile, or from line segments with
tda_polygons.
tda_sd_info(s, ...) tda_sd_relations(s, ...) tda_sd_neighbours(s, ...) tda_sd_enclosing(s, shape = c("rectangle", "hull"), ...) tda_sd_voronoi(s, ...) tda_sd_select(s, ...) tda_sd_intersect(s, ...) tda_sd_lines(s, ...) tda_sd_points(s, ...) tda_sd_data(s, ...) tda_sd_clip(s, rec, ...)tda_sd_info(s, ...) tda_sd_relations(s, ...) tda_sd_neighbours(s, ...) tda_sd_enclosing(s, shape = c("rectangle", "hull"), ...) tda_sd_voronoi(s, ...) tda_sd_select(s, ...) tda_sd_intersect(s, ...) tda_sd_lines(s, ...) tda_sd_points(s, ...) tda_sd_data(s, ...) tda_sd_clip(s, rec, ...)
s |
a |
... |
options for the command. |
shape |
for |
rec |
the clipping rectangle, |
tda_sd_info reports what a structure holds: how many points, lines
and polygons, and the bounding box. tda_sd_voronoi builds a
Voronoi diagram and the Delaunay triangulation of the points;
tda_sd_enclosing the enclosing rectangle or the convex hull,
tda_sd_neighbours nearest-neighbour lists, and
tda_sd_relations the relations between objects.
tda_sd_select picks out objects in a region – like
tda_sd_clip, it needs rec (as an option:
tda_sd_select(s, rec = "0,0,1,1")), which TDA will not guess. The
polygon operations – tda_sd_intersect, tda_sd_lines,
tda_sd_points and tda_sd_clip – each write a record file
that comes back as a table.
An object carrying the run and, where there is one, a table.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_polygons(),
tda_read_dbf(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd(),
tda_sd_ps3(),
tda_spatial()
# four points, as a spatial structure d <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) # what is in it tda_sd_info(s) # the Voronoi diagram of those points: what sdvd writes is itself a # spatial data file (points for the Voronoi vertices, lines for the # edges), so plot() reads it back with the input's plot machinery v <- tda_sd_voronoi(s, opt = 2) plot(v, xlim = c(-0.5, 1.5), ylim = c(-0.5, 1.5)) # clip to a rectangle; rec is required, TDA will not guess one tda_sd_clip(s, c(0, 0, 0.5, 0.5)) # a select needs one too, the region to select within tda_sd_select(s, rec = "0,0,1,1")$table # relations and nearest neighbours, on the same points tda_sd_relations(s) tda_sd_neighbours(s) tda_sd_enclosing(s, shape = "hull")$table # polygon data: typ = 3 groups consecutive rows sharing an id into one # polygon each -- here two squares poly <- data.frame(id = c(1, 1, 1, 1, 2, 2, 2, 2), x = c(0, 2, 2, 0, 3, 5, 5, 3), y = c(0, 0, 2, 2, 0, 0, 2, 2)) sp <- tda_spatial(poly, type = 3) tda_sd_data(sp)$table # the polygons' own vertex coordinates back out # tda_sd_intersect/tda_sd_lines/tda_sd_points compare polygons against a # *different* object type (points or lines) already in the same spatial # structure -- with only the two polygons above and nothing else, there # is nothing for them to find, which is what they correctly report tda_sd_lines(sp)$table tda_sd_intersect(sp)$table tda_sd_points(sp)$table # a real shapefile, if one is available: sf's example data, North # Carolina counties -- everything above works on synthetic points or two # squares; this is what these look like on real, complicated polygons if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) print(tda_sd_info(nc)) # 108 counties, 2421 vertices # relations' real answer is printed, not written to a file -- $text # holds the boundary comparisons TDA's console output shows head(tda_sd_relations(nc)$text, 4) # a neighbour network needs line data; a set of polygons alone # legitimately has none to report -- 0 nodes, 0 edges, not a bug tda_sd_neighbours(nc)$text tda_sd_enclosing(nc)$table # the whole state's bounding box # select/clip write one record per vertex, not all the same length -- # a polygon's header row, then that many coordinate pairs, the # same ragged shape as sdvd's edge list above -- a proper rectangular # table is what tda_sd_data() gives instead tda_sd_select(nc, rec = "-79,35,-77,36")$table # counties in a region tda_sd_clip(nc, c(-79, 35, -77, 36))$table # the same, cut to it head(tda_sd_data(nc)$table) # every county's vertices, # as an ordinary data frame }# four points, as a spatial structure d <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) # what is in it tda_sd_info(s) # the Voronoi diagram of those points: what sdvd writes is itself a # spatial data file (points for the Voronoi vertices, lines for the # edges), so plot() reads it back with the input's plot machinery v <- tda_sd_voronoi(s, opt = 2) plot(v, xlim = c(-0.5, 1.5), ylim = c(-0.5, 1.5)) # clip to a rectangle; rec is required, TDA will not guess one tda_sd_clip(s, c(0, 0, 0.5, 0.5)) # a select needs one too, the region to select within tda_sd_select(s, rec = "0,0,1,1")$table # relations and nearest neighbours, on the same points tda_sd_relations(s) tda_sd_neighbours(s) tda_sd_enclosing(s, shape = "hull")$table # polygon data: typ = 3 groups consecutive rows sharing an id into one # polygon each -- here two squares poly <- data.frame(id = c(1, 1, 1, 1, 2, 2, 2, 2), x = c(0, 2, 2, 0, 3, 5, 5, 3), y = c(0, 0, 2, 2, 0, 0, 2, 2)) sp <- tda_spatial(poly, type = 3) tda_sd_data(sp)$table # the polygons' own vertex coordinates back out # tda_sd_intersect/tda_sd_lines/tda_sd_points compare polygons against a # *different* object type (points or lines) already in the same spatial # structure -- with only the two polygons above and nothing else, there # is nothing for them to find, which is what they correctly report tda_sd_lines(sp)$table tda_sd_intersect(sp)$table tda_sd_points(sp)$table # a real shapefile, if one is available: sf's example data, North # Carolina counties -- everything above works on synthetic points or two # squares; this is what these look like on real, complicated polygons if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) print(tda_sd_info(nc)) # 108 counties, 2421 vertices # relations' real answer is printed, not written to a file -- $text # holds the boundary comparisons TDA's console output shows head(tda_sd_relations(nc)$text, 4) # a neighbour network needs line data; a set of polygons alone # legitimately has none to report -- 0 nodes, 0 edges, not a bug tda_sd_neighbours(nc)$text tda_sd_enclosing(nc)$table # the whole state's bounding box # select/clip write one record per vertex, not all the same length -- # a polygon's header row, then that many coordinate pairs, the # same ragged shape as sdvd's edge list above -- a proper rectangular # table is what tda_sd_data() gives instead tda_sd_select(nc, rec = "-79,35,-77,36")$table # counties in a region tda_sd_clip(nc, c(-79, 35, -77, 36))$table # the same, cut to it head(tda_sd_data(nc)$table) # every county's vertices, # as an ordinary data frame }
sdplot31, sdplot32 and sdplot33 draw spatial objects
in a three-dimensional coordinate system rather than the flat one
plot() uses. That system comes from psetup3, so the ranges
of all three axes and the direction the plot is viewed from are set up
once with tda_sd_ps3(), the 3-D counterpart of tda_ps
– tda_sd_pl3_points(), tda_sd_pl3_lines() and
tda_sd_pl3_polygons() then add drawing commands to it the way
tda_pl_lines and its siblings add to a tda_ps
session, and plot() draws the result. tda_pl_text3
and tda_pl_points3 (TDA's 3-D-aware commands, not tied
to a spatial file) work on a tda_sd_ps3 session too, which is how
a title or an extra marker gets added – TDA's ordinary plabel()
(tda_pl_labels) is 2-D only and refuses outright with
“current coordinate system is 3-dimensional” if tried here.
tda_pl_lines3, by contrast, does not work on a
tda_sd_ps3 session: it folds its coordinates into a regular
nvar variable, which needs an ordinary nvar declaration
that a spatial session, declared with sdnvar instead, does not
have – “Syntax error or undefined variables”. Use
tda_pl_points3 instead, which takes literal coordinates and
needs no such declaration.
tda_sd_ps3( s, xlim = NULL, ylim = NULL, zlim, view = c(30, 30), width = 100, ... ) tda_sd_pl3(p, cmd, ..., zvar = NULL) tda_sd_pl3_points(p, symbol = 1, size = NULL, zvar = NULL, zval = NULL, ...) tda_sd_pl3_lines(p, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ...) tda_sd_pl3_polygons( p, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ... ) tda_sd_plot3( s, z, xlim = NULL, ylim = NULL, view = c(30, 30), width = 100, newpage = TRUE, symbol = 1, size = NULL, zvar = NULL, zval = NULL, ... ) tda_sd_plot3_lines( s, z, xlim = NULL, ylim = NULL, view = c(30, 30), width = 100, newpage = TRUE, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ... ) tda_sd_plot3_polygons( s, z, xlim = NULL, ylim = NULL, view = c(30, 30), width = 100, newpage = TRUE, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ... )tda_sd_ps3( s, xlim = NULL, ylim = NULL, zlim, view = c(30, 30), width = 100, ... ) tda_sd_pl3(p, cmd, ..., zvar = NULL) tda_sd_pl3_points(p, symbol = 1, size = NULL, zvar = NULL, zval = NULL, ...) tda_sd_pl3_lines(p, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ...) tda_sd_pl3_polygons( p, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ... ) tda_sd_plot3( s, z, xlim = NULL, ylim = NULL, view = c(30, 30), width = 100, newpage = TRUE, symbol = 1, size = NULL, zvar = NULL, zval = NULL, ... ) tda_sd_plot3_lines( s, z, xlim = NULL, ylim = NULL, view = c(30, 30), width = 100, newpage = TRUE, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ... ) tda_sd_plot3_polygons( s, z, xlim = NULL, ylim = NULL, view = c(30, 30), width = 100, newpage = TRUE, symbol = NULL, size = NULL, zvar = NULL, zval = NULL, ... )
s |
a |
xlim, ylim
|
ranges of the x and y axes, taken from the structure when not given. |
view |
direction of the projection, as longitude and latitude in degrees; TDA's default is 30,30. |
width |
horizontal size of the plot in mm. |
... |
further options for the command. |
p |
a |
cmd |
the TDA command name. |
zvar |
an attribute carried in from the source file, used as each
point's or polygon's height instead of a flat |
symbol |
marker symbol to draw at each point, as TDA's |
size |
marker size in mm. |
zval |
a single height for every point or polygon, when they do
not have their own via |
z, zlim
|
the range of the z axis, as two numbers. Unlike x and y there is nothing in the spatial file to take it from, so it has no default. |
newpage |
start a new grid page. |
A north-up view of geographic data (longitude/latitude, the
way an ordinary map looks) is view = c(-90, 90), not TDA's
own default of c(30, 30). This is a property of TDA's
azimuth/elevation convention
itself, not of any particular dataset, so it is the same for any
longitude/latitude data.
Each of the three drawing commands only draws one kind of
object, silently drawing nothing at all for any other kind:
tda_sd_pl3_points draws points, tda_sd_pl3_lines draws
lines, tda_sd_pl3_polygons draws polygons. A shapefile of
counties, say, is polygons – points on it draws nothing, not because
anything is wrong, but because it is looking for points that are not
there. Check tda_sd_info first if it is not obvious which
kind a structure holds.
tda_sd_plot3, tda_sd_plot3_lines and
tda_sd_plot3_polygons are one-shot equivalents – set up a
session, add one drawing command, plot it – kept for the simple case
where nothing else needs adding to the same plot.
tda_sd_ps3() and the tda_sd_pl3_* functions return
the session, with the command added. plot() on a session, and
the one-shot functions, draw the plot and return the parsed drawing
operations invisibly.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_polygons(),
tda_read_dbf(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd(),
tda_sd_analyses,
tda_spatial()
set.seed(1) d <- data.frame(id = 1:8, x = runif(8), y = runif(8), z = runif(8)) s <- tda_spatial(d, attributes = "z") pdf(NULL) # composable form: build a session, add commands, plot it -- a title # (via TDA's 3-D-aware text command, not the 2-D-only plabel) and an # extra marker layered onto the same plot as the data p <- tda_sd_ps3(s, zlim = c(0, 1)) p <- tda_sd_pl3_points(p, symbol = 1, size = 3) p <- tda_pl_text3(p, "eight points", at = c(0.5, 0.5, 0.9)) plot(p) # the one-shot form, for when nothing else needs adding tda_sd_plot3(s, z = c(0, 1), symbol = 1, size = 3) # plot3_lines wants line-type spatial data, not scattered points -- # a single connected line here, four vertices sharing one id ln <- data.frame(id = 1, x = c(0, 0.3, 0.6, 1), y = c(0, 0.4, 0.5, 1), z = c(0, 0.3, 0.6, 1)) sl <- tda_spatial(ln, type = 2, attributes = "z") tda_sd_plot3_lines(sl, z = c(0, 1), symbol = 1) # plot3_polygons draws flat polygons at a single height in the z range, # or, given zvar, raises each one into a prism of that height -- h here poly <- data.frame(id = 1, x = c(0, 2, 2, 0), y = c(0, 0, 2, 2), h = c(2, 2, 2, 2)) sp <- tda_spatial(poly, type = 3, attributes = "h") tda_sd_plot3_polygons(sp, z = c(0, 3), zvar = "h") # a real shapefile, if one is available: sf's example data, North # Carolina counties, in a proper north-up view, with city markers and # labels layered on via TDA's 3-D-aware point/text commands if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) cities <- data.frame( name = c("Raleigh", "Charlotte"), lon = c(-78.6382, -80.8431), lat = c(35.7796, 35.2271)) pnc <- tda_sd_ps3(nc, zlim = c(0, 1), view = c(-90, 90)) pnc <- tda_sd_pl3_polygons(pnc) # fs= is the marker/font size in mm, independent for each command -- # the default marker size (2mm) reads as a large blob at this map's # own small default width (100mm), so it is turned down here, and # the default text size turned up, rather than using both defaults pnc <- tda_pl_points3(pnc, cities$lon, cities$lat, rep(0.5, 2), symbol = 5, size = 0.8, lty = 0) for (i in seq_len(nrow(cities))) pnc <- tda_pl_text3(pnc, cities$name[i], at = c(cities$lon[i] + 0.35, cities$lat[i], 0.5), fs = 4) plot(pnc) } dev.off()set.seed(1) d <- data.frame(id = 1:8, x = runif(8), y = runif(8), z = runif(8)) s <- tda_spatial(d, attributes = "z") pdf(NULL) # composable form: build a session, add commands, plot it -- a title # (via TDA's 3-D-aware text command, not the 2-D-only plabel) and an # extra marker layered onto the same plot as the data p <- tda_sd_ps3(s, zlim = c(0, 1)) p <- tda_sd_pl3_points(p, symbol = 1, size = 3) p <- tda_pl_text3(p, "eight points", at = c(0.5, 0.5, 0.9)) plot(p) # the one-shot form, for when nothing else needs adding tda_sd_plot3(s, z = c(0, 1), symbol = 1, size = 3) # plot3_lines wants line-type spatial data, not scattered points -- # a single connected line here, four vertices sharing one id ln <- data.frame(id = 1, x = c(0, 0.3, 0.6, 1), y = c(0, 0.4, 0.5, 1), z = c(0, 0.3, 0.6, 1)) sl <- tda_spatial(ln, type = 2, attributes = "z") tda_sd_plot3_lines(sl, z = c(0, 1), symbol = 1) # plot3_polygons draws flat polygons at a single height in the z range, # or, given zvar, raises each one into a prism of that height -- h here poly <- data.frame(id = 1, x = c(0, 2, 2, 0), y = c(0, 0, 2, 2), h = c(2, 2, 2, 2)) sp <- tda_spatial(poly, type = 3, attributes = "h") tda_sd_plot3_polygons(sp, z = c(0, 3), zvar = "h") # a real shapefile, if one is available: sf's example data, North # Carolina counties, in a proper north-up view, with city markers and # labels layered on via TDA's 3-D-aware point/text commands if (requireNamespace("sf", quietly = TRUE)) { nc <- tda_read_shapefile(system.file("shape/nc.shp", package = "sf")) cities <- data.frame( name = c("Raleigh", "Charlotte"), lon = c(-78.6382, -80.8431), lat = c(35.7796, 35.2271)) pnc <- tda_sd_ps3(nc, zlim = c(0, 1), view = c(-90, 90)) pnc <- tda_sd_pl3_polygons(pnc) # fs= is the marker/font size in mm, independent for each command -- # the default marker size (2mm) reads as a large blob at this map's # own small default width (100mm), so it is turned down here, and # the default text size turned up, rather than using both defaults pnc <- tda_pl_points3(pnc, cities$lon, cities$lat, rep(0.5, 2), symbol = 5, size = 0.8, lty = 0) for (i in seq_len(nrow(cities))) pnc <- tda_pl_text3(pnc, cities$name[i], at = c(cities$lon[i] + 0.35, cities$lat[i], 0.5), fs = 4) plot(pnc) } dev.off()
The set-valued counterpart of tda_iddf: each case's
observation is a set of possible categories (not necessarily a
single value, and not necessarily an interval), and the distribution
function is only identified up to bounds consistent with every case's
own set.
tda_sddf( sets, categories = NULL, self_consistent = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... )tda_sddf( sets, categories = NULL, self_consistent = FALSE, control = NULL, options = list(), dir = tempfile("tda"), ... )
sets |
a list, one element per case, each the vector of category
labels that case's set contains – |
categories |
the full list of possible categories; by default,
the sorted union of everything appearing in |
self_consistent |
also compute the self-consistent distribution
( |
control |
convergence settings ( |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object carrying a table of categories and the
distribution function's bounds and mean at each.
Other interval-valued data:
tda_bounds(),
tda_idf(),
tda_ilsreg(),
tda_imean(),
tda_imreg(),
tda_inpreg(),
tda_ivar1(),
tda_ivreg()
# TDA's manual example: o1={1}, o2={2}, o3={3}, o4={1,2}, o5={2,3} fit <- tda_sddf(list(1, 2, 3, c(1, 2), c(2, 3))) fit$table # the same data, already read in as indicator columns (e.g. from # id1.dat via read.table()) -- no conversion needed id1 <- data.frame(X1 = c(1, 0, 0, 1, 0), X2 = c(0, 1, 0, 1, 1), X3 = c(0, 0, 1, 0, 1)) tda_sddf(id1)$table# TDA's manual example: o1={1}, o2={2}, o3={3}, o4={1,2}, o5={2,3} fit <- tda_sddf(list(1, 2, 3, c(1, 2), c(2, 3))) fit$table # the same data, already read in as indicator columns (e.g. from # id1.dat via read.table()) -- no conversion needed id1 <- data.frame(X1 = c(1, 0, 0, 1, 0), X2 = c(0, 1, 0, 1, 1), X3 = c(0, 0, 1, 0, 1)) tda_sddf(id1)$table
TDA's segr: a dissimilarity D-Index, a variance ratio and a Gini
coefficient between two groups, across one or more
categorical class variables. The D-Index is
, the share of one group that
would have to change class for the two groups' distributions across
classes to match exactly.
tda_segr( data, group, variables = NULL, options = list(), dir = tempfile("tda") )tda_segr( data, group, variables = NULL, options = list(), dir = tempfile("tda") )
data |
a data frame. |
group |
the grouping variable, as a name or a vector: coded 0 and
1 (or |
variables |
one or more categorical class variables from
|
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
An object carrying a table: one row per variable in
variables, with the number of classes, cases in each group,
and the three measures.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_subm()
set.seed(1) n <- 100 d <- data.frame(group = rbinom(n, 1, 0.5), class1 = sample(1:3, n, replace = TRUE), class2 = sample(1:2, n, replace = TRUE)) tda_segr(d, group = "group", variables = c("class1", "class2"))set.seed(1) n <- 100 d <- data.frame(group = rbinom(n, 1, 0.5), class1 = sample(1:3, n, replace = TRUE), class2 = sample(1:2, n, replace = TRUE)) tda_segr(d, group = "group", variables = c("class1", "class2"))
Runs TDA's seq; against the sequence structure(s) given –
the same table TDA itself prints after defining them, listing each
structure's number of state variables, its time axis, and the
distinct states it actually contains.
tda_seq_info( sequences, data = NULL, options = list(), type = 1, dir = tempfile("tda"), ... )tda_seq_info( sequences, data = NULL, options = list(), type = 1, dir = tempfile("tda"), ... )
sequences |
a data frame or matrix, one row per case, one column
per time point, in order – the same shape |
data |
optional data frame |
options |
a named list of further TDA options, passed through. |
type |
the sequence data type, TDA's |
dir |
working directory. |
... |
passed to |
A data frame, one row per sequence structure: sn,
type, variables (number of time points),
tmin/tmax (the time axis), nstates, and
states (a list column, the actual state values, since their
count varies by structure).
Other sequence analysis:
tda_evalfi(),
tda_fml(),
tda_frml(),
tda_seqgc(),
tda_seqm(),
tda_seqmd(),
tda_seqpe(),
tda_seqpm()
s <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), Y2 = c(2, 1, 1)) tda_seq_info(s) # several structures at once, the same way tda_seqev's sn= does d <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), S0 = c(1, 3, 1), S1 = c(3, 1, 3)) tda_seq_info(list(c("Y0", "Y1"), c("S0", "S1")), data = d)s <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), Y2 = c(2, 1, 1)) tda_seq_info(s) # several structures at once, the same way tda_seqev's sn= does d <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), S0 = c(1, 3, 1), S1 = c(3, 1, 3)) tda_seq_info(list(c("Y0", "Y1"), c("S0", "S1")), data = d)
Descriptive summaries of a sequence data structure: tda_seqgc
basic characteristics per case (length, number of states visited,
number of transitions, time spent in and number of episodes in each
state), tda_seqlg sequence lengths and gaps, tda_seqsd
the distribution of states over time (how many cases are in each state
at each time point), tda_seqsi a state indicator matrix (one
row per case-time combination, one column per state, 1 where that case
is in that state at that time), and tda_seqen entropy of the
state distribution at each time point. Column names come from TDA's
own description of each output, not a fixed layout guessed in advance
– tda_seqgc's columns, for instance, depend on how many
distinct states the data actually has.
tda_seqgc( sequences, select = NULL, variables = NULL, id = NULL, options = list(), type = 1, dir = tempfile("tda"), ... ) tda_seqlg( sequences, select = NULL, variables = NULL, id = NULL, options = list(), type = 1, dir = tempfile("tda"), ... ) tda_seqsd( sequences, select = NULL, variables = NULL, options = list(), dir = tempfile("tda"), ... ) tda_seqsi( sequences, tp, select = NULL, variables = NULL, id = NULL, options = list(), dir = tempfile("tda"), ... ) tda_seqen( sequences, select = NULL, variables = NULL, options = list(), dir = tempfile("tda"), ... )tda_seqgc( sequences, select = NULL, variables = NULL, id = NULL, options = list(), type = 1, dir = tempfile("tda"), ... ) tda_seqlg( sequences, select = NULL, variables = NULL, id = NULL, options = list(), type = 1, dir = tempfile("tda"), ... ) tda_seqsd( sequences, select = NULL, variables = NULL, options = list(), dir = tempfile("tda"), ... ) tda_seqsi( sequences, tp, select = NULL, variables = NULL, id = NULL, options = list(), dir = tempfile("tda"), ... ) tda_seqen( sequences, select = NULL, variables = NULL, options = list(), dir = tempfile("tda"), ... )
sequences |
a data frame or matrix of one column per time point,
in order, the same shape |
select |
optional expression ( |
variables |
which columns of |
id |
further columns of |
options |
a named list of further TDA options, passed through. |
type |
the sequence data type, TDA's |
dir |
working directory. |
... |
passed to |
tp |
for |
A data frame, one row per case (tda_seqgc,
tda_seqlg) or per time point (tda_seqsd,
tda_seqen), or per case-time combination (tda_seqsi).
Other sequence analysis:
tda_evalfi(),
tda_fml(),
tda_frml(),
tda_seq_info(),
tda_seqm(),
tda_seqmd(),
tda_seqpe(),
tda_seqpm()
s <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), Y2 = c(2, 1, 1), Y3 = c(1, 1, 2), Y4 = c(1, 1, 2), Y5 = c(3, 3, 3)) tda_seqgc(s) # length, states visited, transitions, time in each state tda_seqlg(s) # lengths and gaps tda_seqsd(s) # how many cases are in each state, at each time point tda_seqsi(s, tp = "0(1)5") # state indicator matrix tda_seqen(s) # entropy of the state distribution at each time point # an id column alongside the sequence, positively selected rather # than requiring s2[, -1] s2 <- cbind(id = 101:103, s) tda_seqgc(s2, variables = names(s), id = "id")s <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), Y2 = c(2, 1, 1), Y3 = c(1, 1, 2), Y4 = c(1, 1, 2), Y5 = c(3, 3, 3)) tda_seqgc(s) # length, states visited, transitions, time in each state tda_seqlg(s) # lengths and gaps tda_seqsd(s) # how many cases are in each state, at each time point tda_seqsi(s, tp = "0(1)5") # state indicator matrix tda_seqen(s) # entropy of the state distribution at each time point # an id column alongside the sequence, positively selected rather # than requiring s2[, -1] s2 <- cbind(id = 101:103, s) tda_seqgc(s2, variables = names(s), id = "id")
Computes proximities between sequences and returns a dist, so
hclust, cmdscale and the rest work on the result directly.
tda_seqm( sequences, method = 1, indel = NULL, subcost = NULL, common_length = FALSE, max_restrict = NULL, compare_with = NULL, preprocess = NULL, n_random = NULL, print = NULL, dp_matrix = FALSE, options = list(), dir = tempfile("tda"), ... )tda_seqm( sequences, method = 1, indel = NULL, subcost = NULL, common_length = FALSE, max_restrict = NULL, compare_with = NULL, preprocess = NULL, n_random = NULL, print = NULL, dp_matrix = FALSE, options = list(), dir = tempfile("tda"), ... )
sequences |
one row per case, one column per time point – a data
frame or matrix, or a list of vectors of differing lengths, one per
case, padded with |
method |
optimal matching method, TDA's |
indel |
indel cost, TDA's |
subcost |
substitution costs, TDA's |
common_length |
require all sequences to share one length before
aligning them ( |
max_restrict |
restrict the alignment search ( |
compare_with |
compare every sequence against specific sequences
rather than every pair ( |
preprocess |
one or both of |
n_random |
request an approximate random sample of this many
sequence pairs rather than comparing every pair – |
print |
add further columns to |
dp_matrix |
capture TDA's step-by-step dump of the alignment
algorithm's internal dynamic-programming matrix ( |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
Ordinarily a dist, with the pairwise table kept in its
pairs attribute, and, with print = "sequential", the
per-time-point breakdown also in dist_by_time (see
print). Either shape also carries states, the
distinct states sequences actually has, in the ascending
order subcost (if given as a matrix) must follow, and, with
dp_matrix = TRUE, the per-pair alignment breakdown in
dp_matrix (see dp_matrix). Also carries run,
the underlying tda_run result – run$dir is
where the generated TDA commands ($run$commands) and, with
dp_matrix = TRUE, the raw, unparsed debug file TDA itself
wrote (dp.tst) both sit, if what dp_matrix parsed out
of it needs checking directly. With compare_with given,
there is no full pairwise matrix to return – cn= writes
each sequence's distance to the reference set instead – so
the return value is instead an object carrying that as table
(case, length, distance), and states
the same way.
With the default costs a substitution costs twice an indel, so it never
beats a delete plus an insert, and the result is the indel distance
|a| + |b| - 2 * LCS(a, b). Setting indel = 2 makes
substitution the cheaper move and the result becomes twice the Levenshtein
distance.
Other sequence analysis:
tda_evalfi(),
tda_fml(),
tda_frml(),
tda_seq_info(),
tda_seqgc(),
tda_seqmd(),
tda_seqpe(),
tda_seqpm()
s <- data.frame(t1 = c(1, 1, 2), t2 = c(1, 2, 2), t3 = c(2, 2, 3)) d <- tda_seqm(s) hclust(d)s <- data.frame(t1 = c(1, 1, 2), t2 = c(1, 2, 2), t3 = c(2, 2, 3)) d <- tda_seqm(s) hclust(d)
Turns sequence data into the discrete-time expanded form a logistic or
probit model needs: one row per individual per time point at risk, a
binary indicator of whether the target event (a transition from one
state to another) occurred there, dummy variables for each time period
(so period effects can be estimated freely, the way factor(t)
would in a regular model), and any covariates carried along. Fit the
result with tda_qreg (model = "logit" or
"probit") or tda_glm(family = binomial) on the
event column against the period dummies and covariates –
TDA's manual (chapter 6.18) calls this approach out explicitly as
the discrete-time counterpart to tda_rate.
tda_seqmd( sequences, event, data = NULL, covariates = NULL, event_covariates = NULL, select = NULL, tp = NULL, summary = FALSE, options = list(), dir = tempfile("tda"), ... ) tda_seqev( sequences, data = NULL, sn = 1L, select = NULL, options = list(), dir = tempfile("tda"), ... ) tda_seqevd( sequences, data = NULL, sn = 1L, select = NULL, options = list(), dir = tempfile("tda"), ... )tda_seqmd( sequences, event, data = NULL, covariates = NULL, event_covariates = NULL, select = NULL, tp = NULL, summary = FALSE, options = list(), dir = tempfile("tda"), ... ) tda_seqev( sequences, data = NULL, sn = 1L, select = NULL, options = list(), dir = tempfile("tda"), ... ) tda_seqevd( sequences, data = NULL, sn = 1L, select = NULL, options = list(), dir = tempfile("tda"), ... )
sequences |
a data frame or matrix, one row per case, one column
per time point, in order – the same shape |
event |
for |
data |
optional data frame |
covariates |
optional further time-independent covariates,
carried into the output unchanged – a data frame or matrix, one
row per case in the same order as |
event_covariates |
optional time-varying covariates – TDA's
|
select |
optional expression ( |
tp |
optional restriction of the time axis, as a vector of time
points or a single TDA range expression such as |
summary |
instead of the full per-case, per-period data, just a
|
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
sn |
for |
tda_seqev and tda_seqevd are the exploratory step before
committing to a target event: tda_seqev counts how often each
state-to-state transition actually occurs in the data, and
tda_seqevd tabulates event counts over time.
A note on names: the manual documents this command as
seqnd, but TDA 6.4 itself calls it seqmd;
tda_seqmd() uses the name that works.
This wrapper always defines exactly one sequence data structure per
call (a fresh seqdef, every time), so TDA's sn= –
selecting among several already-defined structures – has nothing to
select among here: sn = 1 is always correct, and there is no
way to reach any other value through this interface. Not exposed as
an argument for that reason, rather than included as a parameter
that could never meaningfully differ from its default.
tda_seqev ignores TDA's dtda= (no description file
is written even when asked for one); its output shape
(from/to/count) needs no further description to
read reliably. tda_seqmd's dtda= is used
internally to read TDA's real column structure back, since
event_covariates, in particular, can change how many columns
come back and where.
tda_seqmd returns a data frame: id, time,
event (the binary indicator), one period dummy column
per distinct time point, and any covariates – or, with
summary = TRUE, time, riskset, events
instead. tda_seqev
returns a data frame, one row per transition that occurs
in the data: from, to, count.
tda_seqevd returns a data frame: time, cases,
one match-count column per event type found, and total.
Other sequence analysis:
tda_evalfi(),
tda_fml(),
tda_frml(),
tda_seq_info(),
tda_seqgc(),
tda_seqm(),
tda_seqpe(),
tda_seqpm()
# three individuals, six time points (0-5), states 1-3; the target # event is a 1 -> 2 transition, with two time-independent covariates s <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), Y2 = c(2, 1, 1), Y3 = c(1, 1, 2), Y4 = c(1, 1, 2), Y5 = c(3, 3, 3)) cov <- data.frame(v1 = c(1, 2, 2), v2 = c(-10, -15, -20)) tda_seqev(s) # which transitions actually occur, and how often tda_seqevd(s) # event counts over time d <- tda_seqmd(s, event = c(1, 2), covariates = cov) d # fit it: a period dummy for every distinct time point, the way # factor(time) would in an ordinary logistic regression pd <- grep("^period", names(d), value = TRUE) tda_qreg(stats::as.formula(paste("event ~", paste(c(pd, "v1", "v2"), collapse = "+"))), d, model = "logit", intercept = FALSE) # the same data, but with an ID column and the states/covariates all # together in one data frame, the more realistic shape -- sequences= # and covariates= just name columns in data= directly full <- cbind(id = 1:3, s, cov) tda_seqmd(paste0("Y", 0:5), event = c(1, 2), data = full, covariates = c("v1", "v2"))# three individuals, six time points (0-5), states 1-3; the target # event is a 1 -> 2 transition, with two time-independent covariates s <- data.frame(Y0 = c(1, 1, 2), Y1 = c(1, 2, 1), Y2 = c(2, 1, 1), Y3 = c(1, 1, 2), Y4 = c(1, 1, 2), Y5 = c(3, 3, 3)) cov <- data.frame(v1 = c(1, 2, 2), v2 = c(-10, -15, -20)) tda_seqev(s) # which transitions actually occur, and how often tda_seqevd(s) # event counts over time d <- tda_seqmd(s, event = c(1, 2), covariates = cov) d # fit it: a period dummy for every distinct time point, the way # factor(time) would in an ordinary logistic regression pd <- grep("^period", names(d), value = TRUE) tda_qreg(stats::as.formula(paste("event ~", paste(c(pd, "v1", "v2"), collapse = "+"))), d, model = "logit", intercept = FALSE) # the same data, but with an ID column and the states/covariates all # together in one data frame, the more realistic shape -- sequences= # and covariates= just name columns in data= directly full <- cbind(id = 1:3, s, cov) tda_seqmd(paste0("Y", 0:5), event = c(1, 2), data = full, covariates = c("v1", "v2"))
seqpd prints the sequence data in one of four layouts, chosen
by layout (TDA's m=):
every sequence structure side by side, one row per case
one row per case and structure
one row per case, structure and position
one row per spell: its origin and destination state, and the times it spans
tda_seqpd( sequences, layout = 1, select = NULL, variables = NULL, id = NULL, options = list(), type = 1, second = NULL, second_type = 2, dir = tempfile("tda"), ... )tda_seqpd( sequences, layout = 1, select = NULL, variables = NULL, id = NULL, options = list(), type = 1, second = NULL, second_type = 2, dir = tempfile("tda"), ... )
sequences |
a data frame or matrix of one column per time point,
in order, the same shape |
layout |
1 to 4, the shape of the result, as listed above. |
select |
optional expression ( |
variables |
which columns of |
id |
further columns of |
options |
a named list of further TDA options, passed through. |
type |
the sequence data type, TDA's |
second |
names of the columns of a second sequence structure,
declared beside the first as the manual's |
second_type |
the sequence data type of the second structure,
as |
dir |
working directory. |
... |
passed to |
A data frame in the requested layout.
# four cases over three states, one sequence structure s <- data.frame(ID = 1:4, Y1 = c(1, 2, 3, 1), Y2 = c(1, 2, 3, 3), Y3 = c(2, 2, 1, 3), Y4 = c(2, 3, 1, 1)) tda_seqpd(s, id = "ID") # one row per spell instead, with the times each spans tda_seqpd(s, layout = 4, id = "ID")# four cases over three states, one sequence structure s <- data.frame(ID = 1:4, Y1 = c(1, 2, 3, 1), Y2 = c(1, 2, 3, 3), Y3 = c(2, 2, 1, 3), Y4 = c(2, 3, 1, 1)) tda_seqpd(s, id = "ID") # one row per spell instead, with the times each spans tda_seqpd(s, layout = 4, id = "ID")
seqpe: builds a sequence – a state at every time point – from
episode data (a start time, an end time, and origin/destination states
for each spell). The result can be read back with a fresh call to
tda_seqm or any of the other sequence functions once
written out and re-read; this function only performs the conversion,
since TDA's output is a plain data file rather than something kept
in memory across calls the way tda_seqm manages
internally.
tda_seqpe( data, id, origin, destination, start, end, tp, missing = NULL, missing_start = NULL, missing_end = NULL, options = list(), dir = tempfile("tda"), ... )tda_seqpe( data, id, origin, destination, start, end, tp, missing = NULL, missing_start = NULL, missing_end = NULL, options = list(), dir = tempfile("tda"), ... )
data |
a data frame of episodes, one row per spell. |
id |
name of the case identifier column in |
origin, destination
|
names of the origin- and destination-state columns. |
start, end
|
names of the start- and end-time columns. |
tp |
definition of the time points the sequence is built over, as
a vector or a single TDA range expression such as |
missing |
value to use for a gap at the beginning
( |
missing_start, missing_end
|
see |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
A data frame: the case id, then one column per time point in
tp, each holding the state the case was in at that time.
Other sequence analysis:
tda_evalfi(),
tda_fml(),
tda_frml(),
tda_seq_info(),
tda_seqgc(),
tda_seqm(),
tda_seqmd(),
tda_seqpm()
# two cases, two spells each e <- data.frame(id = c(1, 1, 2, 2), org = c(1, 2, 1, 3), des = c(2, 3, 3, 1), ts = c(0, 3, 0, 2), tf = c(3, 5, 2, 5)) tda_seqpe(e, id = "id", origin = "org", destination = "des", start = "ts", end = "tf", tp = "0(1)5")# two cases, two spells each e <- data.frame(id = c(1, 1, 2, 2), org = c(1, 2, 1, 3), des = c(2, 3, 3, 1), ts = c(0, 3, 0, 2), tf = c(3, 5, 2, 5)) tda_seqpe(e, id = "id", origin = "org", destination = "des", start = "ts", end = "tf", tp = "0(1)5")
Counts, per sequence, how many times each of up to 20 patterns occurs –
TDA's seqpm. A pattern is a vector of states and wildcards, one
element per position: c(3, 3) looks for state 3 immediately
followed by state 3; "?" matches any one state, "*" any
run of states (including none), "+" any repeat of the state
before it, and "-" any run of identical states. Several
patterns are given as a list, list(c(3, 3), c(3, "*", 3)).
tda_seqpm( sequences, patterns, variables = NULL, id = NULL, options = list(), dir = tempfile("tda"), ... )tda_seqpm( sequences, patterns, variables = NULL, id = NULL, options = list(), dir = tempfile("tda"), ... )
sequences |
a data frame or matrix of one column per time point,
in order – the same shape |
patterns |
a list of patterns, each a vector of states (numbers)
and wildcards ( |
variables |
which columns of |
id |
further columns of |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
An object carrying a table with one row per case: its
sequence id, its length, one match-count column per pattern, and any
id columns requested.
Other sequence analysis:
tda_evalfi(),
tda_fml(),
tda_frml(),
tda_seq_info(),
tda_seqgc(),
tda_seqm(),
tda_seqmd(),
tda_seqpe()
# six short sequences over three states; does "3,3" (state 3 twice in a # row) occur, and does the sequence ever return to 1 after leaving it? s <- data.frame(Y1 = c(1, 1, 3, 3, 3, 1), Y2 = c(1, 3, 3, 3, 1, 2), Y3 = c(1, 3, 3, 1, 2, 2), Y4 = c(2, 3, 1, 2, 2, 2), Y5 = c(2, 1, 2, 2, 2, 3)) r <- tda_seqpm(s, list(c(3, 3), c(1, "*", 1))) r$table # an id column alongside the sequence, positively selected s2 <- cbind(person = 101:106, s) r2 <- tda_seqpm(s2, list(c(3, 3)), variables = names(s), id = "person") r2$table# six short sequences over three states; does "3,3" (state 3 twice in a # row) occur, and does the sequence ever return to 1 after leaving it? s <- data.frame(Y1 = c(1, 1, 3, 3, 3, 1), Y2 = c(1, 3, 3, 3, 1, 2), Y3 = c(1, 3, 3, 1, 2, 2), Y4 = c(2, 3, 1, 2, 2, 2), Y5 = c(2, 1, 2, 2, 2, 3)) r <- tda_seqpm(s, list(c(3, 3), c(1, "*", 1))) r$table # an id column alongside the sequence, positively selected s2 <- cbind(person = 101:106, s) r2 <- tda_seqpm(s2, list(c(3, 3)), variables = names(s), id = "person") r2$table
TDA's sga: values > 0 mean success on a task.
tda_sga(x, ...)tda_sga(x, ...)
x |
matrix, persons in rows, tasks in columns. |
... |
passed to |
the printed output.
r <- tda_sga(rbind(c(1, 1, 0), c(1, 0, 0), c(1, 1, 1))) cat(head(tda_payload(r), 12), sep = "\n")r <- tda_sga(rbind(c(1, 1, 0), c(1, 0, 0), c(1, 1, 1))) cat(head(tda_payload(r), 12), sep = "\n")
A weighted moving average over a set of cases, TDA's sma.
tda_sma( x, width = NULL, weights = NULL, options = list(), dir = tempfile("tda") )tda_sma( x, width = NULL, weights = NULL, options = list(), dir = tempfile("tda") )
x |
the variable to average. |
width |
an odd window size for an equal-weight moving average,
e.g. |
weights |
TDA's half-kernel directly (see above), for an
unequal-weight window – |
options |
a named list of further TDA options, passed through:
|
dir |
working directory. |
gss= is TDA's weight specification, and it takes only half a
symmetric kernel: the centre weight followed by the weights moving out
to one side, mirrored automatically to build the full window –
c(1, 1) becomes the three weights 1, 1, 1; c(1, 1,
1) becomes five, 1, 1, 1, 1, 1. There is no tp= at
all: a plain equal-weight window over consecutive cases is what
sma does, not a smooth over a separate time axis. Weights
that sum to 1 give an ordinary average, matching
zoo::rollmean() for the equal-weight case aside from TDA's
own end-value rule where rollmean would give NA.
An object carrying a table: the case index, the
original value, and the smoothed value.
Other smoothing:
tda_integrate(),
tda_interp(),
tda_isotonic(),
tda_mat(),
tda_smd(),
tda_spl()
x <- c(1, 2, 3, 10, 5, 6, 7, 8, 9, 10) tda_sma(x, width = 3)$table # equal-weight 3-point average tda_sma(x, weights = c(0.5, 0.25))$table # weighted 0.25, 0.5, 0.25x <- c(1, 2, 3, 10, 5, 6, 7, 8, 9, 10) tda_sma(x, width = 3)$table # equal-weight 3-point average tda_sma(x, weights = c(0.5, 0.25))$table # weighted 0.25, 0.5, 0.25
A sequence of running-median smoothing passes, resistant to outliers the way a mean is not.
tda_smd(x, sm = "3R", options = list(), dir = tempfile("tda"))tda_smd(x, sm = "3R", options = list(), dir = tempfile("tda"))
x |
the variable to smooth. |
sm |
the smoothing operations as a string of characters: |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
An object carrying a table: one row per case, with the
raw value beside its smoothed one.
Other smoothing:
tda_integrate(),
tda_interp(),
tda_isotonic(),
tda_mat(),
tda_sma(),
tda_spl()
# a running median is robust to the single outlier at position 9 x <- c(5, 2, 8, 3, 9, 1, 7, 4, 100, 6) tda_smd(x, sm = "3R")$table# a running median is robust to the single outlier at position 9 x <- c(5, 2, 8, 3, 9, 1, 7, 4, 100, 6) tda_smd(x, sm = "3R")$table
Builds TDA's spatial data structure from a data frame of coordinates. Each object – a point, a line or a polygon – is a group of rows sharing an id.
tda_spatial( data, id = "id", x = "x", y = "y", attributes = NULL, type = 1, options = list(), dir = tempfile("tda") )tda_spatial( data, id = "id", x = "x", y = "y", attributes = NULL, type = 1, options = list(), dir = tempfile("tda") )
data |
a data frame with an id column and two coordinate columns. |
id, x, y
|
the column names. |
attributes |
further columns to carry along, TDA's |
type |
type of spatial object, TDA's |
options |
a named list of further |
dir |
working directory; the spatial file is written there and stays for the commands that read it. |
A tda_spatial.
Other spatial analysis:
plot.tda_spatial(),
tda_map(),
tda_polygons(),
tda_read_dbf(),
tda_read_shapefile(),
tda_read_spatial,
tda_sd(),
tda_sd_analyses,
tda_sd_ps3()
d <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) tda_sd_info(s)d <- data.frame(id = 1:4, x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) s <- tda_spatial(d) tda_sd_info(s)
A smoothing spline through a pair of variables, optionally weighted.
smooth.spline is the R analogue.
tda_spl( x, y, weights = NULL, sig = 1, deg = NULL, max = 200, rx = NULL, options = list(), dir = tempfile("tda") )tda_spl( x, y, weights = NULL, sig = 1, deg = NULL, max = 200, rx = NULL, options = list(), dir = tempfile("tda") )
x, y
|
the pair of variables. |
weights |
optional per-point weights, the same idea as
|
sig |
smoothing factor; 0 interpolates. |
deg |
degree of the spline. |
max |
maximum number of knots. |
rx |
range over which to evaluate, e.g. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
An object carrying a table of fitted values.
Other smoothing:
tda_integrate(),
tda_interp(),
tda_isotonic(),
tda_mat(),
tda_sma(),
tda_smd()
set.seed(33) x <- sort(runif(30, 0, 10)) y <- sin(x) + rnorm(30, sd = 0.15) sp <- tda_spl(x, y, sig = 1) head(sp$table)set.seed(33) x <- sort(runif(30, 0, 10)) y <- sin(x) + rnorm(30, sd = 0.15) sp <- tda_spl(x, y, sig = 1) head(sp$table)
A covariate that changes during an episode is handled by cutting the
episode in two at the moment it changes, so that each piece has one value.
TDA does this with the split option of edef, and
tda_episodes and tda_rate take a split
argument that reaches it.
tda_split( formula, data, at = NULL, grid = NULL, vars = NULL, dir = tempfile("tda"), ... )tda_split( formula, data, at = NULL, grid = NULL, vars = NULL, dir = tempfile("tda"), ... )
formula |
the usual |
data |
a data frame. |
at |
one or more variables holding a split time per episode, as names or as a vector, matrix or data frame – one column per cut. |
grid |
fixed times at which every episode is cut, as a numeric
vector. Combines with |
vars |
further variables to carry into the split data. |
dir |
working directory. |
... |
passed to |
at names a variable holding, for each episode, the time at which
the change happens – measured on the same axis as the episode's start and
end. An episode whose covariate never changes is given a value beyond its
end, conventionally a large number, and is not cut.
edef cuts once per split variable, so several are needed to cut an
episode more than once. grid is the common case said directly: a
set of fixed times every episode is cut at, one split variable per time.
grid = seq(60, 420, by = 60) is how TDA's rrdat.d60 was
built, 600 job episodes becoming 1021 pieces of at most five years.
A data frame of split episodes, one row per piece.
Other rate models:
tda_constrain(),
tda_control(),
tda_dple(),
tda_rates(),
tda_survivor(),
tda_transitions(),
vcov.tda_fit()
d <- tda_rrdat() # marriage during the job episode, or beyond its end if never d$MarrDate <- ifelse(d$TMAR <= 0, 10000, d$TMAR - d$TStart) head(tda_split(Surv(TFP, DES) ~ EDU, d, at = "MarrDate")) # every five years, however long the episode nrow(tda_split(Surv(TFP, DES) ~ EDU, d, grid = seq(60, 420, by = 60)))d <- tda_rrdat() # marriage during the job episode, or beyond its end if never d$MarrDate <- ifelse(d$TMAR <= 0, 10000, d$TMAR - d$TStart) head(tda_split(Surv(TFP, DES) ~ EDU, d, at = "MarrDate")) # every five years, however long the episode nrow(tda_split(Surv(TFP, DES) ~ EDU, d, grid = seq(60, 420, by = 60)))
TDA's spmod: iterates a population vector under the Leslie
matrix built from age-specific fertility (first row) and survivor
rates (subdiagonal) until the age distribution is stationary.
Verified in the suite against R's eigen: the growth factor
equals the dominant eigenvalue and the stationary vector the
normalized dominant eigenvector.
tda_spmod( fertility, survival, start = rep(1, length(fertility)), tolf = 1e-08, mxit = 500, ... )tda_spmod( fertility, survival, start = rep(1, length(fertility)), tolf = 1e-08, mxit = 500, ... )
fertility, survival, start
|
numeric vectors of equal length: age-specific fertility, survivor rates (last entry unused), and the starting population. |
tolf |
convergence tolerance. |
mxit |
iteration cap. |
... |
passed to |
list with growth (the dominant eigenvalue) and
stationary (the stable age distribution, summing to 1).
r <- tda_spmod(c(0, .4, .3, .1), c(.9, .8, .7, 0), rep(1, 4)) r L <- rbind(c(0, .4, .3, .1), cbind(diag(c(.9, .8, .7)), 0)) stopifnot(abs(r$growth - Re(eigen(L)$values[1])) < 1e-5)r <- tda_spmod(c(0, .4, .3, .1), c(.9, .8, .7, 0), rep(1, 4)) r L <- rbind(c(0, .4, .3, .1), cbind(diag(c(.9, .8, .7)), 0)) stopifnot(abs(r$growth - Re(eigen(L)$values[1])) < 1e-5)
tda_strings returns the string variables a run printed with
pdata, as a named list of character vectors.
tda_strings(res, trim = TRUE)tda_strings(res, trim = TRUE)
res |
a run, as returned by |
trim |
trim the fixed-width padding (default |
TDA stores strings fixed-width, so every value is padded to the variable's declared length; the padding is trimmed here, since it is storage rather than data. The values come through the export channel rather than being re-read from the printed file: a string cannot travel on the numeric channel, and parsing it back out of fixed-width text is exactly what the exports exist to avoid.
A character or factor column in a data frame becomes a TDA string
variable (see tda_write_data), and rspss and
rstata create them from the file's string columns. Those
are the only ways TDA makes one.
A named list of character vectors, one per string variable, or an empty list if the run printed none.
Other data:
tda_read_spss(),
tda_read_xls()
d <- data.frame(ID = 1:3, S = c("pear", "fig", "date"), X = c(1.5, 2.5, 3.5)) r <- tda_run(c(tda_nvar(d), "pdata() = out.txt;"), data = d) tda_strings(r)d <- data.frame(ID = 1:3, S = c("pear", "fig", "date"), X = c(1.5, 2.5, 3.5)) r <- tda_run(c(tda_nvar(d), "pdata() = out.txt;"), data = d) tda_strings(r)
tda_subm measures the substitution-metric distance between a
reference distribution and one or more others, TDA's subm.
tda_subm(..., options = list(), dir = tempfile("tda"))tda_subm(..., options = list(), dir = tempfile("tda"))
... |
the distribution variables: the reference first, then one or more to compare against it. |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
Its columns are not raw data: every value must lie in [0, 1], one
row per support point, each column a probability distribution over the
same support – TDA rejects anything else with “no distribution in
variable”. The first column is the reference; the rest are compared
against it, giving one distance each.
TDA prints the distances rather than writing them to the file df=
names (that file holds the substitution detail, not the summary), so
tda_subm parses them from the run's output into distances,
a named numeric vector – table stays NULL unless
options = list(df = ...) is given, in which case it holds that
detail instead.
An object carrying distances, a named numeric vector.
Other descriptive statistics:
tda_brr(),
tda_cov(),
tda_dstat(),
tda_freq(),
tda_independence(),
tda_ineq(),
tda_loglin(),
tda_quant(),
tda_rcorr(),
tda_segr()
# six points of support (say, a 6-point agreement scale): Y1 is close # to the reference X, Y2 is a very different shape d <- data.frame(X = c(0.05, 0.15, 0.30, 0.30, 0.15, 0.05), Y1 = c(0.03, 0.12, 0.32, 0.33, 0.15, 0.05), Y2 = c(0.30, 0.30, 0.20, 0.10, 0.07, 0.03)) tda_subm(d)$distances# six points of support (say, a 6-point agreement scale): Y1 is close # to the reference X, Y2 is a very different shape d <- data.frame(X = c(0.05, 0.15, 0.30, 0.30, 0.15, 0.05), Y1 = c(0.03, 0.12, 0.32, 0.33, 0.15, 0.05), Y2 = c(0.30, 0.30, 0.20, 0.10, 0.07, 0.03)) tda_subm(d)$distances
TDA writes one block per group and its examples select a row range out
of the flat file with tsel = Case[16,,30]. This returns the whole
thing as one long data frame instead, with a group column, so it
can be plotted, subset or joined without knowing how many blocks there
were.
tda_survivor(x, conf.int = 0.95)tda_survivor(x, conf.int = 0.95)
x |
|
conf.int |
width of the confidence band to add as |
The same call works for tda_ltb and tda_ple:
both name their time column time here, whatever the underlying
command called it, and both carry survivor and std.err.
Where the estimator provides them, density and rate come too.
A data frame with group, time, survivor,
std.err, and where available density, rate,
lower and upper.
Other rate models:
tda_constrain(),
tda_control(),
tda_dple(),
tda_rates(),
tda_split(),
tda_transitions(),
vcov.tda_fit()
d <- data.frame(t = c(4, 3, 1, 5, 8, 2), s = c(1, 1, 0, 1, 1, 1), g = c(1, 1, 1, 2, 2, 2)) f <- tda_ltb(Surv(t, s) ~ as.factor(g), d, tp = seq(0, 10, 2)) tda_survivor(f)d <- data.frame(t = c(4, 3, 1, 5, 8, 2), s = c(1, 1, 0, 1, 1, 1), g = c(1, 1, 1, 2, 2, 2)) f <- tda_ltb(Surv(t, s) ~ as.factor(g), d, tp = seq(0, 10, 2)) tda_survivor(f)
TDA's tnet on a directed edge list.
tda_tnet( edges, report = c("basic", "subgraphs", "indegrees", "outdegrees", "layers"), ... )tda_tnet( edges, report = c("basic", "subgraphs", "indegrees", "outdegrees", "layers"), ... )
edges |
data frame: from, to, then at least three value columns in the order VALIDITY (>= 0 keeps the edge), then the edge's valid-from and valid-to dates with from <= to – established from the source's check; the command requires a multigraph with three or more subgraphs. |
report |
"basic", "subgraphs", "indegrees", "outdegrees", or "layers". |
... |
passed to |
the printed output.
r <- tda_tnet(data.frame(i = c(1, 2, 3), j = c(2, 3, 4), valid = c(1, 1, 1), from = c(10, 12, 14), to = c(20, 22, 24))) cat(head(tda_payload(r), 12), sep = "\n")r <- tda_tnet(data.frame(i = c(1, 2, 3), j = c(2, 3, 4), valid = c(1, 1, 1), from = c(10, 12, 14), to = c(20, 22, 24))) cat(head(tda_payload(r), 12), sep = "\n")
The origin and destination state pairs a fitted model covers. A multi-state fit returns more than one row; a single-transition fit returns one.
tda_transitions(x)tda_transitions(x)
x |
a fitted model. |
A data frame with Org and Des, or NULL.
Other rate models:
tda_constrain(),
tda_control(),
tda_dple(),
tda_rates(),
tda_split(),
tda_survivor(),
vcov.tda_fit()
set.seed(9) mn <- 60 m1 <- data.frame(ts = 0, tf = round(rexp(mn, 0.1), 1) + 0.5, org = 0, des = sample(c(0, 1, 2), mn, TRUE, c(.25, .45, .30)), x = round(rnorm(mn), 2)) mi <- which(m1$des == 1) m2 <- data.frame(ts = m1$tf[mi], tf = m1$tf[mi] + round(rexp(length(mi), 0.08), 1) + 0.5, org = 1, des = sample(c(1, 2), length(mi), TRUE, c(.4, .6)), x = m1$x[mi]) md <- rbind(m1, m2) # three transitions: 0->1, 0->2 (censored at 2), 1->2 mf <- tda_rate(Surv(ts, tf, org, des) ~ x, md, model = "exponential") tda_transitions(mf)set.seed(9) mn <- 60 m1 <- data.frame(ts = 0, tf = round(rexp(mn, 0.1), 1) + 0.5, org = 0, des = sample(c(0, 1, 2), mn, TRUE, c(.25, .45, .30)), x = round(rnorm(mn), 2)) mi <- which(m1$des == 1) m2 <- data.frame(ts = m1$tf[mi], tf = m1$tf[mi] + round(rexp(length(mi), 0.08), 1) + 0.5, org = 1, des = sample(c(1, 2), length(mi), TRUE, c(.4, .6)), x = m1$x[mi]) md <- rbind(m1, m2) # three transitions: 0->1, 0->2 (censored at 2), 1->2 mf <- tda_rate(Surv(ts, tf, org, des) ~ x, md, model = "exponential") tda_transitions(mf)
TDA's triang over an x,y point set.
tda_triang(x, y, ...)tda_triang(x, y, ...)
x, y
|
coordinate vectors. |
... |
passed to |
the output file's lines (the triangle list).
# a Delaunay triangulation of five points: the edges of the triangles tda_triang(x = c(0, 2, 1, 3, 1), y = c(0, 0, 1, 1, 2))# a Delaunay triangulation of five points: the edges of the triangles tda_triang(x = c(0, 2, 1, 3, 1), y = c(0, 0, 1, 1, 2))
tda_ucl splits an ordering of a graph's nodes into
clusters contiguous groups so that the largest cluster
diameter is as small as possible, by the dynamic program of Alpert
and Kahng (1997). The diameter of a cluster is the largest edge value
between any two of its nodes.
tda_ucl( g, clusters = 2, min_size = NULL, max_size = NULL, order = NULL, options = list(), dir = tempfile("tda"), ... )tda_ucl( g, clusters = 2, min_size = NULL, max_size = NULL, order = NULL, options = list(), dir = tempfile("tda"), ... )
g |
a |
clusters |
number of clusters, at least 2 (default 2). |
min_size, max_size
|
smallest and largest number of nodes a cluster may have. Defaults: 1, and the number of nodes. |
order |
the ordering to split, as node indices |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
The clusters are runs of the ordering, not arbitrary subsets:
this answers "where do I cut this sequence" rather than "which things
group together". Give the ordering with order; the default is
the nodes in their internal order, which is rarely what you want
unless the graph was built that way. A seriation or a first principal
coordinate is the usual source.
The graph must be undirected and valued, and no edge value may be negative or missing.
A data frame with one row per node: position in the
ordering, node (internal index), cluster, and
label (the node number the graph was built with).
attr(x, "diameter") is the largest cluster diameter, the
quantity minimised, and attr(x, "run") carries the run.
TDA 6.4's ucl did not work. It optimised over the identity
ordering with its first two nodes swapped, counted a state with no
legal split as costing nothing, searched only the first few split
positions, and read past the end of its own cost matrix. On the
example shipped with TDA it returned a partition of diameter 7 where
one of 4 exists. The number of clusters and the size bounds were
fixed at 3, 1 and 3 whatever you asked for.
All of that is repaired here, and the result is checked in this
package's tests against a brute force over every contiguous
partition. The fixes are ours, not Rohwer's, and are listed in the
package's README.
Alpert, C. J. and Kahng, A. B. (1997). Splitting an ordering into a partition to minimize diameter. Journal of Classification 14, 51–74.
Other graph analysis:
plot.tda_graph(),
tda_dmet(),
tda_g(),
tda_g_analyses,
tda_graph(),
tda_locate_line(),
tda_ptree()
# six points on a line, distance growing with the gap between them d <- as.dist(outer(1:6, 1:6, function(i, j) 3 * abs(i - j) + 1)) g <- tda_graph(d) p <- tda_ucl(g, clusters = 3) p attr(p, "diameter") # the largest cluster diameter, minimised# six points on a line, distance growing with the gap between them d <- as.dist(outer(1:6, 1:6, function(i, j) 3 * abs(i - j) + 1)) g <- tda_graph(d) p <- tda_ucl(g, clusters = 3) p attr(p, "diameter") # the largest cluster diameter, minimised
TDA's unf: each row ranks the alternatives (larger is
preferred).
tda_unf(x, ...)tda_unf(x, ...)
x |
matrix of preference values. |
... |
passed to |
the printed output.
r <- tda_unf(rbind(c(3, 2, 1), c(1, 3, 2), c(2, 3, 1))) cat(tail(tda_payload(r), 4), sep = "\n") # the best permutationr <- tda_unf(rbind(c(3, 2, 1), c(1, 3, 2), c(2, 3, 1))) cat(tail(tda_payload(r), 4), sep = "\n") # the best permutation
tda_write_data writes a data frame as the whitespace-delimited file
TDA reads; tda_nvar generates the variable block that describes it;
tda_block builds any other command. The typed interfaces use these,
and they are exported so a hand-written script can too.
tda_write_data(data, file, na = ".") tda_nvar( data, file = NA_character_, vars = colnames(data), mpnt = -5, fmt = NULL, extra = NULL, ... ) tda_block(name, ..., rhs = NULL)tda_write_data(data, file, na = ".") tda_nvar( data, file = NA_character_, vars = colnames(data), mpnt = -5, fmt = NULL, extra = NULL, ... ) tda_block(name, ..., rhs = NULL)
data |
a data frame. |
file |
output file name. |
na |
the marker written for a missing value. It has to be a
marker rather than a number: a number is data to TDA, counted
and used by the fits. "." is the point marker |
vars |
variable names, defaulting to the column names. |
mpnt |
the value the point marker stands for. TDA substitutes it and reports how many there were. |
fmt |
print formats, one per variable. |
extra |
further variable definitions, as text. |
... |
further options, as |
name |
a command name. |
rhs |
the command's right-hand side. |
A character vector of commands, or the file name, invisibly.
Every wrapper hands its data over through rdataframe, which
stores R double columns as TDA <8> double arrays and integer
columns as <5> int arrays – nothing is squeezed through a
narrower type on the way in. All of TDA's estimation arithmetic is
double, and the direct-export channel ($run$exports) copies
doubles into R doubles, so an exported value is bit-for-bit the
number TDA computed; only the printed output rounds, at
tfmt/mfmt. Two deliberate exceptions to know about:
TDA's default storage for variables declared in a hand-written
command file (tda_run(cf=), or tda_nvar with
file= and fmt=) is a 4-byte float, faithful to the
original program – declare <8> in the definition if you need
double storage there; and a few of TDA's internal summaries (the
episode table's weighted counts, for one) pass through float by
TDA's design, which the package reproduces rather than corrects.
tdaR.use_exports optionEvery reader takes its numbers from the export channel and falls back
to parsing TDA's printed output or its written files only if the
export is absent or does not fit. Setting
options(tdaR.use_exports = FALSE) forces that fallback
everywhere, which is useful for two things: comparing the two paths
when a value looks wrong, and reproducing what an older version of
the package returned.
Expect the parser path to give you less precision, not
different answers – it reads values TDA has already rounded for
printing, typically to four or five decimals. A few readers also
differ in shape, because a text table cannot always express what the
export can: tda_atab keeps the open first and last classes
(the cases outside your breaks) on the export path and drops them on
the parser path, since TDA prints those rows with a blank bound that
the fixed-width reader cannot parse.
The package's test suite runs under both settings, so the fallback stays working rather than bit-rotting.
TDA's parser accepts a variable name only if it starts with an uppercase
letter, _, @ or $; a lowercase start is read as some
other token. This is not an arbitrary restriction that could be patched
out: the first character's case is how TDA's expression lexer
tells variables apart from everything spelled in
lowercase – functions (log, exp, if), comparison
operators (eq, le, gt), the episode accessors
(ts, tf, org, des, time), random
draws (rd, rdn), and the estimated parameters
(b1, b2, ...). Allowing a lowercase variable would make
a column called time or b1 ambiguous against those, with
no rule to break the tie, so the case requirement stays and the R side
translates instead.
The typed wrappers do that translation invisibly: a lowercase name is
sent to TDA as V<name> (.tda_names(), internal) and the
caller's spelling is put back on everything returned – coefficient
tables, vcov() dimnames, table columns, labels. The V
spelling appears only in raw TDA console output ($run$output)
and in command files, where it is TDA's name for the column. Only when
writing tda_nvar/tda_block commands by hand does the
requirement reach you: use names that start with a capital there, or
pass them through the same convention.
The symptom varies by exactly where the bad name ends up, and none of
the variants mention case, which makes this easy to lose an hour to (it
has happened more than once writing this package): a lowercase name
used to reference an existing variable fails with
“Syntax error or undefined variables”, pointing at the command,
not the name; a lowercase name used to declare a new one –
x = c4 rather than X = c4 in a hand-built sdnvar
or nvar block, say – fails differently and more confusingly,
with “Syntax error: x=c4,)”, which looks like a problem with the
column reference, the trailing comma, or a missing type/format
specifier, and is none of those.
A character or factor column becomes a TDA string variable:
tda_nvar declares it with = str(n,m) (TDA's only way of
making one) and tda_write_data pads every field to a fixed
width so those character positions are known. Strings are written
last in the file whatever order your columns are in, because TDA
cannot reach a = cK field lying after a string one; the
declaration keeps your order, so nothing changes on the R side.
tda_strings returns them as character.
Four operators work on a string variable, and extra= accepts a
{ } block of plain R, so they read as R rather than TDA
syntax:
tda_nvar(d, extra = {
Len = strlen(S) # storage width, not visible characters
Rank = strsp(S) # alphabetical position, as R's rank()
Num = strv(Code) # digits to a number, -1 if not all digits
Sub = strvp(Code, 2, 3) # characters 2..3 as a number
})
strlen returns the declared storage size, so a padded
"fig" in a width-4 variable is 4, not 3. strv and
strvp return -1 when the text is not all digits, rather
than failing.
Other TDA infrastructure:
tda_ccnt(),
tda_help(),
tda_output(),
tda_read_table(),
tda_run()
d <- data.frame(Vx = c(1, 2, 3, 4), Vy = c(2, 4, 5, 9)) # the plain data file tda_run() writes and TDA reads -- fixed-width # columns, no header, exactly what dfile= in an nvar block points at f <- tempfile() tda_write_data(d, f) cat(readLines(f), sep = "\n") cmds <- c(tda_nvar(d), tda_block("dstat", rhs = "Vx,Vy")) cat(cmds, sep = "\n") res <- tda_run(cmds, data = d) cat(res$output, sep = "\n")d <- data.frame(Vx = c(1, 2, 3, 4), Vy = c(2, 4, 5, 9)) # the plain data file tda_run() writes and TDA reads -- fixed-width # columns, no header, exactly what dfile= in an nvar block points at f <- tempfile() tda_write_data(d, f) cat(readLines(f), sep = "\n") cmds <- c(tda_nvar(d), tda_block("dstat", rhs = "Vx,Vy")) cat(cmds, sep = "\n") res <- tda_run(cmds, data = d) cat(res$output, sep = "\n")
These build TDA's internal data matrix from data and then hand
it to TDA's writers. tda_write_spss produces a portable
file (.por) or, with format = "sav", an SPSS system
file. tda_write_stata produces a .dta for a chosen
Stata release. tda_write_sys produces a TDA system file, which
tda_read_sys reads back.
tda_write_spss( data, file, keep = NULL, drop = NULL, sort = NULL, format = c("portable", "sav"), options = list(), dir = tempfile("tda"), ... ) tda_write_stata( data, file, keep = NULL, drop = NULL, sort = NULL, release = 10, options = list(), dir = tempfile("tda"), ... ) tda_write_sys(data, file, options = list(), dir = tempfile("tda"), ...)tda_write_spss( data, file, keep = NULL, drop = NULL, sort = NULL, format = c("portable", "sav"), options = list(), dir = tempfile("tda"), ... ) tda_write_stata( data, file, keep = NULL, drop = NULL, sort = NULL, release = 10, options = list(), dir = tempfile("tda"), ... ) tda_write_sys(data, file, options = list(), dir = tempfile("tda"), ...)
data |
a data frame. |
file |
path to write to. |
keep, drop
|
variables to keep or drop, as a character vector. Give at most one of them. |
sort |
variables to sort the cases by, as a character vector. |
format |
for |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
release |
for |
A TDA system file is TDA's format: it stores the data matrix
together with the variable definitions, so reading one back restores
the session's variables without repeating the nvar block.
file, invisibly. attr(x, "run") carries the run.
TDA will not read a variable name that does not begin with a capital
– nvar(id = c1) is a syntax error to it, and the same parser
handles keep, drop and sort. Columns are
therefore capitalised on the way in, so id is written as
Id. Give keep, drop and sort the
names as they are in data; the capitalisation is applied for
you.
d <- data.frame(id = 1:5, y = c(2.5, 3, 1.5, 4, 2)) f <- tempfile(fileext = ".por") tda_write_spss(d, f) tda_read_spss(f, portable = TRUE)d <- data.frame(id = 1:5, y = c(2.5, 3, 1.5, 4, 2)) f <- tempfile(fileext = ".por") tda_write_spss(d, f) tda_read_spss(f, portable = TRUE)
tda_zreg/tda_zreg1 are TDA's zreg/zreg1:
least squares with a censoring indicator, a Buckley-James estimator
where right-censored cases are iteratively reweighted rather than
dropped or treated as exact.
tda_zreg(formula, data, censor, options = list(), dir = tempfile("tda"), ...) tda_zreg1( formula, data, censor, dates = NULL, options = list(), dir = tempfile("tda"), ... )tda_zreg(formula, data, censor, options = list(), dir = tempfile("tda"), ...) tda_zreg1( formula, data, censor, dates = NULL, options = list(), dir = tempfile("tda"), ... )
formula |
a two-sided formula. |
data |
a data frame. |
censor |
the censoring indicator, as a name or a vector: |
options |
a named list of further TDA options, passed through. |
dir |
working directory. |
... |
passed to |
dates |
for |
censor follows R's convention (survival::Surv()'s):
TRUE or 1 marks a case whose response is censored. TDA's
own yw= runs the other way – a case counts as exact when
its indicator is zero – so this is translated for you, the same
correction tda_lsreg1 documents for its cen=.
Sent through unflipped, zreg recovers essentially nothing of a
known relationship (a near-zero slope); flipped, it recovers it
closely, checked against the uncensored least-squares fit.
The iteration often hits mxit (default 20) without TDA's
tolerance test passing, even once the estimates have stopped moving –
tda_run then warns “TDA did not converge”. Raising
options = list(mxit = ...) rarely changes the estimate by more
than its last few iterations already did; check by comparing coefficients
at two values of mxit rather than assuming the warning means the
fit is unusable.
tda_zreg1 is TDA's zreg1, the residual-life variant:
instead of one fit, it refits the Buckley-James regression of the
remaining lifetime () at every time step
while more than 10 cases remain at risk,
and the result is the whole trajectory of coefficients over time.
Time-varying covariates enter as event dates
(dates, TDA's xv=): at each step, a date column
becomes the indicator "has this event happened by "
(date <= t), so its coefficient traces how experiencing the
event shifts expected remaining lifetime. It takes the same plain
one-row-per-case frame as tda_zreg, plus the date columns –
the dichotomisation over time is the time variation.
An object of class tda_fit.
Other regression:
TDA_FAMILIES,
TDA_QRMODELS,
tda_freg(),
tda_gdf(),
tda_l1reg(),
tda_lsreg(),
tda_mlrc_design(),
tda_mreg(),
tda_nlreg(),
tda_npreg()
set.seed(1) d <- data.frame(x = round(rnorm(50), 2)) d$y <- round(2 - 0.8 * d$x + rnorm(50, sd = 0.4), 3) d$cen <- as.integer(d$y > 2.2) d$yc <- pmin(d$y, 2.2) # zreg iterates to reweight the censored cases; a "did not converge" # warning here is typical of the method, not a sign the fit is wrong. # True coefficients are 2 and -0.8, so this should land close to them. zr <- tda_zreg(yc ~ x, d, censor = "cen") coef(zr) head(fitted(zr)) predict(zr, newdata = data.frame(x = c(0, 1)))set.seed(1) d <- data.frame(x = round(rnorm(50), 2)) d$y <- round(2 - 0.8 * d$x + rnorm(50, sd = 0.4), 3) d$cen <- as.integer(d$y > 2.2) d$yc <- pmin(d$y, 2.2) # zreg iterates to reweight the censored cases; a "did not converge" # warning here is typical of the method, not a sign the fit is wrong. # True coefficients are 2 and -0.8, so this should land close to them. zr <- tda_zreg(yc ~ x, d, censor = "cen") coef(zr) head(fitted(zr)) predict(zr, newdata = data.frame(x = c(0, 1)))
unzoo extracts a .zoo archive, and zoo creates one –
unzip and zip for Zoo rather
than Zip. This is tdaR's code, not part of TDA (TDA can only load an
archive's contents into its data matrix, via a command that needs a
companion .zad description file, and has no general extract or
create capability at all).
unzoo(zoofile, files = NULL, list = FALSE, exdir = ".", overwrite = TRUE) zoo(zoofile, files, method = 1L, names = basename(files))unzoo(zoofile, files = NULL, list = FALSE, exdir = ".", overwrite = TRUE) zoo(zoofile, files, method = 1L, names = basename(files))
zoofile |
path to a |
files |
paths of the files to add. |
list |
if |
exdir |
directory to extract into, created if it does not exist. |
overwrite |
whether to replace files already present in |
method |
packing method for the members: |
names |
the names the members get in the archive, one per file:
by default the files' base names. A name may carry a directory,
|
unzoo decodes both of Zoo's packing methods, LZD and LZH, ported
from TDA's reference implementation – the same
code path TDA itself has used since the 1990s to read .zoo
archives, so archives TDA itself could read, this reads too. Both
methods are tested against a historical TDA archive (deha1.zoo
from the TDA teaching pages, kept outside the package as an external
test fixture): every decoded byte matches the CRC-16 the original
archive itself stored, and separately, every file
zoo writes here was extracted correctly, with a passing CRC-16,
by the independent, unrelated zoo/unzoo reference tools
(https://github.com/troglobit/zoo) – not just read back
correctly by this same code, which would only prove self-consistency.
zoo writes LZD-compressed entries by default, or stored
(uncompressed) ones with method = 0, each with its CRC-16
checksum, readable by any Zoo implementation including TDA's.
Member names are Zoo 2.1's: a long file name and a directory name are
stored in the directory entry beside the DOS-style 8.3 short name, and
both unzoo and zoo use them, so sub/long_name.dat
round-trips as itself. unzoo creates the directories it needs
under exdir. An archive zoo writes is, field for field,
what the reference zoo tool writes for the same members (its
header, every directory entry's names and version bytes, the file
leaders, the terminal record; only the members' dates differ, which
zoo leaves unset), and TDA's own arcd finds a member by
its full stored name. TDA's archive description file separates its
fields by blanks, so a member TDA is to read may not have a blank in
its name.
Zoo can, in principle, keep more than one stored version of a file under
the same name (its version-history feature) – unzoo does not
collapse or deduplicate by name, so if an archive has several entries
called the same thing, all of them come back as separate rows/files
rather than only the latest.
For list = TRUE, a data frame with one row per member:
name (with its directory, if the entry stores one), method (0 stored, 1 LZD, 2 LZH), size
(original, uncompressed), and ok (whether this reads correctly –
always TRUE for methods 0/1/2, since those are the only methods
Zoo defines). Otherwise, the paths of the files written, invisibly the
same as unzip.
archive <- system.file("extdata", "tda.zoo", package = "tdaR") unzoo(archive, list = TRUE) ex <- tempfile() paths <- unzoo(archive, files = "avar.dat", exdir = ex) readLines(paths) # round-trip: write what was just extracted back out, and read it again out <- tempfile(fileext = ".zoo") zoo(out, paths) unzoo(out, list = TRUE) # names longer than 8.3 and a directory are kept as given zoo(out, paths, names = "results/avar_first_run.dat") unzoo(out, list = TRUE) ex2 <- tempfile() unzoo(out, exdir = ex2) list.files(ex2, recursive = TRUE) ## Not run: unzoo("https://example.com/archive.zoo", exdir = tempfile()) ## End(Not run)archive <- system.file("extdata", "tda.zoo", package = "tdaR") unzoo(archive, list = TRUE) ex <- tempfile() paths <- unzoo(archive, files = "avar.dat", exdir = ex) readLines(paths) # round-trip: write what was just extracted back out, and read it again out <- tempfile(fileext = ".zoo") zoo(out, paths) unzoo(out, list = TRUE) # names longer than 8.3 and a directory are kept as given zoo(out, paths, names = "results/avar_first_run.dat") unzoo(out, list = TRUE) ex2 <- tempfile() unzoo(out, exdir = ex2) list.files(ex2, recursive = TRUE) ## Not run: unzoo("https://example.com/archive.zoo", exdir = tempfile()) ## End(Not run)