Вот один из способов. Это «прославленный цикл» в маскировке lapply
в последовательности.
# 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))) )
Что дает правильный результат:
> newRanges
start end
1 1 2
2 3 4
3 2 3
4 4 5
5 3 4
А потом рассмотрим более серьезную проблему:
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) ) )
Это займет около 1,6 секунд на моей машине. Достаточно хорошо?
... Хитрость заключается в том, чтобы работать с векторами напрямую, а не с data.frame. А затем создайте data.frame в конце.
Обновление @Ellipsis ... отметил, что lapply
не лучше, чем цикл for. Посмотрим:
system.time( a <- unlist(lapply(seq_along(start), function(i) start[i]+seq(0, end[i]-start[i]))) ) # 1.6 secs
system.time( b <- {
res <- vector('list', length(start))
for (i in seq_along(start)) {
res[[i]] <- start[i]+seq(0, end[i]-start[i])
}
unlist(res)
}) # 1.8 secs
Таким образом, цикл for не только примерно на 12% медленнее в этом случае, но и намного более многословен ...
ОБНОВЛЕНИЕ СНОВА!
@ Мартин Морган предложил использовать Map
, и это действительно самое быстрое решение - быстрее, чем do.call
в моем другом ответе. Кроме того, с помощью 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) )