选择匹配项上下N行

3
我希望选择匹配项上面和下面的N行。
我正在尝试使用该命令:
mtcars[which(mtcars$vs == 1) + c(-1:1), ]

它返回以下警告:

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


该警告通常出现在使用R语言进行数据分析时,其中which()函数的输入参数出现了问题。这个错误可以通过检查代码中which()函数的输入参数并确保其正确性来解决。

2
这个代码对你应该有效: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
与@AntoniosK提供的mtcars [min(which(mtcars $ vs == 1))+ c(-1:1),]类似,您还可以使用mtcars [first(which(mtcars $ vs == 1))+ c(-1:1),] - tmfmnk
@tmfmnk,你需要使用dplyr来使用first函数,对吗? - AntoniosK
1
@AntoniosK 你是正确的。 - tmfmnk
另一种方法可能是,但最近已经关闭了... n <- 1 i <- head(tail(filter(c(rep(FALSE, n), mtcars$vs == 1, rep(FALSE, n)), rep(1, 1+n*2)), -n), -n) > 0 mtcars[i,] - GKi
3个回答

3

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

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)

3
在将所需的索引范围添加到您的焦点索引(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)]), ] 

2

这似乎是一个简单的问题,但并不像预期的那样琐碎。

问题在于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规则: 回收规则如下所述:

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

因此,较短的向量-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所期望的。

此外,我们得到了以下警告信息:

警告信息:
在 which(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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接