% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/dyad_ratios.R
\name{extract}
\alias{extract}
\title{Run the Dyad Ratios Algorithm}
\usage{
extract(
  data,
  varname_col = "varname",
  date_col = "date",
  index_col = "index",
  n_col = NULL,
  agg_interval = c("annual", "quarterly", "monthly", "daily", "multi_year"),
  multiple = 1L,
  start_date = NULL,
  end_date = NULL,
  n_dim = 1L,
  smoothing = TRUE,
  tol = 0.001,
  fiscal_year_end = 12L,
  smooth_seed = 1L
)
}
\arguments{
\item{data}{A \code{data.frame} with at minimum the columns specified in
\code{varname_col}, \code{date_col}, \code{index_col}, and optionally
\code{n_col}.  Each row represents one survey marginal: the proportion
(or count) of respondents taking a particular position on one issue at
one point in time.  The variable name column identifies which opinion
item the row belongs to.}

\item{varname_col}{Character.  Name of the column that identifies the
opinion variable (issue series).  Default \code{"varname"}.}

\item{date_col}{Character.  Name of the column containing the observation
date.  Must be coercible to \code{Date} via \code{as.Date()}.
Default \code{"date"}.}

\item{index_col}{Character.  Name of the column containing the survey
marginal value (e.g. proportion liberal, per cent approving, etc.).
Default \code{"index"}.}

\item{n_col}{Character or \code{NULL}.  Name of the column containing the
number of respondents (sample size / weight).  When \code{NULL} (default)
all observations receive equal weight of 1000, matching the original
program's default.}

\item{agg_interval}{Character.  Temporal aggregation level.  One of
\code{"annual"} (default), \code{"quarterly"}, \code{"monthly"},
\code{"daily"}, or \code{"multi_year"}.}

\item{multiple}{Integer.  Number of years per period when
\code{agg_interval = "multi_year"}.  Default \code{1}.}

\item{start_date}{Optional \code{Date} (or character coercible by
\code{as.Date}) giving the earliest date to include.  Default: the
earliest date found in \code{data}.}

\item{end_date}{Optional \code{Date} (or character coercible by
\code{as.Date}) giving the latest date to include.  Default: the
latest date found in \code{data}.}

\item{n_dim}{Integer 1 or 2.  Number of latent dimensions to extract.
Default \code{1}.}

\item{smoothing}{Logical.  Apply optimal exponential smoothing to each
forward and backward pass.  Default \code{TRUE}.}

\item{tol}{Numeric.  Convergence tolerance (maximum weighted change in
item-mood correlations between iterations).  Default \code{0.001}.}

\item{fiscal_year_end}{Integer 1–12.  Final month of the fiscal / policy
year; use 12 (default) for calendar years.  When set to a value < 12
observations after this month are rolled forward into the next year,
consistent with the original program's \code{FinalMonth} parameter.}

\item{smooth_seed}{Integer.  Seed for the C random number generator used
inside the exponential-smoothing optimiser (\code{eSmooth}).  The default
value of \code{1} replicates MCalc's implicit behaviour: MCalc never
calls \code{srand()}, so C's \code{rand()} starts from seed 1 on every
run.  Change this only if you need to explore sensitivity to the smoothing
optimiser's random fallback step.  Has no effect when
\code{smoothing = FALSE}.}
}
\value{
An object of class \code{"extract"}, which is a named list
  containing:
  \describe{
    \item{\code{mood}}{Numeric vector of estimated public mood, one value
      per period.  When \code{n_dim = 2} this is the first dimension.}
    \item{\code{mood_dim2}}{Numeric vector of the second dimension, or
      \code{NA} when \code{n_dim = 1}.}
    \item{\code{periods}}{A \code{data.frame} describing each period
      (year, month/quarter where applicable) matching the length of
      \code{mood}.}
    \item{\code{loadings}}{A \code{data.frame} of variable names with
      loading on each extracted dimension.}
    \item{\code{iterations}}{A \code{data.frame} of the iteration history
      (convergence, reliability, smoothing alphas per iteration).}
    \item{\code{n_series}}{Integer.  Number of opinion series retained
      after dropping constant series.}
    \item{\code{n_periods}}{Integer.  Number of time periods.}
    \item{\code{n_obs}}{Integer.  Total number of input observations used.}
    \item{\code{alpha_F}}{Final forward-pass smoothing parameter.}
    \item{\code{alpha_B}}{Final backward-pass smoothing parameter.}
    \item{\code{eigenvalue}}{Eigenvalue estimate for the first dimension.}
    \item{\code{variance_explained}}{Proportion of total variance accounted
      for by the first dimension.}
    \item{\code{variance_explained_dim2}}{(\code{n_dim = 2} only) Additional
      proportion of total variance accounted for by the second dimension (i.e.
      its share of the variance left unexplained by dimension 1).  \code{NA}
      for single-dimension solutions.}
    \item{\code{call}}{The matched \code{\link[base]{call}}.}
    \item{\code{settings}}{List of all parameter values used.}
  }
}
\description{
Estimates one or two latent opinion dimensions from a collection of
time-series issue variables using the Dyad Ratios algorithm developed by
James Stimson (Stimson 1991, 1999).  This function accepts already-loaded
data as a \code{data.frame}, handles aggregation to the requested interval,
standardises the issue matrix, passes it to the compiled C++ core, and
returns a richly-annotated result object.
}
\details{
The algorithm iterates between a forward pass and a backward pass.  In each
pass every period's latent score is estimated as the weighted average of
ratios of issue values relative to all other periods for which both values
are non-missing.  The weights are the squared correlations of each issue
with the current mood estimate.  Convergence is declared when the maximum
weighted change in these correlations falls below \code{tol}.

Issues are standardised to a mean of 100 and a standard deviation of 10
before estimation, then the final mood series is rescaled to have the
weighted mean and standard deviation of the raw issue series.
}
\examples{
# Minimal synthetic example
set.seed(42)
n <- 60
dates <- seq(as.Date("1980-01-01"), by = "year", length.out = n / 3)
dat <- data.frame(
  varname = rep(c("item_a", "item_b", "item_c"), each = length(dates)),
  date    = rep(dates, 3),
  index   = c(seq(40, 65, length.out = length(dates)) + rnorm(length(dates), 0, 2),
              seq(55, 35, length.out = length(dates)) + rnorm(length(dates), 0, 2),
              seq(45, 70, length.out = length(dates)) + rnorm(length(dates), 0, 3)),
  n       = 1000
)
result <- extract(dat, n_col = "n", smoothing = FALSE)
print(result)

}
\references{
Stimson, J. A. (1991). \emph{Public Opinion in America: Moods, Cycles, and
Swings}. Westview Press.

Stimson, J. A. (1999). \emph{Public Opinion in America}, 2nd ed.
Westview Press.
}
