Мой код выглядит так, как показано ниже, мне интересно, есть ли лучший способ сделать его быстрее:
pos=NULL
row=data.frame(matrix(nrow=216,ncol=4))
colnames(row)=c("sub","subi","group","trial")
for (i in 1:100000){
row$sub = "Positive"
row$subi=NA
row$group=NA
row$subi[1:144]=c(1:144)
row$group[1:144]=1
row$subi[145:216]=c(1:72)
row$group[145:216]=2
row$trial=i
pos=rbind(pos,row)
}





Не нужна петля. Вы можете построить data.frame или tibble(мой пример) самостоятельно.
Учитывая, что вы хотите настроить длину строки позже:
library(dplyr)
n_rows <- 10000
tibble(
trail = 1:n_rows,
sub = "positive",
subi = c(seq(1:144), seq(1:72), rep(NA, n_rows-216)),
group = c(rep(1, 144), rep(2, 72), rep(NA, n_rows-216))
)
Выход:
# A tibble: 10,000 × 4
trail sub subi group
<int> <chr> <int> <dbl>
1 1 positive 1 1
2 2 positive 2 1
3 3 positive 3 1
4 4 positive 4 1
5 5 positive 5 1
6 6 positive 6 1
7 7 positive 7 1
8 8 positive 8 1
9 9 positive 9 1
10 10 positive 10 1
# … with 9,990 more rows
здесь не нужно mutate(), все может идти в звонилку tibble()
да, правда, был еще один первый подход, который не сработал. Тай
Это тоже была моя первоначальная идея. Однако OP запросил решение Быстрее, и мое тестирование с использованием microbenchmark показало, что этот подход был на в среднем медленнее, чем решение OP, из-за небольшого количества очень медленных итераций. Поэтому я не выложил. Что показывает ваше тестирование?
Кроме того, я думаю, что вы неправильно истолковали намерение ОП. OP, похоже, реплицирует фрейм данных из 216 строк один раз для каждого значения trail (так в оригинале), что дает фрейм данных из 216 000 строк. Обратите внимание на вызов rbind() в последней строке цикла. Похоже, что ваше решение дает фрейм данных из 10000 строк.
правильно, мы должны спросить об ожидаемом результате его/ее цикла.
Похоже, вы пытаетесь воспроизвести этот фрейм данных 100 000 раз, причем каждая итерация фрейма имеет другой номер trial.
data.frame(sub = rep("Positive", 216),
subi = c(1:144, 1:72),
group = rep(c(1, 2), c(144, 72)))
Функция replicate отлично подходит для многократного запуска статического кода. Таким образом, один из вариантов — создать свои 100 000 копий, а затем обновить пробный номер.
FrameList <-
replicate(n = 100,
{
data.frame(sub = rep("Positive", 216),
subi = c(1:144, 1:72),
group = rep(c(1, 2), c(144, 72)),
trial = rep(NA_real_, 216))
},
simplify = FALSE)
Чтобы обновить пробный номер, вы можете использовать цикл for.
for (i in seq_along(FrameList)){
FrameList$trial <- i
}
или вы можете попробовать что-то необычное, но с гораздо большим количеством кода
FrameList <- mapply(function(FL, i){
FL$trial <- i
FL
},
FrameList,
seq_along(FrameList),
SIMPLIFY = FALSE)
Куда бы вы ни пошли, вы можете сложить их все вместе с помощью
Frame <- do.call("rbind", FrameList)
Это, конечно, не самый элегантный способ сделать это, поэтому следите за тем, чтобы другие не давали вам другие хитрости. Но это, я полагаю, будет основным процессом, которому нужно следовать.
Единственное, что отличается в каждом проходе цикла, это trial. rep твой друг. Для других столбцов R будет автоматически перерабатываться, чтобы соответствовать самому длинному столбцу (здесь это trial с 21,6 млн строк).
pos <- data.frame(
sub = "Positive",
subi = c(1:144, 1:72),
group = rep.int(1:2, c(144, 72)),
trial = rep(1:1e5, each = 216)
)
Ну да, цикл for ничего не делает :)