The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
R package for categorical functional data analysis. Implements the methods described in:
Champon X, Staicu A-M, Weishampel A, Jayalath C, Rand W (2026). “Clustering Social Media Users Using Categorical-Valued Functional Data Analysis.” Journal of the American Statistical Association. https://doi.org/10.1080/01621459.2026.2672226
Categorical functional data arise when each subject is observed as a
sequence of categorical values over a dense time grid (e.g., daily
tweet-type activity). catfda estimates the latent Gaussian
processes underlying such data using GAM-based approaches, providing the
inputs needed for downstream FPCA-based clustering.
Core functions:
| Function | Description |
|---|---|
estimate_categ_func_data() |
Main dispatcher: estimate latent Z and probability curves |
estimate_categ_func_data_multinomial() |
Multinomial GAM estimation |
estimate_categ_func_data_probit() |
Probit/adaptive estimation |
estimate_categ_func_data_binomial_parallel() |
Parallel binomial estimation |
get_x_from_w() |
Convert categorical matrix to one-hot array |
generate_categ_func_data() |
Simulate categorical functional data |
# Install from GitHub
remotes::install_github("XiaoxiaChampon/catfda")The example below reproduces the core workflow from the paper: simulate three groups of social media users with distinct tweeting patterns, estimate the latent probability curves, extract MFPCA scores, and cluster.
library(catfda)
library(doParallel) # parallel backend
library(refund) # for fpca.face()
library(NbClust) # for cluster count selection
library(fossil) # for rand.index(), adj.rand.index()
# ---- 1. Simulate 3 clusters of users (T=250, n=100) ----
set.seed(123)
T <- 250
n1 <- 50; n2 <- 30; n3 <- 20
tt <- seq(0, 1, length.out = T)
sim_cluster <- function(n_users, mu1_fn, mu2_fn, seed_offset = 0) {
W <- matrix(NA, nrow = T, ncol = n_users)
for (i in seq_len(n_users)) {
set.seed(123 + seed_offset + i)
z1 <- mu1_fn(tt) + rnorm(T, 0, 0.3)
z2 <- mu2_fn(tt) + rnorm(T, 0, 0.3)
denom <- 1 + exp(z1) + exp(z2)
p <- cbind(exp(z1)/denom, exp(z2)/denom, 1/denom)
W[, i] <- apply(p, 1, function(pr) sample(1:3, 1, prob = pr))
}
W
}
W1 <- sim_cluster(n1, function(t) 3.8 + 4*t^2 - 5, function(t) 1.5 + 4*t^2 - 5)
W2 <- sim_cluster(n2, function(t) 0.97 + 6*t^2 - 8, function(t) 0.50 + 4*t^2 - 6, seed_offset = 100)
W3 <- sim_cluster(n3, function(t) -sin(2*pi*t) + 1, function(t) 3*t - 1.5, seed_offset = 200)
W <- cbind(W1, W2, W3)
true_labels <- c(rep(1, n1), rep(2, n2), rep(3, n3))
# ---- 2. Estimate latent Z and probability curves ----
cl <- makeCluster(2); registerDoParallel(cl)
est <- estimate_categ_func_data("multinomial", tt, W, n_basis = 25)
stopCluster(cl)
# Returns: z1_est, z2_est (T x n), p1_est, p2_est, p3_est (T x n)
# ---- 3. Extract MFPCA scores ----
out1 <- fpca.face(Y = t(est$z1_est), argvals = tt, pve = 0.95)
out2 <- fpca.face(Y = t(est$z2_est), argvals = tt, pve = 0.95)
scores <- cbind(out1$scores, out2$scores)
# ---- 4. Cluster with k-means (silhouette, 2-5 clusters) ----
fit <- NbClust(data = scores, distance = "euclidean",
min.nc = 2, max.nc = 5, method = "kmeans", index = "silhouette")
labels <- fit$Best.partition
# ---- 5. Evaluate ----
rand.index(true_labels, labels)
adj.rand.index(true_labels, labels)citation("catfda")MIT © 2026 Xiaoxia Champon, Ana-Maria Staicu, Chathura Jayalath
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.