得到一个 ECDF 的导数

Max*_*ank 3 statistics r ecdf

是否可以区分 ECDF?以下面得到的那个为例。

set.seed(1)

a <- sort(rnorm(100))
b <- ecdf(a)

plot(b)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我想取导数b以获得其概率密度函数(PDF)。

李哲源*_*李哲源 5

n <- length(a)  ## `a` must be sorted in non-decreasing order already
plot(a, 1:n / n, type = "s")  ## "staircase" plot; not "line" plot
Run Code Online (Sandbox Code Playgroud)

但是我正在寻找的导数 b

在基于样本的统计中,估计密度(对于连续随机变量)不是通过微分从 ECDF 获得的,因为样本大小是有限的,并且 ECDF 是不可微的。相反,我们直接估计密度。我想plot(density(a))这就是你真正要找的。


几天之后..

警告:以下只是没有统计依据的数值解!

我把它作为一个练习来学习关于R包scam形状限制加模型,子包的mgcv伍德教授的早期博士生PYA博士。

逻辑是这样的:

  • 使用scam::scam,将单调递增的 P 样条拟合到 ECDF(您必须指定所需的结数);[请注意,单调性不是唯一的理论约束。要求平滑的 ECDF 在其两条边上“剪裁”:左侧边为 0,右侧边为 1。我目前正在使用weights这种约束,通过在两条边上赋予非常大的权重]
  • 使用stats::splinefun,通过节点和节点处的预测值使用单调插值样条重新参数化拟合样条;
  • 返回插值样条函数,它也可以计算一阶、二阶和三阶导数。

为什么我希望这样做:

随着样本量的增加,

  • ECDF 收敛到 CDF;
  • P-spline 是一致的,所以平滑的 ECDF 对 ECDF 将越来越无偏;
  • 对于 PDF,平滑 ECDF 的一阶导数将越来越无偏。

谨慎使用:

  • 您必须自己选择结的数量;
  • 所述衍生物NOT归一化,使得曲线下的面积是1;
  • 结果可能相当不稳定,仅适用于大样本量。

函数参数:

  • x:样本向量;
  • n.knots:结数;
  • n.cells: 绘制导数函数时的网格点数

您需要scam从 CRAN安装软件包。

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
  }
Run Code Online (Sandbox Code Playgroud)
## try large sample size
set.seed(1)
x <- rnorm(1000)
f <- test(x, n.knots = 20, n.cells = 100)
Run Code Online (Sandbox Code Playgroud)

测试

f是由stats::splinefun(read ?splinefun)返回的函数。

一个简单的、类似的解决方案是在 ECDF 上做插值样条而不进行平滑。但这是一个非常糟糕的主意,因为我们没有一致性。

g <- splinefun(sort(x), 1:length(x) / length(x), method = "hyman")
curve(g(x, deriv = 1), from = -3, to = 3)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

提醒:强烈建议stats::density用于直接密度估计。