cov_from_genetic_data: Covariance from multivariate genetic data

View source: R/genetic_covariance.R

cov_from_genetic_dataR Documentation

Covariance from multivariate genetic data

Description

Calculates individual- or population-level genetic covariance from multivariate genetic data. This is useful for microsatellite, multiallelic, SNP dosage, PCA score, or other numeric encodings.

Usage

cov_from_genetic_data(
  x,
  groups = NULL,
  input = c("features", "allele_calls"),
  loci = NULL,
  center = TRUE,
  scale = TRUE,
  tol = sqrt(.Machine$double.eps),
  diagonal = c("gower", "within", "auto"),
  normalize = c("none", "features")
)

Arguments

x

Genetic data. For input = "features", a numeric matrix or data frame with individuals in rows and genetic features in columns. For input = "allele_calls", a matrix or data frame of allele calls with one column per allele copy.

groups

Optional factor, character, or integer vector assigning each row of x to a population. If NULL, each row is treated as an individual sampled unit and an individual-level covariance matrix is returned.

input

Input format. "features" treats x as an already numeric feature matrix. "allele_calls" converts allele calls to per-locus allele dosage columns before calculating covariance.

loci

Required for input = "allele_calls"; a vector with one entry per column of x identifying the locus for each allele-copy column. For a diploid microsatellite matrix with two columns per locus, the two columns for each locus should have the same loci value.

center

Should feature columns be centered by their global mean before covariance calculation? Default TRUE.

scale

Should feature columns be divided by their global standard deviation? Default TRUE. Constant features are dropped.

tol

Tolerance used to identify constant features when scale = TRUE.

diagonal

How to set the returned covariance diagonal. The default, "gower", retains the centered covariance for both grouped and individual-level data. The legacy "auto" option uses "within" for grouped population data with replication and "gower" for individual-level data. "within" replaces the Gower covariance diagonal with the within-population genetic variance, following the population-graph covariance construction. "gower" leaves the double-centered distance diagonal unchanged.

normalize

Should covariance scale be normalized? "none" returns sums over retained features. "features" divides the covariance, squared distances, and within-population variances by the number of retained features.

Details

The function first obtains a numeric feature matrix. Microsatellite data can be supplied as allele calls by setting input = "allele_calls"; these are converted to allele dosage columns, one column per locus-allele combination. Missing allele calls are imputed to the modal observed allele within each locus, with a message reporting the number of imputed calls.

For Wishart models, the nu argument is the effective degrees of freedom in the empirical covariance. With biallelic SNPs, each retained polymorphic SNP contributes one independent standardized allele-frequency column, so nu is usually the retained SNP count (reduced for linkage disequilibrium). With microsatellites, use the number of loci L as the conservative default: allele frequencies within a locus are correlated (they sum to a constant), so the locus is the natural unit of information in population genetics. \sum_l (K_l - 1), where K_l is the number of observed alleles at locus l, is an upper bound that assumes within-locus alleles are independent; this assumption is not generally satisfied, and using it can yield over-confident standard errors and model-selection statistics. The true effective \nu for microsatellite data lies somewhere between L and \sum_l (K_l - 1). Report the value used and conduct a sensitivity analysis across that range. See wishart_covariance for the full explanation.

If groups = NULL, rows of the processed feature matrix are used directly and squared Euclidean distances among individuals are transformed to a covariance matrix by Gower double-centering. This produces a positive semidefinite row-level covariance matrix up to numerical tolerance.

If groups is supplied, population centroids are calculated in feature space before the Gower transform. With diagonal = "within", the diagonal is replaced by the sum of within-population feature variances. This matches the covariance construction used before population-graph partial-correlation filtering in Dyer-style population graph workflows.

Missing values are not currently supported because common microsatellite imputation choices can change the resulting covariance.

The within-population diagonal is on a different scale from the covariance among population centroids and is unsuitable for a Wishart likelihood. Use diagonal = "gower" for that purpose. Replacing the diagonal also removes the guarantee of positive semidefiniteness and zero row sums. Unequal group sizes imply unequal sampling variance. Standardizing allele features gives greater weight to rare variants; filter by minor allele frequency before constructing the covariance and report the filtering rule.

Value

A symmetric numeric matrix with one row and column per individual (when groups = NULL) or population (when groups is supplied). The matrix is positive semi-definite up to numerical tolerance, except when diagonal = "within" is used (see Details). The following attributes are attached:

centroids

Feature matrix of population centroids (or individual feature vectors when ungrouped).

centroid_distance2

Squared Euclidean distance matrix among centroids.

within_variance

Named vector of within-population variances (only when groups is supplied and some populations have \geq 2 individuals).

unit_size

Named integer vector of group sizes.

feature_center, feature_scale

Centering and scaling constants applied to each retained feature.

retained_features

Names of the features kept after constant features were dropped.

level

Either "individual" or "population".

diagonal

The diagonal method actually used.

centered

"sites" for the Gower covariance, or "sites_before_diagonal_replacement" when the within-population diagonal replaces the centered covariance diagonal.

normalizer

Divisor applied to the covariance and distances (1 for normalize = "none", number of retained features for normalize = "features").

References

Gower JC. 1966. Some distance properties of latent root and vector methods used in multivariate analysis. Biometrika 53(3-4):325-338. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1093/biomet/53.3-4.325")}

Dyer RJ, Nason JD. 2004. Population graphs: the graph theoretic shape of genetic structure. Molecular Ecology 13(7):1713-1727. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1111/j.1365-294X.2004.02177.x")}

Dyer RJ. 2015. Population graphs and landscape genetics. Annual Review of Ecology, Evolution, and Systematics 46:327-342. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1146/annurev-ecolsys-112414-054150")}

See Also

wishart_covariance, cov_from_biallelic, dist_from_cov, simulate_covariance_response

Examples

# Numeric allele dosage / feature matrix
x <- matrix(c(0, 1,
              1, 1,
              2, 0,
              2, 1,
              0, 2,
              1, 2),
            ncol = 2, byrow = TRUE)
cov_from_genetic_data(x)

groups <- rep(c("pop1", "pop2", "pop3"), each = 2)
cov_from_genetic_data(x, groups = groups)

# Microsatellite-style allele-call columns: two allele copies per locus
alleles <- data.frame(
  loc1_a = c(100, 100, 102, 102, 104, 104),
  loc1_b = c(100, 102, 102, 104, 104, 100),
  loc2_a = c(200, 202, 200, 202, 204, 204),
  loc2_b = c(202, 202, 204, 204, 204, 200)
)
cov_from_genetic_data(
  alleles,
  groups = groups,
  input = "allele_calls",
  loci = c("loc1", "loc1", "loc2", "loc2")
)


landgraph documentation built on Sept. 26, 2026, 1:08 a.m.