在不使用R中的循环的情况下平滑序列

时间:2012-07-11 00:17:51

标签: r loops statistics

我正在用R中的学术论文(见结尾引用)实现统计方法。我认为有一种方法可以在不使用循环的情况下执行其中一个步骤,但我无法确定如何攻击它

此方法对具有三个变量的数据帧进行操作:x,n和p。它只能在所有i的p [i] <= p [i + 1]时运行。如果一对点违反了这一点,则通过将p [i]和p [i + 1]设置为等于其加权平均值来平滑它们     (N [1] * P [I] + N [I + 1] * P [I + 1])/(N [1] + N [I + 1]) 迭代此平滑直到p_i是非递减序列。

这种平滑的问题在于a)循环在R中是不良形式,并且b)如果在一行中存在多个点,则p_i> p_(i + 1)> = p_(i + 2),该方法可能无法终止或需要很长时间才能收敛。例如,如果发生这样的序列:

x  n  p
2  10 0.6
5  10 0.5
10 10 0.5

平滑将p的前两个值设置为0.55,然后将第二个值设置为0.525,然后将前两个设置为0.5325,依此类推并永远循环(或者如果我很幸运达到了重要的极限) a bajillion迭代)。通过识别相邻的递减数据点并将它们作为一组进行平均,应该有一种数学上等效但更有效的方法,但我不确定如何在R中进行处理。

如果您需要更多背景资料,相关论文为Martin A. Hamilton, Rosemarie C. Russo, Robert V. Thurston. "Trimmed Spearman-Karber method for estimating median lethal concentrations in toxicity bioassays." Environ. Sci. Technol., 1977, 11 (7), pp 714–719。我指的是第716页的“第一步”部分。

2 个答案:

答案 0 :(得分:2)

根据我对算法的理解,您需要找到p正在减少的位置,并从每个位置开始,找出(累计)加权平均值减少的时间,以便p可以逐块更新。如果没有某种循环,我不知道如何做到这一点。一些解决方案可能会隐藏lapply下的循环或等效但恕我直言,这是那些复杂到足以让我更喜欢旧循环的算法之一。你可能会失去一点效率,但代码读得很好。我的尝试,使用while循环:

smooth.p <- function(df) {

   while (any(diff(df$p) < 0)) {

      # where does it start decreasing
      idx <- which(diff(df$p) < 0)[1]

      # from there, compute the cumulative weighted average
      sub <- df[idx:nrow(df), ]
      cuml.wavg <- cumsum(sub$n * sub$p) / cumsum(sub$n)

      # and see for how long it is decreasing
      bad.streak.len <- rle(diff(cuml.wavg) <= 0)$lengths[1]

      # these are the indices for the block to average
      block.idx <- seq(from = idx, length = bad.streak.len + 1)

      # compute and apply the average p
      df$p[block.idx] <- sum(df$p[block.idx] * df$n[block.idx]) /
                     sum(df$n[block.idx])
   }
   return(df)
}

以下是一些数据,包括您建议的粗略补丁:

df <- data.frame(x = 1:9,
                 n = rep(1, 9),
                 p = c(0.1, 0.3, 0.2, 0.6, 0.5, 0.5, 0.8, 1.0, 0.9))
df
#   x n   p
# 1 1 1 0.1
# 2 2 1 0.3
# 3 3 1 0.2
# 4 4 1 0.6
# 5 5 1 0.5
# 6 6 1 0.5
# 7 7 1 0.8
# 8 8 1 1.0
# 9 9 1 0.9

输出:

smooth.p(df)
#   x n         p
# 1 1 1 0.1000000
# 2 2 1 0.2500000
# 3 3 1 0.2500000
# 4 4 1 0.5333333
# 5 5 1 0.5333333
# 6 6 1 0.5333333
# 7 7 1 0.8000000
# 8 8 1 0.9500000
# 9 9 1 0.9500000

答案 1 :(得分:0)

在上面的Glen_b之后,汉密尔顿论文中描述的内容相当于CRAN包gpava中的isotone