【问题标题】:r-find two closest values in a vectorr-在向量中找到两个最接近的值
【发布时间】:2019-02-24 21:37:07
【问题描述】:

我试图在下面的向量中找到两个值,它们都接近 10。期望值是 10.12099196 和 10.63054170。您的意见将不胜感激。

 [1]  0.98799517  1.09055728  1.20383713  1.32927166  1.46857509  1.62380423  1.79743107  1.99241551  2.21226576  2.46106916  2.74346924  3.06455219  3.42958354  3.84350238  4.31005838
[16]  4.83051356  5.40199462  6.01590035  6.65715769  7.30532785  7.93823621  8.53773241  9.09570538  9.61755743 10.12099196 10.63018180 11.16783243 11.74870531 12.37719092 13.04922392
[31] 13.75661322 14.49087793 15.24414627 16.00601247 16.75709565 17.46236358 18.06882072 18.51050094 18.71908344 18.63563523 18.22123225 17.46709279 16.40246292 15.09417699 13.63404124
[46] 12.11854915 10.63054170  9.22947285  7.95056000  6.80923943  5.80717982  4.93764782  4.18947450  3.54966795  3.00499094  2.54283599  2.15165780  1.82114213  1.54222565  1.30703661
[61]  1.10879707  0.94170986  0.80084308  0.68201911  0.58171175  0.49695298  0.42525021  0.36451350  0.31299262  0.26922281  0.23197860  0.20023468  0.17313291  0.14995459  0.13009730
[76]  0.11305559  0.09840485  0.08578789  0.07490387  0.06549894  0.05735864 

【问题讨论】:

    标签: r match


    【解决方案1】:

    我想不出不使用sort 的方法。但是,您可以使用partial sort 加快速度。

    x[abs(x-10) %in% sort(abs(x-10), partial=1:2)[1:2]]
    # [1]  9.617557 10.120992
    

    如果相同的值多次出现,您将在此处获取所有值。因此,您可以使用unique 包装它,也可以使用match,如下所示:

    x[match(sort(abs(x-10), partial=1:2)[1:2], abs(x-10))]
    # [1] 10.120992  9.617557
    

    输入输出:

    dput(x)
    c(0.98799517, 1.09055728, 1.20383713, 1.32927166, 1.46857509, 
    1.62380423, 1.79743107, 1.99241551, 2.21226576, 2.46106916, 2.74346924, 
    3.06455219, 3.42958354, 3.84350238, 4.31005838, 4.83051356, 5.40199462, 
    6.01590035, 6.65715769, 7.30532785, 7.93823621, 8.53773241, 9.09570538, 
    9.61755743, 10.12099196, 10.6301818, 11.16783243, 11.74870531, 
    12.37719092, 13.04922392, 13.75661322, 14.49087793, 15.24414627, 
    16.00601247, 16.75709565, 17.46236358, 18.06882072, 18.51050094, 
    18.71908344, 18.63563523, 18.22123225, 17.46709279, 16.40246292, 
    15.09417699, 13.63404124, 12.11854915, 10.6305417, 9.22947285, 
    7.95056, 6.80923943, 5.80717982, 4.93764782, 4.1894745, 3.54966795, 
    3.00499094, 2.54283599, 2.1516578, 1.82114213, 1.54222565, 1.30703661, 
    1.10879707, 0.94170986, 0.80084308, 0.68201911, 0.58171175, 0.49695298, 
    0.42525021, 0.3645135, 0.31299262, 0.26922281, 0.2319786, 0.20023468, 
    0.17313291, 0.14995459, 0.1300973, 0.11305559, 0.09840485, 0.08578789, 
    0.07490387, 0.06549894, 0.05735864)
    

    【讨论】:

      【解决方案2】:

      另一种选择是允许用户控制“容忍度”以设置“接近度”,这可以通过使用一个简单的函数来完成:

      close <- function(x, value, tol=NULL){
        if(!is.null(tol)){
          x[abs(x-10) <= tol]
        } else {
          x[order(abs(x-10))]
        }
      }
      

      其中x 是值向量,value 是接近度比较的值,tol 是逻辑值,如果是NULL,则返回所有按“接近度”排序的“接近”值value,否则只返回满足tol中给定条件的值。

      > close(x, value=10, tol=.7)
      [1]  9.617557 10.120992 10.630182 10.630542
      
      
      > close(x, value=10)
       [1] 10.12099196  9.61755743 10.63018180 10.63054170  9.22947285  9.09570538 11.16783243
       [8]  8.53773241 11.74870531  7.95056000  7.93823621 12.11854915 12.37719092  7.30532785
      [15] 13.04922392  6.80923943  6.65715769 13.63404124 13.75661322  6.01590035  5.80717982
      [22] 14.49087793  5.40199462  4.93764782 15.09417699  4.83051356 15.24414627  4.31005838
      [29]  4.18947450 16.00601247  3.84350238 16.40246292  3.54966795  3.42958354 16.75709565
      [36]  3.06455219  3.00499094  2.74346924  2.54283599 17.46236358 17.46709279  2.46106916
      [43]  2.21226576  2.15165780  1.99241551 18.06882072  1.82114213  1.79743107 18.22123225
      [50]  1.62380423  1.54222565 18.51050094  1.46857509 18.63563523  1.32927166  1.30703661
      [57] 18.71908344  1.20383713  1.10879707  1.09055728  0.98799517  0.94170986  0.80084308
      [64]  0.68201911  0.58171175  0.49695298  0.42525021  0.36451350  0.31299262  0.26922281
      [71]  0.23197860  0.20023468  0.17313291  0.14995459  0.13009730  0.11305559  0.09840485
      [78]  0.08578789  0.07490387  0.06549894  0.05735864
      

      在第一个示例中,我将“紧密度”定义为valuex 中的每个元素之间的差值最多为0.7。在第二个示例中,函数close 返回一个值向量,其中第一个与value 中给出的值最接近,最后一个是来自value 的最远值。

      由于我的解决方案没有像@Arun 指出的那样提供查找tol 的简单(实用)方法,因此找到最接近值的一种方法是设置tol=NULL 并询问关闭值的确切数量,如:

      > close(x, value=10)[1:3]
      [1] 10.120992  9.617557 10.630182
      

      这显示了x 中最接近 10 的三个值。

      【讨论】:

      • 有没有更好的方法来选择这个容差?如果没有,它没有多大用处,不是吗?例如:如果下一个接近 10 的值是 50...?
      • @Arun 你是绝对正确的,我的解决方案并没有提供一种简单的方法来找到公差,但我编辑了我的答案以使其在某种程度上有用。
      • +1 - 这就是我的想法。我的基准测试显示order(我认为它使用基数排序?)比sort 慢。而且我想当数据真的很大时,可以更好地从部分排序中受益。只是一个评论。
      【解决方案3】:

      我不确定你的问题是否清楚,所以这里有另一种方法。要找到最接近您的第一个所需值的值 10.12099196 ,请从向量中减去该值,取绝对值,然后找到最接近的元素的索引。显式:

      delx <- abs( 10.12099196 - x)
      min.index <- which.min(delx)  #returns index of first minimum if there are duplicates
      x[min.index]   #gets you the value itself
      

      如果这不是您的问题的意图,我们深表歉意。

      【讨论】:

      • Carl,+1 - 这个想法就在那里,但它并不是 OP 的完整意图,直到您每次调用 which.min "x" 次数时从向量中删除当前最小值。他需要 2 个最接近给定值的元素。
      • @Arun,谢谢。我假设他想独立地找到与每个识别值的最佳匹配。您和 Jilber 生成的答案看起来不错。
      猜你喜欢
      • 1970-01-01
      • 2019-06-01
      • 1970-01-01
      • 2018-12-23
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-22
      相关资源
      最近更新 更多