如何解决R中hist.default数值错误及uniroot端点符号相同错误
问题1:解决
Error in hist.default(res) : 'x' must be numeric 原因
hist()函数要求输入为数值向量,但lapply(xmats, find_t)返回的res是列表结构,无法直接传入直方图函数。
解决方案
将列表转换为数值向量即可,常用方法如下:
# 直接转换后绘制直方图 hist(unlist(res)) # 先转换为向量再处理(适合后续多次使用) res_vec <- unlist(res) hist(res_vec)
如果列表中存在NA值(问题2解决后可能出现),可先过滤无效值:
hist(na.omit(unlist(res)))
问题2:解决uniroot函数报错
f() values at end points not of opposite sign 原因
uniroot()要求目标函数在指定区间两端的函数值符号相反(确保区间内存在根),你的代码触发报错有三种核心场景:
- 输入向量
x与特征向量v[,n]正交时,h1t(t,x)恒为0,方程h1t(t,x)-epsilon=0无解。 - 当
x接近v[,n]时,h1t(t,x)始终接近1(远大于epsilon=0.01),区间两端函数值均为正,符号相同。 - 原区间范围
c(-50,50)过小,未覆盖函数穿过0点的区间。
解决方案
修改find_t()函数,增加前置检查和错误处理逻辑,增强鲁棒性:
h1t <- function(t,x_0) { h10 <- c(x_0 %*% v[, n]) denom <- vapply(t, function(.t) { sum((x_0 %*% v)^2 * exp(-4*(l - l[n]) * .t)) }, numeric(1L)) abs(h10) / sqrt(denom) } find_t <- function(x, epsilon = 0.01, range = c(-100, 100)) { f <- function(t) h1t(t, x) - epsilon f_left <- f(range[1]) f_right <- f(range[2]) # 处理x与v[,n]正交的情况(h1t恒为0,方程无解) h10 <- c(x %*% v[, n]) if (abs(h10) < .Machine$double.eps) { warning("x is orthogonal to v[,n], no root exists") return(NA) } # 检查区间两端函数值符号是否相反 if (sign(f_left) == sign(f_right)) { if (f_left <= 0 && f_right <= 0) { warning(paste("Root exists beyond upper bound", range[2], ", returning NA")) return(NA) } else if (f_left >= 0 && f_right >= 0) { warning(paste("h1t(t,x) is always larger than epsilon, no root exists")) return(NA) } } # 尝试调用uniroot,捕获其他潜在错误 tryCatch({ uniroot(f, range, tol = .Machine$double.eps)$root }, error = function(e) { warning(paste("uniroot failed:", e$message)) return(NA) }) } # 重新计算res res <- lapply(xmats, find_t)
关键修改说明
- 正交场景拦截:提前判断
x与v[,n]是否正交,直接返回NA并给出明确警告。 - 区间符号校验:针对两端符号相同的情况,区分场景给出警告,避免
uniroot()报错。 - 扩大区间范围:将默认区间调整为
c(-100,100),覆盖更多可能的根位置。 - 错误捕获机制:用
tryCatch()处理uniroot()的其他异常,避免程序中断。
后续处理
计算完成后绘制直方图时,记得过滤NA值:
hist(na.omit(unlist(res)), main = "Distribution of Root Values", xlab = "t")
内容的提问来源于stack exchange,提问作者oliver
相关产品推荐
相关产品推荐

