我正在实现一种算法,该算法涉及从集合中添加和删除大量内容。在R中,这很慢,因为据我所知,从向量中添加或删除内容很慢,因为必须重新分配整个向量。有没有办法更有效地做到这一点?
编辑:我当前的解决方案是使用一个布尔向量,其长度与可以在集合中的事物列表相同,并将其用作成员资格表。
答案 0 :(得分:14)
The R Inferno的第2章对此有一些有趣的评论,包括用于减少内存碎片和分配开销的perdiodic增长对象。
如果您知道该集合的最终大小是什么,那么您建议的方法可能是最好的 - 即使用适当的成员资格向量来自整个宇宙的subset
。很难知道什么是最好的,但没有看到你想要做的事情。
答案 1 :(得分:13)
如果可以,在算法期间初始化矢量使其长度等于其最大长度可能会有所帮助。
e.g。
vec <- rep(NA,10)
vec[1:3] <- 1:3
vec[4:5] <- 4:5
vec[6:10] <- 6:10
而不是
vec <- 1:3
vec <- c(vec,4:5)
vec <- c(vec,6:10)
比较
> system.time({vec <- rep(NA,10^4); for (i in 1:(10^4)) vec[i] <- i })
user system elapsed
0.043 0.001 0.044
到
> system.time({vec <- NULL; for (i in 1:(10^4)) vec <- c(vec,i) })
user system elapsed
0.249 0.089 0.335
答案 2 :(得分:4)
很难说你想要什么。也许你真的想要像push和pop这样的堆栈命令。以下不是那个。但这是一个快速的解决方案。
分配足够大的矢量以容纳您需要的所有类型的物品。将每个值设置为NA。添加项目很简单。删除项目会再次将它们设置为NA。使用向量只是na.omit(myVec)
myVec <- numeric (maxLength) # a vector of maximum length
is.na(myVec) <- 1:maxLength # set every item in myVec to NA
myVec[c(2,6,20)] <- 5 # add some values
na.omit(myVec)
#This will also work if you can initialize all of your values to something that you know you won't need.
答案 3 :(得分:1)
是的,还有更有效的方法。
这取决于您如何使用数据;您的用例。您是按照数据放置的顺序,反转的顺序,随机的顺序还是排序的顺序取出数据?
对于FIFO,对于固定大小的数组,请使用circular buffer;对于完全动态大小,请使用deque(读音卡组)。 (这可能就是您想要的。)
要随机获取数据,请考虑使用从未调整大小的1列矩阵。调整大小很慢。
如果需要有序集合(例如c(3,2,5) -> c(2,3,5)
),请查看tree or a heap。