Как сделать цикл быстрее?

Мой код выглядит так, как показано ниже, мне интересно, есть ли лучший способ сделать его быстрее:

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)
}

Ну да, цикл for ничего не делает :)

moodymudskipper 12.05.2022 12:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
45
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Не нужна петля. Вы можете построить 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()

moodymudskipper 12.05.2022 12:29

да, правда, был еще один первый подход, который не сработал. Тай

Stephan 12.05.2022 13:01

Это тоже была моя первоначальная идея. Однако OP запросил решение Быстрее, и мое тестирование с использованием microbenchmark показало, что этот подход был на в среднем медленнее, чем решение OP, из-за небольшого количества очень медленных итераций. Поэтому я не выложил. Что показывает ваше тестирование?

Limey 12.05.2022 13:04

Кроме того, я думаю, что вы неправильно истолковали намерение ОП. OP, похоже, реплицирует фрейм данных из 216 строк один раз для каждого значения trail (так в оригинале), что дает фрейм данных из 216 000 строк. Обратите внимание на вызов rbind() в последней строке цикла. Похоже, что ваше решение дает фрейм данных из 10000 строк.

Limey 12.05.2022 13:12

правильно, мы должны спросить об ожидаемом результате его/ее цикла.

Stephan 12.05.2022 13:28

Похоже, вы пытаетесь воспроизвести этот фрейм данных 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)
)

Другие вопросы по теме