R - 一系列数据点的递归二分法
R - Recursive dichotomy over a series of data points
# start with 3 points
# calculate their mid point, assumming normal distribution
start_init <- 10
mid_init <- 20
end_init <- 50
start <- start_init
end <- mid_init
mid_1 <- mean(c(start,end))
start <- mid_init
end <- end_init
mid_2 <- mean(c(start,end))
# now we have 3 points
c(start_init, mid_1, mid_init, mid_2, end_init)
# further calculate the mid points between
start <- start_init
end <- mid_1
mid_1_1 <- mean(c(start,end))
start <- mid_1
end <- mid_init
mid_1_2 <- mean(c(start,end))
start <- mid_init
end <- mid_2
mid_2_1 <- mean(c(start,end))
start <- mid_2
end <- end_init
mid_2_2 <- mean(c(start,end))
# now we have 9 data points
res <- c(start_init, mid_1_1 ,mid_1, mid_1_2, mid_init, mid_2_1, mid_2, mid_2_2, end_init)
我想压缩上面的代码,以便可以定义递归深度。
例如,对于深度等于 1 的情况,我们需要为 2 个连续点的所有可用组合生成 1 个新点。
如上例所示,我们从 3 个点 (A,B,C) 开始,因此深度等于 1,我们将在 A 和 B 以及 B 和 C 之间最多有 2 个额外的新点。
使用自定义辅助函数 cross_vectors
,您可以创建另一个自定义函数(我将其命名为 recursive_dichotomy
),它使用包 zoo
来计算两个连续点之间的平均值。
这是代码
# helper function
cross_vectors <- function(x, y){
c(x, y)[order(c(ceiling(seq_along(x) / 1), seq_along(y)))]
}
recursive_dichotomy <- function(v, depth){
# initialization
require(zoo)
current_depth <- 1
# while cycle for the depth of the splitting
while(current_depth <= depth){
v <- cross_vectors(v, rollmean(v, k = 2))
current_depth <- current_depth + 1
}
return(v)
}
输出
recursive_dichotomy(c(10, 20, 50), depth = 2)
# [1] 10.0 12.5 15.0 17.5 20.0 27.5 35.0 42.5 50.0
这是另一个看起来(经过几次试验和错误)有效的替代方案:
ff = function(x, depth)
{
nbetween = 2 ^ depth
means = (x[-1] - x[-length(x)]) / nbetween
diffs = c(x[1], rep(means, each = nbetween))
return(cumsum(diffs))
}
ff(c(10, 20, 50), 2)
#[1] 10.0 12.5 15.0 17.5 20.0 27.5 35.0 42.5 50.0
ff(c(10, 20, -5, 5), 1)
#[1] 10.0 15.0 20.0 7.5 -5.0 0.0 5.0
ff(c(10, 20, -5, 5), 2)
#[1] 10.00 12.50 15.00 17.50 20.00 13.75 7.50 1.25 -5.00 -2.50 0.00 2.50 5.00
# start with 3 points
# calculate their mid point, assumming normal distribution
start_init <- 10
mid_init <- 20
end_init <- 50
start <- start_init
end <- mid_init
mid_1 <- mean(c(start,end))
start <- mid_init
end <- end_init
mid_2 <- mean(c(start,end))
# now we have 3 points
c(start_init, mid_1, mid_init, mid_2, end_init)
# further calculate the mid points between
start <- start_init
end <- mid_1
mid_1_1 <- mean(c(start,end))
start <- mid_1
end <- mid_init
mid_1_2 <- mean(c(start,end))
start <- mid_init
end <- mid_2
mid_2_1 <- mean(c(start,end))
start <- mid_2
end <- end_init
mid_2_2 <- mean(c(start,end))
# now we have 9 data points
res <- c(start_init, mid_1_1 ,mid_1, mid_1_2, mid_init, mid_2_1, mid_2, mid_2_2, end_init)
我想压缩上面的代码,以便可以定义递归深度。 例如,对于深度等于 1 的情况,我们需要为 2 个连续点的所有可用组合生成 1 个新点。
如上例所示,我们从 3 个点 (A,B,C) 开始,因此深度等于 1,我们将在 A 和 B 以及 B 和 C 之间最多有 2 个额外的新点。
使用自定义辅助函数 cross_vectors
,您可以创建另一个自定义函数(我将其命名为 recursive_dichotomy
),它使用包 zoo
来计算两个连续点之间的平均值。
这是代码
# helper function
cross_vectors <- function(x, y){
c(x, y)[order(c(ceiling(seq_along(x) / 1), seq_along(y)))]
}
recursive_dichotomy <- function(v, depth){
# initialization
require(zoo)
current_depth <- 1
# while cycle for the depth of the splitting
while(current_depth <= depth){
v <- cross_vectors(v, rollmean(v, k = 2))
current_depth <- current_depth + 1
}
return(v)
}
输出
recursive_dichotomy(c(10, 20, 50), depth = 2)
# [1] 10.0 12.5 15.0 17.5 20.0 27.5 35.0 42.5 50.0
这是另一个看起来(经过几次试验和错误)有效的替代方案:
ff = function(x, depth)
{
nbetween = 2 ^ depth
means = (x[-1] - x[-length(x)]) / nbetween
diffs = c(x[1], rep(means, each = nbetween))
return(cumsum(diffs))
}
ff(c(10, 20, 50), 2)
#[1] 10.0 12.5 15.0 17.5 20.0 27.5 35.0 42.5 50.0
ff(c(10, 20, -5, 5), 1)
#[1] 10.0 15.0 20.0 7.5 -5.0 0.0 5.0
ff(c(10, 20, -5, 5), 2)
#[1] 10.00 12.50 15.00 17.50 20.00 13.75 7.50 1.25 -5.00 -2.50 0.00 2.50 5.00