Ответ 1
edit:
Старое предложенное решение t3 <- sapply(1:ncol(bigDF), function(idx) class(bigDF[,idx]))
теперь изменено на t3 <- sapply(1:ncol(bigDF), function(idx) class(bigDF[[idx]]))
. Это еще быстрее. Благодаря комментарию @Wojciech
Причина, по которой я могу думать, заключается в том, что вы без необходимости конвертируете data.frame в список. Кроме того, ваши результаты также не идентичны.
bigDF <- as.data.frame(matrix(0, nrow=1E5, ncol=1E3))
t1 <- sapply(bigDF, class)
t2 <- for_soln(bigDF)
> head(t1)
V1 V2 V3 V4 V5 V6
"numeric" "numeric" "numeric" "numeric" "numeric" "numeric"
> head(t2)
[1] "numeric" "numeric" "numeric" "numeric" "numeric" "numeric"
> identical(t1, t2)
[1] FALSE
Выполнение Rprof
on sapply
говорит, что все потраченное время находится на as.list.data.fraame
Rprof()
t1 <- sapply(bigDF, class)
Rprof(NULL)
summaryRprof()
$by.self
self.time self.pct total.time total.pct
"as.list.data.frame" 1.16 100 1.16 100
Вы можете ускорить операцию, не спрашивая as.list.data.frame
. Вместо этого мы могли просто запросить класс каждого столбца data.frame
напрямую, как показано ниже. Это в точности эквивалентно тому, что вы делаете с for-loop
на самом деле.
t3 <- sapply(1:ncol(bigDF), function(idx) class(bigDF[[idx]]))
> identical(t2, t3)
[1] TRUE
microbenchmark(times=20,
sapply(bigDF, class),
for_soln(bigDF),
sapply(1:ncol(bigDF), function(idx)
class(bigDF[[idx]]))
)
Unit: milliseconds
expr min lq median uq max
1 for-soln (t2) 38.31545 39.45940 40.48152 43.05400 313.9484
2 sapply-new (t3) 18.51510 18.82293 19.87947 26.10541 261.5233
3 sapply-orig (t1) 952.94612 1075.38915 1159.49464 1204.52747 1484.1522
Разница в t3
заключается в том, что вы создаете список длиной 1000 каждый с длиной 1. В то время как в t1 его список длиной 1000, каждый длиной 10000.