模拟一个近似伽玛分布的AR(1)过程。

huangapple go评论94阅读模式
英文:

Simulate an AR(1) process that approximates a gamma distribution

问题

我想模拟一个AR(1)时间序列,该序列近似于伽玛分布而不是正态分布。我希望结果具有指定的速率和形状,并具有给定的phi的AR(1)过程。我已经看到这个帖子,并理解严格的伽玛模拟存在问题,但我对近似形状和速率的结果会感到满意。粗略调整形状和速率,作为phi的函数,可能已经足够满足我的需求。有什么想法?

例如,

  1. n <- 500
  2. foo <- rgamma(n = n, shape = 1.5 , rate = 5)
  3. phi <- 0.3
  4. bar <- arima.sim(list(order = c(1,0,0), ar = phi), n = n,
  5. rand.gen = rgamma, shape = 1.5,
  6. rate = 5)
  7. ggplot() +
  8. geom_density(aes(x=foo),fill="#FF8C00",alpha=0.5) +
  9. geom_density(aes(x=bar),fill="#A034F0",alpha=0.5)
  1. <details>
  2. <summary>英文:</summary>
  3. I’d like to simulate an AR(1) time series that approximates a gamma distribution rather than a normal distribution. I’d like the result to have a specified rate and shape along with a AR(1) process with a given phi. I have seen this [post][1] and understand that a strict gamma simulation is problematic, but I&#39;d be satisfied with a result that approximates the shape and rate. Some crude adjustment of shape and rate as a function of phi is likely enough for my needs. Any idea?
  4. E.g.,

n <- 500
foo <- rgamma(n = n, shape = 1.5 , rate = 5)

phi <- 0.3
bar <- arima.sim(list(order = c(1,0,0), ar = phi), n = n,
rand.gen = rgamma, shape = 1.5,
rate = 5)

ggplot() +
geom_density(aes(x=foo),fill="#FF8C00",alpha=0.5) +
geom_density(aes(x=bar),fill="#A034F0",alpha=0.5)

  1. [1]: https://stats.stackexchange.com/questions/180109/generate-a-random-variable-which-follow-gamma-distribution-and-ar1-process-sim
  2. </details>
  3. # 答案1
  4. **得分**: 2
  5. 从[这个CV回答][1]中借用函数,我们可以首先从所需的分布中进行采样,然后 *重新排序* 这些样本以近似来自AR过程的期望ACF
  6. ```R
  7. set.seed(721893540)
  8. n <- 500
  9. foo <- rgamma(n = n, shape = 1.5 , rate = 5)
  10. phi <- 0.3
  11. # 匹配前4个滞后的自相关,当自相关(当n -&gt; Inf时)首次下降到0.01以下
  12. alpha <- phi^(0:ceiling(log(0.01)/log(0.3)))
  13. # 重新排序foo以获得所需的ACF(ARIMA(0,0,1),phi = 0.3)
  14. bar <- acf.reorder(foo, alpha)

bar的ACF将与alpha更接近,而不是从随机生成的AR(1)中预期的:

  1. # 随机高斯AR(1)的自相关函数:
  2. ACF <- acf(arima.sim(list(order = c(1,0,0), ar = phi), n), plot = 0)$acf
  3. data.frame(
  4. normal = ACF[1:length(alpha)],
  5. gamma = acf(bar, length(alpha) - 1, plot = 0)$acf
  6. )
  7. #&gt; normal gamma
  8. #&gt; 1 1.000000000 1.00000000
  9. #&gt; 2 0.334034734 0.29929104
  10. #&gt; 3 0.060370711 0.09063563
  11. #&gt; 4 0.001948240 0.03818762
  12. #&gt; 5 -0.004354808 0.01196619

如果这种行为不理想,一个选项是将alpha设置为从随机生成的AR(1)的ACF(直到它不再单调下降):

  1. alpha <- ACF[1:which.max(diff(ACF) > 0)]
  2. bar2 <- acf.reorder(foo, alpha)
  3. data.frame(
  4. normal = ACF[1:length(alpha)],
  5. gamma = acf(bar, length(alpha) - 1, plot = 0)$acf,
  6. gamma2 = acf(bar2, length(alpha) - 1, plot = 0)$acf
  7. )
  8. #&gt; normal gamma gamma2
  9. #&gt; 1 1.000000000 1.00000000 1.000000000
  10. #&gt; 2 0.334034734 0.29929104 0.333494498
  11. #&gt; 3 0.060370711 0.09063563 0.060757048
  12. #&gt; 4 0.001948240 0.03818762 -0.017663549
  13. #&gt; 5 -0.004354808 0.01196619 0.008826011

为了方便,包括acf.reorder函数:

  1. acf.reorder <- function(x, alpha) {
  2. tol <- 1e-5
  3. maxIter <- 10L
  4. n <- length(x)
  5. xx <- sort(x)
  6. y <- rnorm(n)
  7. w0 <- w <- alpha1 <- alpha
  8. m <- length(alpha)
  9. i1 <- sequence((m - 1):1)
  10. i2 <- sequence((m - 1):1, 2:m)
  11. i3 <- cumsum((m - 1):1)
  12. tol10 <- tol/10
  13. iter <- 0L
  14. x <- xx[rank(filter(y, w, circular = TRUE))]
  15. SSE0 <- Inf
  16. f <- function(ww) {
  17. sum((c(1, diff(c(0, cumsum(ww[i1]*(ww[i2]))[i3]))/sum(ww^2)) - alpha1)^2)
  18. }
  19. ACF <- function(x) acf(x, lag.max = m - 1, plot = FALSE)$acf[1:m]
  20. while ((SSE <- sum((ACF(x) - alpha)^2)) > tol) {
  21. if (SSE < SSE0) {
  22. SSE0 <- SSE
  23. w <- w0
  24. }
  25. if ((iter <- iter + 1L) == maxIter) break
  26. w1 <- w0
  27. a <- 0
  28. sse0 <- Inf
  29. while (max(abs(alpha1 - a)) > tol10) {
  30. a <- c(1, diff(c(0, cumsum(w1[i1]*(ww1[i2]))[i3]))/sum(w1^2))
  31. if ((sse <- sum((a - alpha1)^2)) < sse0) {
  32. sse0 <- sse
  33. w0 <- w1
  34. } else {
  35. # w0 failed to converge; try optim
  36. w1 <- optim(w0, f, method = "L-BFGS-B")$par
  37. a <- c(1, diff(c(0, cumsum(w1[i1]*(w1[i2]))[i3]))/sum(w1^2))
  38. if (sum((a - alpha1)^2) < sse0) w0 <- w1
  39. break
  40. }
  41. w1 <- (w1*alpha1/a + w1)/2
  42. }
  43. x <- xx[rank(filter(y, w0, circular = TRUE))]
  44. alpha1 <- (alpha1*alpha/ACF(x) + alpha1)/2
  45. }
  46. xx[rank(filter(y, w, circular = TRUE))]
  47. }
英文:

Borrowing the function from this CV answer, we can first sample from the desired distribution, then reorder the samples to approximate the expected ACF from the AR process.

  1. set.seed(721893540)
  2. n &lt;- 500
  3. foo &lt;- rgamma(n = n, shape = 1.5 , rate = 5)
  4. phi &lt;- 0.3
  5. # match the autocorrelation for the first 4 lags, when the
  6. # autocorrelation (in the limit as n -&gt; Inf) first drops below 0.01
  7. alpha &lt;- phi^(0:ceiling(log(0.01)/log(0.3)))
  8. # reorder foo to get the desired ACF (ARIMA(0,0,1), phi = 0.3)
  9. bar &lt;- acf.reorder(foo, alpha)

The ACF of bar will match alpha more closely than would be expected from a randomly generated AR(1):

  1. # autocorrelation function of a random Gaussian AR(1):
  2. ACF &lt;- acf(arima.sim(list(order = c(1,0,0), ar = phi), n), plot = 0)$acf
  3. data.frame(
  4. normal = ACF[1:length(alpha)],
  5. gamma = acf(bar, length(alpha) - 1, plot = 0)$acf
  6. )
  7. #&gt; normal gamma
  8. #&gt; 1 1.000000000 1.00000000
  9. #&gt; 2 0.334034734 0.29929104
  10. #&gt; 3 0.060370711 0.09063563
  11. #&gt; 4 0.001948240 0.03818762
  12. #&gt; 5 -0.004354808 0.01196619

If this behavior is undesirable, one option is to set alpha to the ACF from a randomly generated AR(1) (until it stops decreasing monotonically).

  1. alpha &lt;- ACF[1:which.max(diff(ACF) &gt; 0)]
  2. bar2 &lt;- acf.reorder(foo, alpha)
  3. data.frame(
  4. normal = ACF[1:length(alpha)],
  5. gamma = acf(bar, length(alpha) - 1, plot = 0)$acf,
  6. gamma2 = acf(bar2, length(alpha) - 1, plot = 0)$acf
  7. )
  8. #&gt; normal gamma gamma2
  9. #&gt; 1 1.000000000 1.00000000 1.000000000
  10. #&gt; 2 0.334034734 0.29929104 0.333494498
  11. #&gt; 3 0.060370711 0.09063563 0.060757048
  12. #&gt; 4 0.001948240 0.03818762 -0.017663549
  13. #&gt; 5 -0.004354808 0.01196619 0.008826011

Including acf.reorder for convenience.

  1. acf.reorder &lt;- function(x, alpha) {
  2. tol &lt;- 1e-5
  3. maxIter &lt;- 10L
  4. n &lt;- length(x)
  5. xx &lt;- sort(x)
  6. y &lt;- rnorm(n)
  7. w0 &lt;- w &lt;- alpha1 &lt;- alpha
  8. m &lt;- length(alpha)
  9. i1 &lt;- sequence((m - 1):1)
  10. i2 &lt;- sequence((m - 1):1, 2:m)
  11. i3 &lt;- cumsum((m - 1):1)
  12. tol10 &lt;- tol/10
  13. iter &lt;- 0L
  14. x &lt;- xx[rank(filter(y, w, circular = TRUE))]
  15. SSE0 &lt;- Inf
  16. f &lt;- function(ww) {
  17. sum((c(1, diff(c(0, cumsum(ww[i1]*(ww[i2]))[i3]))/sum(ww^2)) - alpha1)^2)
  18. }
  19. ACF &lt;- function(x) acf(x, lag.max = m - 1, plot = FALSE)$acf[1:m]
  20. while ((SSE &lt;- sum((ACF(x) - alpha)^2)) &gt; tol) {
  21. if (SSE &lt; SSE0) {
  22. SSE0 &lt;- SSE
  23. w &lt;- w0
  24. }
  25. if ((iter &lt;- iter + 1L) == maxIter) break
  26. w1 &lt;- w0
  27. a &lt;- 0
  28. sse0 &lt;- Inf
  29. while (max(abs(alpha1 - a)) &gt; tol10) {
  30. a &lt;- c(1, diff(c(0, cumsum(w1[i1]*(w1[i2]))[i3]))/sum(w1^2))
  31. if ((sse &lt;- sum((a - alpha1)^2)) &lt; sse0) {
  32. sse0 &lt;- sse
  33. w0 &lt;- w1
  34. } else {
  35. # w0 failed to converge; try optim
  36. w1 &lt;- optim(w0, f, method = &quot;L-BFGS-B&quot;)$par
  37. a &lt;- c(1, diff(c(0, cumsum(w1[i1]*(w1[i2]))[i3]))/sum(w1^2))
  38. if (sum((a - alpha1)^2) &lt; sse0) w0 &lt;- w1
  39. break
  40. }
  41. w1 &lt;- (w1*alpha1/a + w1)/2
  42. }
  43. x &lt;- xx[rank(filter(y, w0, circular = TRUE))]
  44. alpha1 &lt;- (alpha1*alpha/ACF(x) + alpha1)/2
  45. }
  46. xx[rank(filter(y, w, circular = TRUE))]
  47. }

huangapple
  • 本文由 发表于 2023年7月7日 02:33:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定