【问题标题】:R lookup interpolate between values or closest matchR查找在值或最接近的匹配之间进行插值
【发布时间】:2017-06-20 23:56:14
【问题描述】:

我有一个水库体积数据集(9 个水库的 9 列),我想使用 R 中的查找(或类似函数)使用评级表将体积转换为级别(我的评级表有两列,数量和级别)。如果我使用查找,它不会在评级表值之间插入并生成一系列 N/A。
注意:评分表中的行数与数据集中的行数不同。
我的代码与此类似 storagelevel1

我怎样才能在查找表中插入或至少找到最接近的匹配项? 谢谢

【问题讨论】:

  • 请提供代码及数据和评级表。请参阅minimal reproducible example 了解您显然尚未阅读的 hep 页面。您还应该提供您在编写时引用的代码:“如果我使用查找,...”,因为base 或推荐的 R 包中没有“查找”功能。

标签: r interpolation lookup


【解决方案1】:

单词级别引起了一些混乱。水位是指物理测量的水位(深度)。每个水位都对应一个特定的体积,例如:

电平音量 0 0 1 30 2 35 3 37 4 38

由于水库的几何形状,这些关系通常不是线性的,而是略微随机的跳跃。问题是当测量电平为 3.5(在本例中为 37.5)时如何找到音量。近似函数可以进行线性插值。

我的解决方案:

cap <- data.frame(level = 0:4, volume = c(0, 20, 33, 35, 36))
res <- data.frame(level = c(0.5, 1.2, 2.7, 3.2))
vol <- lapply(res, function(l) approx(cap$level, cap$volume, xout=l))
vol <- vol$level
plot(cap$level, cap$volume, type="b")
points(vol$x, vol$y, col="red", pch = 19)

附: @Heerj 那是 Heerbod 吗?

【讨论】:

  • 虽然接受的答案很好且完整,但我相信@Peter 更好地解决了真正的问题(我同意,表述不够好)。我发现他的解决方案优雅而有用。只是给新读者的提示:公认的解决方案依赖于完整数据集的线性模型,这可能并非在所有情况下都是正确的。
【解决方案2】:

正如 42 所评论的那样,如果我们不知道您在做什么,那么很难为您提供帮助。就是说,这段代码能给你任何见解吗?

storagerating <- data.frame(volumes = c(10, 100, 1000, 10000), 
                            levels = c("A","B","C","D"))
#  volumes levels
#1      10      A
#2     100      B
#3    1000      C
#4   10000      D

z <- 888 # a random volume
storagerating$levels[which.min(abs(z - storagerating$volumes))] # closest rating
#[1] C 
#Levels: A B C D

编辑:矢量化解决方案

z <- round(runif(300, 1, 10000)) # a random volumes

# OPTION 1: sapply
z_levels1 <- sapply(z, function(x) storagerating$levels[which.min(abs(x - storagerating$volumes))])
z_levels1

# OPTION 2: for loop
z_levels2 <- vector("numeric",length(z))
for(i in 1:length(z)){
  z_levels2[i] <- storagerating$levels[which.min(abs(z[i] - storagerating$volumes))]
}
storagerating$levels[z_levels2]

# OPTION 3: make a function with sapply
lookup <- function(x, volumes){
  sapply(x, function(x) which.min(abs(x - volumes)))
}
storagerating$levels[lookup(z, storagerating$volumes)]

EDIT2:插值

storagerating <- data.frame(volumes = seq.int(100,400,100), 
                            levels = c(1:4))
storagerating # given this
#  volumes levels
#1     100      1
#2     200      2
#3     300      3
#4     400      4

mod <- lm(levels ~ volumes, data = storagerating) # linear model example
df_new <- data.frame(volumes = z) # use our model results to estimate 
levels_new <- predict(mod, newdata = df_new) # must be data.frame with same var name
storagerating_new <- cbind(df_new, levels_new)
head(storagerating_new); tail(storagerating_new)
#  volumes levels_new
#1       1       0.01
#2       3       0.03
#3       5       0.05
#4       7       0.07
#5       9       0.09
#6      11       0.11
#    volumes levels_new
#195     389       3.89
#196     391       3.91
#197     393       3.93
#198     395       3.95
#199     397       3.97
#200     399       3.99

【讨论】:

  • 谢谢@Evan。它有效,但不是作为载体。如果我希望 z 作为一个向量(或矩阵)和一个向量(或矩阵)的答案,您的代码会根据向量中的最后一个值给我一个答案。我们可以使用此代码或矢量的修改版本吗?或者我应该写一个循环来单独读取每个值?
  • 是的,您必须循环或应用矢量化,请参阅我上面的编辑
  • 非常感谢@Evan。函数版本非常适合矢量。我现在正试图使其适用于 z 矩阵。再次感谢。
  • 我在函数上应用了一个简单的循环,它也适用于矩阵。再次感谢@Evan Friedland
  • 谢谢@Evan。还有一个问题:如果我需要插值而不是最接近的匹配,最好的方法是什么?
猜你喜欢
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多