% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mcml.R
\name{build_mcml}
\alias{build_mcml}
\title{Build MCML from Raw Transition Data}
\usage{
build_mcml(
  x,
  clusters = NULL,
  method = c("sum", "mean", "median", "max", "min", "density", "geomean"),
  type = c("tna", "frequency", "cooccurrence", "raw"),
  directed = TRUE,
  compute_within = TRUE,
  actor = NULL,
  action = NULL,
  time = NULL,
  order = NULL,
  session = NULL,
  time_threshold = 900,
  labels = NULL
)
}
\arguments{
\item{x}{Input data. Accepts multiple formats:
\describe{
\item{data.frame with from/to columns}{Edge list. Columns named
from/source/src/v1/node1/i and to/target/tgt/v2/node2/j are
auto-detected. Optional weight column (weight/w/value/strength).}
\item{data.frame without from/to columns}{Sequence data. Each row is a
sequence, columns are time steps. Consecutive pairs (t, t+1) become
transitions.}
\item{tna object}{If \code{x$data} is non-NULL, uses sequence path on
the raw data. Otherwise falls back to \code{\link{cluster_summary}}.}
\item{netobject}{If \code{x$data} is non-NULL, detects edge list
vs sequence data. Otherwise falls back to \code{\link{cluster_summary}}.}
\item{cluster_summary}{Returns as-is.}
\item{square numeric matrix}{Falls back to \code{\link{cluster_summary}}.}
\item{non-square or character matrix}{Treated as sequence data.}
}}

\item{clusters}{Cluster/group assignments. Accepts:
\describe{
\item{named list}{Direct mapping. List names = cluster names, values =
character vectors of node labels.
Example: \code{list(A = c("N1","N2"), B = c("N3","N4"))}}
\item{data.frame}{A data frame where the first column contains node names
and the second column contains group/cluster names.
Example: \code{data.frame(node = c("N1","N2","N3"), group = c("A","A","B"))}}
\item{membership vector}{Character or numeric vector. Node names are
extracted from the data.
Example: \code{c("A","A","B","B")}}
\item{column name string}{For edge list data.frames, the name of a
column containing cluster labels. The mapping is built from unique
(node, group) pairs in both from and to columns. \strong{Limitation:}
this mode assigns the row's group label to \emph{both} endpoints, so
it only makes sense for edge lists where source and target nodes
always share the same group (within-group edges only). For general
edge lists where a single node may be source in some rows and target
in others, or where source and target belong to different groups,
pass an explicit named list (\code{list(G1 = c("N1","N2"), ...)})
or a two-column data frame \code{data.frame(node, group)} instead.}
\item{NULL}{Auto-detect from \code{netobject$nodes} or
\code{$node_groups} (same logic as \code{\link{cluster_summary}}).}
}}

\item{method}{Aggregation method for combining edge weights: "sum", "mean",
"median", "max", "min", "density", "geomean". Default "sum". For raw
sequence/event-log inputs the function is counting observed transitions,
so \code{"sum"} is the only interpretation that preserves the count
semantics -- the other methods are useful when aggregating
weighted edge lists or pre-existing weight matrices, where each row
already represents a measurement rather than a single observation.}

\item{type}{Post-processing of the aggregated count matrix. One of:
\describe{
\item{"tna"}{(default) Row-normalize so each row sums to 1
(first-order Markov transition probabilities).}
\item{"raw"}{Return the un-normalized count matrix.}
\item{"frequency"}{Explicit alias of \code{"raw"} -- identical raw
count construction (kept as a synonym for callers using
frequency-network terminology).}
\item{"cooccurrence"}{Symmetrize the matrix (undirected
co-occurrence).}
}
\code{"semi_markov"} is \emph{not} accepted: the package does not
implement a semi-Markov / holding-time construction, so passing it
errors rather than silently aliasing \code{"tna"}.}

\item{directed}{Logical. If \code{TRUE} (default), treat transitions as
directed. If \code{FALSE}, symmetrize sequence- and edge-derived weights
before returning raw/frequency weights or before row-normalizing
transition probabilities.}

\item{compute_within}{Logical. Compute within-cluster matrices? Default TRUE.}

\item{actor, action, time, order, session, time_threshold}{Long-format event-log
shortcut. When \code{action} is supplied on a data.frame input, the data
is passed through \code{prepare()} to derive a wide sequence, which is
then routed to the existing sequence path. Behaves identically to
\code{prepare(...) |> build_network() |> build_mcml()}.}

\item{labels}{Optional name -> label remap applied to within-cluster nodes
(the macro layer is left untouched because its labels are cluster
names). Accepts a 2-column data.frame \code{(name, label)}, a named
character vector \code{c(name = "label")}, or a named list. Unmapped
names pass through unchanged.}
}
\value{
A \code{cluster_summary} object with \code{meta$source = "transitions"},
fully compatible with \code{plot()}, \code{as_tna()}, and
\code{plot()}.
}
\description{
Builds a Multi-Cluster Multi-Level (MCML) model from raw transition data
(edge lists or sequences) by recoding node labels to cluster labels and
counting actual transitions. Unlike \code{\link{cluster_summary}} which
aggregates a pre-computed weight matrix, this function works from the
original transition data to produce the TRUE Markov chain over cluster states.
}
\examples{
# Edge list with clusters
edges <- data.frame(
  from = c("A", "A", "B", "C", "C", "D"),
  to   = c("B", "C", "A", "D", "D", "A"),
  weight = c(1, 2, 1, 3, 1, 2)
)
clusters <- list(G1 = c("A", "B"), G2 = c("C", "D"))
cs <- build_mcml(edges, clusters)
cs$macro$weights

# Sequence data with clusters
seqs <- data.frame(
  T1 = c("A", "C", "B"),
  T2 = c("B", "D", "A"),
  T3 = c("C", "C", "D"),
  T4 = c("D", "A", "C")
)
cs <- build_mcml(seqs, clusters, type = "raw")
cs$macro$weights
}
\seealso{
\code{\link{cluster_summary}} for matrix-based aggregation,
\code{net_as_tna()} to convert to tna objects,
\code{plot()} for visualization
}
