You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于R语言FDA:如何将谐波变异叠加至均值并绘图?

绘制一阶和二阶谐波并叠加变异至均值的实现方案

我参考Ramsay所著《FDA with R and MATLAB》,尝试绘制一阶和二阶谐波,期望效果为包含均值曲线及叠加±1倍、±2倍一阶/二阶谐波变异的曲线集合(类似手部手写轨迹的变异展示图)。

已完成的初始代码如下:

平滑处理代码

handpartx <- handwrit[,,1]
handparty <- handwrit[,,2]
curv.Lfd <- int2Lfd(2)
lambda <- 1e-2
breaks <- seq(min(handwritTime), max(handwritTime), length.out = 100)
xbasis <- create.bspline.basis(range(handwritTime), norder = 6,
                               breaks = breaks)
ybasis <- create.bspline.basis(range(handwritTime), norder = 6,
                               breaks = breaks)

curvx.fdPar <- fdPar(xbasis, curv.Lfd, lambda)
curvy.fdPar <- fdPar(ybasis, curv.Lfd, lambda)

handxsmooth <- smooth.basis(handwritTime, handpartx, curvx.fdPar)
handysmooth <- smooth.basis(handwritTime, handparty, curvy.fdPar)
mean_x <- eval.fd(fdobj = mean.fd(handxsmooth$fd), evalarg = handwritTime)
mean_y <- eval.fd(fdobj = mean.fd(handysmooth$fd), evalarg = handwritTime)

联合PCA代码

zbasis <- smooth.basis(handwritTime, handwrit, curvx.fdPar)$fd
zbasis$fdnames[[1]] <- "Time"
zbasis$fdnames[[2]] <- "Replications"
zbasis$fdnames[[3]] <- list("X", "Y")

nharm <- 10
handPCA <- pca.fd(zbasis, nharm)

代码优化方案

首先可以简化重复代码,统一处理X/Y方向的平滑逻辑,避免冗余:

# 统一创建基础样条和正则化参数,X/Y共享相同配置
curv.Lfd <- int2Lfd(2)
lambda <- 1e-2
breaks <- seq(min(handwritTime), max(handwritTime), length.out = 100)
shared_basis <- create.bspline.basis(range(handwritTime), norder = 6, breaks = breaks)
shared_fdPar <- fdPar(shared_basis, curv.Lfd, lambda)

# 联合平滑X/Y二维数据,直接生成适配PCA的fd对象
hand_smooth <- smooth.basis(handwritTime, handwrit, shared_fdPar)
hand_fd <- hand_smooth$fd
# 标准化fd对象的名称,方便后续识别
hand_fd$fdnames <- list("Time", "Replications", c("X", "Y"))

# 计算均值函数
mean_fd <- mean.fd(hand_fd)

# 执行联合PCA
nharm <- 10
handPCA <- pca.fd(hand_fd, nharm)

叠加谐波变异至均值并绘制的实现

要实现目标效果,核心是提取主成分(谐波)并将其按标准差倍数叠加到均值曲线上,具体代码如下:

# 定义更密集的评估时间点,让曲线更平滑
eval_time <- seq(min(handwritTime), max(handwritTime), length.out = 200)

# 评估均值曲线的X/Y坐标
mean_x <- eval.fd(eval_time, mean_fd[, , 1])
mean_y <- eval.fd(eval_time, mean_fd[, , 2])

# 提取前2个主成分(一阶、二阶谐波)及对应标准差
top_harmonics <- handPCA$harmonics[, , 1:2]
# 主成分的标准差为方差的平方根(handPCA$values存储的是方差)
harm_sd <- sqrt(handPCA$values[1:2])

# 定义要叠加的变异倍数:±1、±2倍标准差
multipliers <- c(-2, -1, 1, 2)

# 初始化绘图,先绘制均值曲线
plot(mean_x, mean_y, type = "l", lwd = 2, col = "black", 
     xlab = "X坐标", ylab = "Y坐标", main = "均值曲线±谐波变异")

# 叠加一阶谐波的变异曲线
for (k in multipliers) {
  var_x <- mean_x + k * harm_sd[1] * eval.fd(eval_time, top_harmonics[, , 1])
  var_y <- mean_y + k * harm_sd[1] * eval.fd(eval_time, top_harmonics[, , 2])
  # 用不同颜色区分倍数,虚线表示一阶谐波变异
  lines(var_x, var_y, lty = 2, col = ifelse(abs(k)==2, "darkred", "darkblue"))
}

# 叠加二阶谐波的变异曲线
for (k in multipliers) {
  var_x <- mean_x + k * harm_sd[2] * eval.fd(eval_time, top_harmonics[, , 2])
  var_y <- mean_y + k * harm_sd[2] * eval.fd(eval_time, top_harmonics[, , 2])
  # 用不同颜色区分倍数,点虚线表示二阶谐波变异
  lines(var_x, var_y, lty = 3, col = ifelse(abs(k)==2, "darkgreen", "darkcyan"))
}

# 添加图例,清晰区分各曲线含义
legend("topright", legend = c("均值曲线", 
                              "一阶谐波±1σ", "一阶谐波±2σ",
                              "二阶谐波±1σ", "二阶谐波±2σ"),
       lty = c(1,2,2,3,3),
       col = c("black", "darkblue", "darkred", "darkcyan", "darkgreen"),
       bty = "n")

关键说明

  • 联合处理X/Y数据:既减少重复代码,又保证平滑参数一致,和PCA输入格式匹配,降低出错概率
  • 谐波变异幅度:pca.fd返回的values是各主成分的方差,取平方根得到标准差,以此控制变异的幅度,符合统计意义上的离散程度
  • 叠加逻辑:均值曲线 + 倍数×标准差×谐波函数值,得到的是该主成分方向上的变异曲线,对应不同倍数的离散程度
  • 可视化区分:用不同线型和颜色区分一阶/二阶谐波以及不同倍数的变异,让图形层次清晰,符合目标效果要求

内容的提问来源于stack exchange,提问作者Thomas Petit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 23:50:56