【问题标题】:Interpolate between each row of a data.frame在 data.frame 的每一行之间进行插值
【发布时间】:2022-10-14 17:25:40
【问题描述】:

我希望以快速的方式在data.frame 的每一行之间重新采样和插值。如果需要,我不介意使用data.table 或其他数据结构。这是一个可重现的示例:

df <- data.frame(x = c(0, 2, 10),
                 y = c(10, 12, 0))

所需输出:函数f(df, n),其中n 是会导致的插值数:

df_int <- f(df, 1)

# That would produce :
# df_int <- data.frame(x = c(0, 1, 2, 6, 10),
#                      y = c(10, 11, 12, 6, 0))

df_int <- f(df, 3)

# That would produce :
# df_int <- data.frame(x = c(0, 0.5, 1, 1.5, 2, 4, 6, 8, 10),
#                      y = c(10, 10.5, 11, 11.5, 12, 9, 6, 3, 0))

使用approx 提出了一些解决方案,但这在我的情况下不起作用。

【问题讨论】:

  • 我对n 作为“插值的数量”的作用并不完全清楚。这些是任意两个给定数字 x_i 和 x_{i+1} 之间的插值数吗?
  • 是的,就是这样。

标签: r interpolation


【解决方案1】:

不考虑速度

interpolate_vector <- function(x, n) {
  Reduce(function(x, tail_x) {
    c(head(x, -1), seq(tail(x, 1), tail_x[1], length.out = n + 2))
  }, init = x[1], x = tail(x, -1))
}

f <- function(df, n) {
  as.data.frame(lapply(df, interpolate_vector, n))
}
f(df, 1)
   x  y
1  0 10
2  1 11
3  2 12
4  6  6
5 10  0
f(df, 3)
     x    y
1  0.0 10.0
2  0.5 10.5
3  1.0 11.0
4  1.5 11.5
5  2.0 12.0
6  4.0  9.0
7  6.0  6.0
8  8.0  3.0
9 10.0  0.0

没有Reduce 和不断增长的向量:

interpolate_vector_2 <- function(x, n) {
  res <- numeric(length = (length(x)-1) * (n+1) + 1)
  for (i in head(seq_along(x), -1)) {
    res[(i + (i-1)*n) : (i + i*n + 1)] <- 
      seq(x[i], x[i+1], length.out = n+2)
  }
  res
}

f_2 <- function(df, n) {
  as.data.frame(lapply(df, interpolate_vector_2, n))
}

基准模板(包括@Maël 的答案):

res <- bench::press(
  rows = c(1e2, 1e3),
  n = c(1, 3, 10),
  {
    df <- data.frame(
      x = runif(rows),
      y = runif(rows)
    )
    bench::mark(
      reduce = f(df, n),
      loop = f_2(df, n),
      mael = f_3(df, n)
    )
  }
)

ggplot2::autoplot(res)

【讨论】:

  • @Maël 完成了!
【解决方案2】:

使用approx

interp <- function(x, n){
  v = c()
  for(i in seq(length(x) - 1)) {
    tmp = approx(c(x[i], x[i + 1]), n = 2 + n)$y
    v = c(v, tmp)
  }
  v[!duplicated(v)]
}

f <- function(df, n) as.data.frame(lapply(df, interp, n))

例子

f(df, 1)
#    x  y
# 1  0 10
# 2  1 11
# 3  2 12
# 4  6  6
# 5 10  0

f(df, 3)
#      x    y
# 1  0.0 10.0
# 2  0.5 10.5
# 3  1.0 11.0
# 4  1.5 11.5
# 5  2.0 12.0
# 6  4.0  9.0
# 7  6.0  6.0
# 8  8.0  3.0
# 9 10.0  0.0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多