Как я могу предотвратить rbind() от получения действительно медленно, как фрейм данных становится больше?
У меня есть фрейм данных только с 1 строкой. Для этого я начинаю добавлять строки с помощью rbind
df #mydataframe with only one row
for (i in 1:20000)
{
df<- rbind(df, newrow)
}
Это становится очень медленным, когда я расту. Почему это так? и как я могу сделать этот тип кода быстрее?
2 ответа:
Вы находитесь во 2-м круге ада, а именно не в состоянии предварительно выделить структуры данных.
Выращивание объектов таким образом-очень и очень плохая вещь в R. либо предварительно выделить и вставить:
df <- data.frame(x = rep(NA,20000),y = rep(NA,20000))
Или реструктурируйте код, чтобы избежать такого рода инкрементного добавления строк. Как обсуждалось в ссылке, которую я цитирую, причина медлительности заключается в том, что каждый раз, когда вы добавляете строку, R должен найти новый непрерывный блок памяти, чтобы соответствовать фрейму данных. Много копирования.
Я попробовал пример. Как бы то ни было, он соглашается с утверждением пользователя о том, что вставка строк в фрейм данных также очень медленная. Я не совсем понимаю, что происходит, поскольку я ожидал, что проблема распределения превзойдет скорость копирования. Может ли кто-нибудь повторить это, или объяснить, почему результаты ниже (rbind
Edit: в первый раз я забыл инициализировать объект в
hell2fun
в фрейм данных, поэтому код выполнял матричные операции, а не операции фрейма данных, которые намного быстрее. Если у меня будет возможность, я расширю сравнение до фрейма данных против Матрицы. Однако качественные утверждения в первом абзаце остаются в силе.N <- 1000 set.seed(101) r <- matrix(runif(2*N),ncol=2) ## second circle of hell hell2fun <- function() { df <- as.data.frame(rbind(r[1,])) ## initialize for (i in 2:N) { df <- rbind(df,r[i,]) } } insertfun <- function() { df <- data.frame(x=rep(NA,N),y=rep(NA,N)) for (i in 1:N) { df[i,] <- r[i,] } } rsplit <- as.list(as.data.frame(t(r))) rbindfun <- function() { do.call(rbind,rsplit) } library(rbenchmark) benchmark(hell2fun(),insertfun(),rbindfun()) ## test replications elapsed relative user.self ## 1 hell2fun() 100 32.439 484.164 31.778 ## 2 insertfun() 100 45.486 678.896 42.978 ## 3 rbindfun() 100 0.067 1.000 0.076