R 分割范围
假设我有一些由起始坐标R 分割范围,r,R,假设我有一些由起始坐标start表示的范围,这里有一种方法。这是一个以序列的lappy为伪装的“荣耀循环” # Your sample data ranges<-data.frame(start=c(1,2,3),end=c(4,5,4)) # Extract the start/end columns start <- ranges$start end <- ranges$end # Calculate result data res <- lapp
start表示的范围,这里有一种方法。这是一个以序列的lappy
为伪装的“荣耀循环”
# Your sample data
ranges<-data.frame(start=c(1,2,3),end=c(4,5,4))
# Extract the start/end columns
start <- ranges$start
end <- ranges$end
# Calculate result data
res <- lapply(seq_along(start), function(i) start[i]+seq(0, end[i]-start[i]))
# Make it into a data.frame by way of a matrix (which has a byrow argument)
newRanges <- as.data.frame( matrix(unlist(res), ncol=2, byrow=TRUE, dimnames=list(NULL, names(ranges))) )
然后把时间花在一个更大的问题上:
n <- 1e5
start <- sample(10, n, replace=TRUE)
end <- start + sample( 3, n, replace=TRUE)*2-1
system.time( newRanges <- as.data.frame( matrix(unlist(lapply(seq_along(start), function(i) start[i]+seq(0, end[i]-start[i]))), ncol=2, byrow=TRUE) ) )
因此,在这种情况下,for循环不仅要慢12%,而且要详细得多
再次更新强>
@Martin Morgan建议使用Map
,这确实是最快的解决方案,比更快。请在我的另一个答案中调用。另外,通过使用seq.int
我的第一个解决方案也快得多:
# do.call solution: 0.46 secs
system.time( matrix(do.call('c', lapply(seq_along(start), function(i) call(':', start[i], end[i]))), ncol=2, byrow=TRUE) )
# lapply solution: 0.42 secs
system.time( matrix(unlist(lapply(seq_along(start), function(i) start[[i]]+seq.int(0L, end[[i]]-start[[i]]))), ncol=2, byrow=TRUE) )
# Map solution: 0.26 secs
system.time( matrix(unlist(Map(seq.int, start, end)), ncol=2, byrow=TRUE) )
这里有一条路。这是一个以序列的lappy
为伪装的“荣耀循环”
# Your sample data
ranges<-data.frame(start=c(1,2,3),end=c(4,5,4))
# Extract the start/end columns
start <- ranges$start
end <- ranges$end
# Calculate result data
res <- lapply(seq_along(start), function(i) start[i]+seq(0, end[i]-start[i]))
# Make it into a data.frame by way of a matrix (which has a byrow argument)
newRanges <- as.data.frame( matrix(unlist(res), ncol=2, byrow=TRUE, dimnames=list(NULL, names(ranges))) )
然后把时间花在一个更大的问题上:
n <- 1e5
start <- sample(10, n, replace=TRUE)
end <- start + sample( 3, n, replace=TRUE)*2-1
system.time( newRanges <- as.data.frame( matrix(unlist(lapply(seq_along(start), function(i) start[i]+seq(0, end[i]-start[i]))), ncol=2, byrow=TRUE) ) )
因此,在这种情况下,for循环不仅要慢12%,而且要详细得多
再次更新强>
@Martin Morgan建议使用Map
,这确实是最快的解决方案,比更快。请在我的另一个答案中调用。另外,通过使用seq.int
我的第一个解决方案也快得多:
# do.call solution: 0.46 secs
system.time( matrix(do.call('c', lapply(seq_along(start), function(i) call(':', start[i], end[i]))), ncol=2, byrow=TRUE) )
# lapply solution: 0.42 secs
system.time( matrix(unlist(lapply(seq_along(start), function(i) start[[i]]+seq.int(0L, end[[i]]-start[[i]]))), ncol=2, byrow=TRUE) )
# Map solution: 0.26 secs
system.time( matrix(unlist(Map(seq.int, start, end)), ncol=2, byrow=TRUE) )
您可以尝试为向量创建文本,parse
-ing和eval
-ing,然后使用矩阵创建数据。frame
:
txt <- paste("c(",paste(ranges$start,ranges$end,sep=":",collapse=","),")",sep="")
> txt
[1] "c(1:4,2:5,3:4)"
vec <- eval(parse(text=txt))
> vec
[1] 1 2 3 4 2 3 4 5 3 4
mat <- matrix(vec,ncol=2,byrow=T)
> data.frame(mat)
X1 X2
1 1 2
2 3 4
3 2 3
4 4 5
5 3 4
txt
[1] c(1:4,2:5,3:4)
vec vec
[1] 1 2 3 4 2 3 4 5 3 4
mat数据帧(mat)
X1-X2
1 1 2
2 3 4
3 2 3
4 4 5
5 3 4
您可以尝试为向量创建文本,解析和求值,然后使用矩阵
创建数据框
:
txt <- paste("c(",paste(ranges$start,ranges$end,sep=":",collapse=","),")",sep="")
> txt
[1] "c(1:4,2:5,3:4)"
vec <- eval(parse(text=txt))
> vec
[1] 1 2 3 4 2 3 4 5 3 4
mat <- matrix(vec,ncol=2,byrow=T)
> data.frame(mat)
X1 X2
1 1 2
2 3 4
3 2 3
4 4 5
5 3 4
txt
[1] c(1:4,2:5,3:4)
vec vec
[1] 1 2 3 4 2 3 4 5 3 4
mat数据帧(mat)
X1-X2
1 1 2
2 3 4
3 2 3
4 4 5
5 3 4
以下是另一个基于@James great solution的答案。它避免了粘贴和解析,并且速度更快:
vec <- do.call('c', lapply(seq_along(start), function(i) call(':', start[i], end[i])))
mat <- matrix(vec,ncol=2,byrow=T)
vec下面是另一个基于@James great solution的答案。它避免了粘贴和解析,并且速度更快:
vec <- do.call('c', lapply(seq_along(start), function(i) call(':', start[i], end[i])))
mat <- matrix(vec,ncol=2,byrow=T)
vec-lappy并不比for-loopMaybeMap(seq,start,end)
好多少,而不是lappy
,或者with(ranges,Map(seq,start,end))
来避免开始和结束的显式提取。@MartinMorgan-好主意Map
确实比这里的Lappy
快(大约快20%)…但我的另一个答案是使用do.call
仍然是最快的。即使它仍然只有0票:(尝试seq.int
的速度,使用USE.NAMES=FALSE
forMap
lappy并不比for loopmableMap(seq,start,end)
好,而不是lappy
,或者的范围,Map(seq,start,end))
避免显式提取开始和结束。@MartinMorgan-好主意!Map
确实比lappy
快(大约快20%)…但我的另一个答案是使用do.call
仍然是最快的。即使它仍然只有0票:(尝试seq.int
以提高速度,使用USE.NAMES=FALSE
以Map
…你为什么不发布你的代码,可能是一个小细节导致了速度上的差异……为什么不发布你的代码,可能是一个小细节导致了速度上的差异…+1用于创新思维!我的m需要0.94秒与我的解决方案的1.6秒相比,achine…太棒了!你知道完成一个解析比一个循环花费的时间少吗?编辑:@Tommy谢谢你确认它没有问题。我认为使用parse
的运气在这里并不适用:…但我倾向于尝试使用do。打电话给来避免这个问题。+1代表创新思维ng!与我的解决方案的1.6秒相比,这在我的机器上花费了0.94秒…太棒了!你知道完成一个解析比一个循环花费的时间少吗?编辑:@Tommy谢谢你确认它是正确的。我认为使用parse
的运气在这里并不适用:…但我倾向于尝试使用do.call
来避免这种情况詹姆斯的代码最大的优点是它根本不需要for循环。@省略号…这个也不需要。它使用lappy
:-)…最终速度会更快。要键入的字符数也几乎相同。因此,即使在时间/字符的基础上,这也更有效…而且它避免了对使用解析的反对意见:james的代码的优点是它根本不需要for循环。@省略号…这个也不需要。它使用e> lappy
:-)…并且最终会更快一些。要键入的字符数也几乎相同。因此,即使在时间/字符的基础上,这也更有效……而且它避免了对使用解析的异议: