如何将梯形积分方法调整为自定义零点?

时间:2019-01-11 16:21:31

标签: r numerical-integration

我想计算序列向量的积分。由于没有可用的功能,所以我使用 trapezoidal方法 1

iglTzm <- function(x, y) sum(diff(x) * (head(y, -1) + tail(y, -1))) / 2

序列的第一个元素应为零点,因此原理是:如果序列的值主要低于第一个值,则积分应为负,否则应为正或0。

考虑矩阵m1

     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    6    7    8    8    6    8   10
[2,]    9    9    8    9    9    8    9
[3,]    9   10   10    9    9    9    9
[4,]    9    8    8    8    6    8    9
[5,]   10   10   10    9   10    8    0
[6,]    9    8    9   10    9    9    9

与这些原始值集成很可能导致不一致的值:

> setNames(apply(m1, 1, iglTzm, 0:6), 1:6)
  1   2   3   4   5   6 
 15   2  -2   7 -52   0 

所以我调整序列(行)的第一个值(第1列),以设置正确的符号,并获得矩阵m2

     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    0    1    2    2    0    2    4
[2,]    0    0   -1    0    0   -1    0
[3,]    0    1    1    0    0    0    0
[4,]    0   -1   -1   -1   -3   -1    0
[5,]    0    0    0   -1    0   -2  -10
[6,]    0   -1    0    1    0    0    0

从逻辑上讲,iglTzm()引发的值不会发生任何变化,因为diff()是相同的:

> setNames(apply(m2, 1, iglTzm, 0:6), 1:6)
  1   2   3   4   5   6 
 15   2  -2   7 -52   0 

无论如何,因为我不能简单地对其进行缩放或反转,所以我还没有一个绝妙的主意,如何调整功能以获取正确的信号,这可能是:

#  1   2   3   4   5   6 
# 15  -2   2  -7 -52   0

有人知道如何适应iglTzm()来获得具有正确符号的积分吗?

m2的图应该进一步说明原理:

enter image description here


数据

m1 <- matrix(c(6, 7, 8, 8, 6, 8, 10,
                9, 9, 8, 9, 9, 8, 9,
                9, 10, 10, 9, 9, 9, 9,
                9, 8, 8, 8, 6, 8, 9, 
                10, 10, 10, 9, 10, 8, 0, 
                9, 8, 9, 10, 9, 9, 9), 6, byrow=TRUE)

m2 <- t(apply(m1, 1, function(x) scale(x, center=x[1], scale=FALSE)))

# plot
par(mfrow=c(2, 3))
lapply(1:nrow(m2), function(x) {
  plot(m2[x, ], type="l", main=x)
  abline(h=m2[x, 1], col="red", lty=2)
})

1 个答案:

答案 0 :(得分:1)

首先,还有一个较小但更重要的问题,尽管在解决它之后,您的问题仍然有效。我的意思是,由于在x中使用函数的方式,应该颠倒yapply作为函数参数的顺序。

但这还不够,现在我们回到您的问题。为此,让我们回想一下通常的积分:ʃf(x)dx(从a到b的限制)将积分f以下的区域,这就是您的函数已经成功完成的工作。现在,您要调整其水平。但是,如果我们从a到b进行积分,则与ʃ(f(x)-f(a))dx =ʃf(x)dx-(b-a)f(a)相同,从而得出

iglTzm <- function(y, x) sum(diff(x) * (head(y, -1) + tail(y, -1))) / 2 - y[1] * (max(x) - min(x))
setNames(apply(m1, 1, iglTzm, 0:6), 1:6)
#  1  2  3  4  5  6 
#  9 -2  2 -7 -8  0 

碰巧只有两个绝对值与xy颠倒的版本不同。让我们看一下第一个函数:应该是9还是15?我们有2 * 2/2 + 1 * 2 + 1 * 2/2 + 2 * 4/2 = 9,所以我们确实想反转xy

另一种编写函数的方法是

iglTzm <- function(y, x) sum(diff(x) * (head(y - y[1], -1) + tail(y - y[1], -1))) / 2
setNames(apply(m1, 1, iglTzm, 0:6), 1:6)
#  1  2  3  4  5  6 
#  9 -2  2 -7 -8  0 

编辑:通过反转,我只表示函数定义中的顺序或在apply中的用法;函数本身以y(函数值)和x(网格值)为好。