移除向量的最后一个元素。

70

我需要移除一组向量中的最后一个数字,例如:

v <- 1:3
v1 <- 4:8

应该变成:

v <- 1:2
v1 <- 4:7

1
可能是R:删除向量的最后一个元素的重复问题。 - C8H10N4O2
4个回答

132

你可以在head(或者tail)中使用负偏移,因此head(x, -1)会删除最后一个元素:

R> head( 1:4, -1)
[1] 1 2 3
R> 
这还能省去一次对 length() 的调用。 编辑: 如Jason所指出的,这种方法实际上并不更快。无法争论经验法则。在我的机器上:
R> x <- rnorm(1000)
R> microbenchmark( y <- head(x, -1), y <- x[-length(x)], times=10000)
Unit: microseconds
                expr    min      lq median     uq     max
1   y <- head(x, -1) 29.412 31.0385 31.713 32.578 872.168
2 y <- x[-length(x)] 14.703 15.1150 15.565 15.955 706.880
R> 

5
根据消息来源,head 函数调用 length 两次,一次用于错误检查,另一次用于调用 maxmin。那么 [ 函数总共调用了三次吗?不知何故,我无法找到实现 [ 函数的代码。 - Jason Morgan
1
+1 对于编辑的支持 :) 更重要的是,提醒我可以这样使用 headtail - Jason Morgan
1
@Dirk:我在我的电脑上运行了你的代码,使用-length()确实更快。但是如果我将x的大小增加到10000,那么head实际上会快2~3倍。似乎有一些与向量长度有关的依赖关系,但我没有任何解释。 - user1642513
2
通过对称性,可以使用 tail(my_vector,-1) 来删除第一个元素。 - Antoine

58

使用 length 获取对象的长度,并使用 - 删除最后一个。

v[-length(v)]
在R中,负索引提取除给定索引之外的所有内容。

11

Dirk和Iselzer已经提供了答案。 Dirk的答案肯定是最简单明了的,但在我的系统上,至少它稍微慢一些,可能是因为使用[进行向量子集化和length检查是便宜的(根据源代码,head确实使用了length,实际上使用了两次):

> x <- rnorm(1000)
> system.time(replicate(50000, y <- head(x, -1)))
   user  system elapsed 
   3.69    0.56    4.25 
> system.time(replicate(50000, y <- x[-length(x)]))
   user  system elapsed 
  3.504   0.552   4.058

这种模式在更大的向量长度和更多的复制品中仍然成立。 YMMV。 在大多数情况下,“head”的可读性显然比“[”的边际性能改进更重要。


4
是的,尽管易读性有一些取决于观察者的主观因素。当使用负数参数时,我总是需要额外花费几毫秒来思考headtail的真正作用...而x[-length(x)]虽然不太优美,但对我这个深受R影响的大脑来说却很惯用。 - Ben Bolker

4

这是另一种选项,之前没有被提出过。 NROW 将您的向量视为一个1列矩阵。

v[-max(NROW(v))]#1 2
v1[-max(NROW(v1))]#4 5 6 7

根据上述讨论,这种方法(略微)比所有其他建议的方法都更快:

x <- rnorm(1000)
system.time(replicate(50000, y <- head(x, -1)))
user  system elapsed 
3.446   0.292   3.762
system.time(replicate(50000, y <- x[-length(x)]))
user  system elapsed 
2.131   0.326   2.472
system.time(replicate(50000, y <- x[-max(NROW(x))]))
user  system elapsed 
2.076   0.262   2.342

2
But why max()? - s_baldur
system.time 不是完全可靠的(microbenchmark 也不是,但它至少给出了更好的摘要)。如果对象是向量,则 NROW 的实现返回 length(x)max() 似乎也是完全随意的。因此,在向量上调用 NROW 时,它与 length(x) 相同 + 几个函数调用。很可能在第二次调用期间触发了 GC(或更频繁地触发),这导致了更长的 system.time。但这不应被解释为一般规则。 - Colombo

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