是否可以区分ECDF?以下面获得的示例为例。
set.seed(1)
a <- sort(rnorm(100))
b <- ecdf(a)
plot(b)
我想采用b
的导数以获得其概率密度函数(PDF)。
答案 0 :(得分:3)
n <- length(a) ## `a` must be sorted in non-decreasing order already
plot(a, 1:n / n, type = "s") ## "staircase" plot; not "line" plot
但是我正在寻找
b
的派生词
在基于样本的统计数据中,未通过微分从ECDF中获得估计的密度(对于连续随机变量),因为样本数量有限且ECDF不可微。相反,我们直接估算密度。我猜plot(density(a))
是您真正想要的。
几天后。
我将以此为练习来了解针对形状受限制的附加模型的R包scam
,这是Wood教授的早期博士生Pya博士的mgcv
子包。
逻辑是这样的:
scam::scam
,使单调递增的P样条曲线适合ECDF(您必须指定所需的节数); [请注意,单调性不是唯一的理论约束。要求将平滑的ECDF的两个边缘“修剪”:左边缘为0,右边缘为1。我目前正在使用weights
来施加这样的约束,方法是在两个边缘上赋予很大的权重] stats::splinefun
,通过结和结上的预测值,使用单调插值样条重新拟合拟合的样条; 为什么我希望这样做有效?
随着样本量的增加,
谨慎使用:
函数参数:
x
:样本向量; n.knots
:结数; n.cells
:绘制导数函数时的网格点数您需要从CRAN安装scam
软件包。
library(scam)
test <- function (x, n.knots, n.cells) {
## get ECDF
n <- length(x)
x <- sort(x)
y <- 1:n / n
dat <- data.frame(x = x, y = y) ## make sure `scam` can find `x` and `y`
## fit a monotonically increasing P-spline for ECDF
fit <- scam::scam(y ~ s(x, bs = "mpi", k = n.knots), data = dat,
weights = c(n, rep(1, n - 2), 10 * n))
## interior knots
xk <- with(fit$smooth[[1]], knots[4:(length(knots) - 3)])
## spline values at interior knots
yk <- predict(fit, newdata = data.frame(x = xk))
## reparametrization into a monotone interpolation spline
f <- stats::splinefun(xk, yk, "hyman")
par(mfrow = c(1, 2))
plot(x, y, pch = 19, col = "gray") ## ECDF
lines(x, f(x), type = "l") ## smoothed ECDF
title(paste0("number of knots: ", n.knots,
"\neffective degree of freedom: ", round(sum(fit$edf), 2)),
cex.main = 0.8)
xg <- seq(min(x), max(x), length = n.cells)
plot(xg, f(xg, 1), type = "l") ## density estimated by scam
lines(stats::density(x), col = 2) ## a proper density estimate by density
## return smooth ECDF function
f
}
## try large sample size
set.seed(1)
x <- rnorm(1000)
f <- test(x, n.knots = 20, n.cells = 100)
f
是stats::splinefun
返回的函数(读为?splinefun
)。
一个简单的类似解决方案是在ECDF上进行插值样条而不进行平滑处理。但这是一个非常糟糕的主意,因为我们缺乏一致性。
g <- splinefun(sort(x), 1:length(x) / length(x), method = "hyman")
curve(g(x, deriv = 1), from = -3, to = 3)
提醒:强烈建议使用stats::density
进行直接密度估算。