【问题标题】:Select N rows above and below match [duplicate]选择上下匹配的N行[重复]
【发布时间】:2018-08-27 21:09:06
【问题描述】:

我想在一个匹配项的上方和下方选择 N 行。

我正在尝试命令:

mtcars[which(mtcars$vs == 1) + c(-1:1), ]

它返回以下警告:

警告信息: 其中(mtcars$vs == 1) + c(-1:1): 较长的对象长度不是较短对象长度的倍数

【问题讨论】:

  • 这应该适合你mtcars[which(mtcars$vs == 1)[1] + c(-1:1), ]。因为which 将返回一系列匹配项(不是第一个匹配项)。通过添加[1],您只保留第一个匹配项。如果您愿意,也可以使用mtcars[min(which(mtcars$vs == 1)) + c(-1:1), ]。类似的逻辑……你也可以像这样N = 1; mtcars[min(which(mtcars$vs == 1)) + c(-N:N), ] 输入你想要的行数
  • 类似于@AntoniosK提供的mtcars[min(which(mtcars$vs == 1)) + c(-1:1), ],也可以使用mtcars[first(which(mtcars$vs == 1)) + c(-1:1), ]
  • @tmfmnk 你需要dplyr 换成first,对吧?
  • @AntoniosK 你是对的。
  • 可能是另一种方式,但它最近被关闭了...n <- 1i <- head(tail(filter(c(rep(FALSE, n), mtcars$vs == 1, rep(FALSE, n)), rep(1, 1+n*2)), -n), -n) > 0mtcars[i,]

标签: r dplyr


【解决方案1】:

我们可以编写一个简短的函数来返回vec 中与val 匹配或在n 元素内的所有元素(任一方向):

newfun <- function(vec, val, n) {
    rows <- sapply(which(vec==val), function(x) seq(x-n, x+n, 1))
    rows <- unique(sort(rows[rows>0 & rows<length(vec)]))
    return(vec[rows])
}

例如:

newfun(mtcars$vs, 1, 2)

【讨论】:

    【解决方案2】:

    在将所需的索引范围添加到焦点索引(which 的结果)之前,您需要将每个值重复到范围的长度。

    # set the number of values to select, before and after each focal index
    n <- 1
    
    # create a range of (relative) indices
    i <- -n:n
    
    # repeat focal indices 
    # add range of n prior and following indices  
    ix <- rep(which(mtcars$vs == 1), each = length(i)) + i
    
    # select unique indices, truncated to the relevant range of rows,...
    unique(ix[ix > 0 & ix <= nrow(mtcars)])
    # [1]  2  3  4  5  6  7  8  9 10 11 12 17 18 19 20 21 22 25 26 27 28 29 31 32
    
    # ...which then can be used to subset data
    mtcars[unique(ix[ix > 0 & ix <= nrow(mtcars)]), ] 
    

    【讨论】:

      【解决方案3】:

      这似乎是一个简单的问题,但并不像想象的那么简单。

      问题在于which(mtcars$vs == 1) 返回一个向量而不是单个值:

      [1]  3  4  6  8  9 10 11 18 19 20 21 26 28 32
      

      如果向其中添加另一个向量 -1:1(即 c(-1L, 0L, 1L)),则适用于对不等长度向量进行操作的正常 R 规则:The recycling rule 表示

      任何短向量操作数都通过循环它们的值来扩展,直到 它们与任何其他操作数的大小相匹配。

      因此较短的向量-1:1将被回收到which(mtcars$vs == 1)的长度,即,

      rep(-1:1, length.out = length(which(mtcars$vs == 1)))
      
       [1] -1  0  1 -1  0  1 -1  0  1 -1  0  1 -1  0
      

      因此,

      的结果
      which(mtcars$vs == 1) + -1:1
      

      是两个向量元素的元素总和,其中较短的向量已被回收以匹配较长向量的长度。

       [1]  2  4  7  7  9 11 10 18 20 19 21 27 27 32
      

      这可能不是 OP 所期望的。

      另外,我们得到了

      警告信息:
      其中(mtcars$vs == 1) + -1:1 :
      较长的对象长度不是较短对象长度的倍数

      因为which(mtcars$vs == 1) 的长度为14,而-1:1 的长度为3。

      使用outer()的解决方案

      为了选择上下每个匹配行的N行,我们需要将-N:N添加到which(mtcars$vs == 1)返回的每个行号:

      outer(which(mtcars$vs == 1), -1:1, `+`)
      
            [,1] [,2] [,3]
       [1,]    2    3    4
       [2,]    3    4    5
       [3,]    5    6    7
       [4,]    7    8    9
       [5,]    8    9   10
       [6,]    9   10   11
       [7,]   10   11   12
       [8,]   17   18   19
       [9,]   18   19   20
      [10,]   19   20   21
      [11,]   20   21   22
      [12,]   25   26   27
      [13,]   27   28   29
      [14,]   31   32   33
      

      现在,我们有一个包含所有行号的数组。不幸的是,它不能直接用于子集,因为它包含重复项,并且mtcars 中不存在行号。因此,结果必须经过“后处理”才能用于子集化。

      library(magrittr) # piping used for clarity
      rn <- outer(which(mtcars$vs == 1), -1:1, `+`) %>% 
        as.vector() %>% 
        unique() %>% 
        Filter(function(x) x[1 <= x & x <= nrow(mtcars)], .)
      
      rn
      
       [1]  2  3  4  5  6  7  8  9 10 11 12 17 18 19 20 21 22 25 26 27 28 29 31 32
      
      mtcars[rn, ]
      
                         mpg cyl  disp  hp drat    wt  qsec vs am gear carb
      Mazda RX4 Wag     21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
      Datsun 710        22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
      Hornet 4 Drive    21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
      Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
      Valiant           18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
      Duster 360        14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
      Merc 240D         24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
      Merc 230          22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
      Merc 280          19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
      Merc 280C         17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
      Merc 450SE        16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
      Chrysler Imperial 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
      Fiat 128          32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
      Honda Civic       30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
      Toyota Corolla    33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
      Toyota Corona     21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
      Dodge Challenger  15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
      Pontiac Firebird  19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
      Fiat X1-9         27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
      Porsche 914-2     26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
      Lotus Europa      30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
      Ford Pantera L    15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
      Maserati Bora     15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
      Volvo 142E        21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-28
        • 2013-07-29
        • 2020-07-27
        • 2014-01-28
        • 2015-02-14
        • 1970-01-01
        相关资源
        最近更新 更多