【问题标题】:How to find the difference between a value and its closest value in a vector in R?如何在R中的向量中找到一个值与其最接近的值之间的差异?
【发布时间】:2019-02-24 21:31:09
【问题描述】:

我有一个像下面这样的向量:

x= c(1,23,4,15,8,17,21)

在对向量中的值进行排序后,我们有:

c(1,4,8,15,17,21,23)

我需要的输出是:

c(3, 3, 4, 2, 2, 2, 2) 

其中包含该值与其最接近的值之间的差异。

但是如果我想在没有排序的情况下输出,有什么解决方案吗?我需要一个像 c(3,2,3,2,4,2,2) 这样的输出来知道哪个样本在输出表中具有最大值(这里第 5 个值是结果)

【问题讨论】:

  • @PierreLafortune 我是这样理解这个问题的:取向量的每个元素与任何其他元素之间的差异,返回无符号最小值。
  • 所以基本上你想要一个函数,从所有内容中减去所有内容并打印每个值的最小差异......?
  • 未排序的向量也应该适用于我之前展示的outer 解决方案。
  • 你不想排序的原因是什么?它使任何可能的解决方案都更加高效。
  • @akrun 您的解决方案使用了太多内存,无法与其他对象一起使用。检查object.size(m1) 看看它的增长速度与x 一样。

标签: r statistics


【解决方案1】:
d <- diff(sort(x))
pmin(c(d, NA), c(NA, d), na.rm = TRUE)
# [1] 3 3 4 2 2 2 2

【讨论】:

  • 非常好,我总是忘记'pmin'。当用于 10e5 个元素的向量(所以甚至没有那么大)时,您的解决方案比我的解决方案快 38 倍。
  • 感谢所有解决方案,...但是如果我想找出 put 而不进行排序,有什么解决方案吗?就像......(3,2,3,2,4,2,2)。
  • @star,那么你可以使用pmin(c(d, NA), c(NA, d), na.rm = TRUE)[match(x, sort(x))]
  • @star 请考虑接受此解决方案,用于存档目的并阻止其他人花时间处理已提供适当解决方案的问题。
【解决方案2】:

如果我理解正确,您想计算向量成员与其邻居之间的最小值。

首先,我们对数据进行排序。

x= sort(c(1,23,4,15,8,17,21))

然后,我们计算与左邻居的差异(项目 1 缺失)和右邻居的差异(项目 2 缺失)

diffs <- cbind(c(NA,diff(x)),c(diff(x),NA))

所以,现在我们有了每个项目的左右差异,现在剩下的就是找到最小的:

res <- apply(diffs,MARGIN=1, min, na.rm=T)

请注意,虽然此解决方案包含说明,但当性能成为问题时,其他提供的解决方案(尤其是 @Julius 的 pmin 方法)可能更快。

【讨论】:

    【解决方案3】:

    不错的解决方案。 Julius' 似乎是最快的:

    library(microbenchmark)
    set.seed(1262016)
    x <- sample(1e5)
    
    all.equal(heroka, NicE, julius, Ambler)
    [1] TRUE
    
    microbenchmark(
    
      julius = {d <- diff(sort(x))
      pmin(c(d, NA), c(NA, d), na.rm = TRUE)},
    
      NicE = {x <- sort(x)
      pmin(abs(x-lag(x)),abs(x-lead(x)),na.rm=T)},
    
      Heroka = {x= sort(x)
      diffs <- cbind(c(NA,diff(x)),c(diff(x),NA))
      apply(diffs,MARGIN=1, min, na.rm=T)},
    
      Ambler = {n <- length(x)
      ds <- c(
        x[2] - x[1], 
        sapply(
          2:(n - 1), 
          function(i) min(x[i] - x[i - 1], x[i + 1] - x[i])
        ),
        x[n] - x[n - 1]
      )}
    )
    # Unit: milliseconds
    #   expr        min         lq      mean     median        uq       max neval
    # julius   4.167302   5.066164  13.94478   7.967066  10.11920  89.06298   100
    # NicE     4.678274   6.804918  13.85149   9.297575  12.45606  83.41032   100
    # Heroka 142.107887 176.768431 199.96590 196.269671 221.05851 299.30336   100
    # Ambler 268.724129 309.238792 334.66432 329.252146 359.88103 409.38698   100
    

    【讨论】:

    • NicE 的速度接近,但我喜欢不需要额外库的解决方案。
    • 它们本质上是捆绑在一起的。但随着规模超过一百万,朱利叶斯的解决方案更加突出。
    【解决方案4】:

    你可以试试:

    library(dplyr)
    x <- sort(x)
    pmin(abs(x-lag(x)),abs(x-lead(x)),na.rm=T)
    #[1] 3 3 4 2 2 2 2
    

    x-lag(x) 计算与最接近的较小数字的差,x-lead(x) 与最接近的较大数字的差。

    【讨论】:

      【解决方案5】:

      你可以通过蛮力做到这一点:

      x <- c(1, 4, 8, 15, 17, 21, 23)
      
      n <- length(x)
      ds <- c(
        x[2] - x[1], 
        sapply(
          2:(n - 1), 
          function(i) min(x[i] - x[i - 1], x[i + 1] - x[i])
        ),
        x[n] - x[n - 1]
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-04-16
        • 1970-01-01
        • 1970-01-01
        • 2019-06-01
        • 1970-01-01
        • 2017-05-21
        • 2015-10-12
        相关资源
        最近更新 更多