Оптимизировать вложенные циклы с помощью apply или аналогичных - PullRequest
0 голосов
/ 08 февраля 2020

Код, который я здесь показываю, вычисляет именно то, что я хочу, за исключением одной проблемы: для больших наборов данных требуется всего лишь СЛИШКОМ ДЛИННОЕ . Поэтому мне было интересно, есть ли альтернативное решение, использующее семейство apply () или каким-либо другим способом .

Мне всегда трудно перевести express вложенные циклы в векторные функции , Как вы думаете, вы могли бы помочь мне? Я был бы очень признателен;)

Итак, до применения этого вложенного цикла у меня уже есть:

  1. 2 кадра данных , называемых "ДАННЫЕ" и "DATA_100_WELLS" . Из них мне нужны только переменные "ХОРОШО" (категориальные) и "ДЕЛЬТА" (цифры c)
  2. 3 глобальные переменные, называемые ti, ta и tb, которые появятся во вложенных циклах
  3. A "selected_model" , которые я буду использовать внутри функции "ести "

Вот и все ... извините, если это трудно понять ...

#loop for each WELL from "DATA_100_WELLS"
for (WELL_PROCESS in unique(DATA_100_WELLS$WELL)) {
  #----------------------------------------------------------------------------------
  #I take just 1 of the wells
  print("WELL------------------------------------------------------------")
  print(WELL_PROCESS)
  DATA_WELL <- DATA_100_WELLS[DATA_100_WELLS$WELL==WELL_PROCESS,] #select just the well I want

  #I calculate some stuff (Var_est0, sigma, linf, lsup, Za, Zb, n_ray and A)
  DATA_WELL$Var_est0 = predict(chosen_model,data.frame(predict=DATA_WELL$predict))
  DATA_WELL$sigma    = sqrt(DATA_WELL$Var_est0)
  DATA_WELL$linf     <- DATA_WELL$predict+DATA_WELL$sigma*ta
  DATA_WELL$lsup     <- DATA_WELL$predict+DATA_WELL$sigma*tb
  Za                 <- qnorm(alfa/2)
  Zb                 <- qnorm(1-alfa/2)
  n_ray              <- mean(DATA_WELL$predict)
  A                  =  sum(DATA_WELL$Var_est0)

  #Then i create an empty df called "TABLE", and slice off the heading
  TABLE<-data.frame(well="",d=0,p=0)
  TABLE<-TABLE[-1,]
  #After that, I iterate over each WELL from the second df, "DATA"
  for (well in unique(DATA$WELL)){
    print(paste("Process...: ",well,sep=""))
    #I calculate variable "large",based on max value of the existing variable "DELTA" (numeric)
    large = max(DATA[DATA$WELL==well,]$DELTA)
    #cicle from 1 max.distance (large-1)
    for (d in c(1:(large-1))){
      #cicle from position 1 to large-distance (look how this turns to be symmetric)
      for (pos in (1:(large-d))){
        #I did all of this to calculate variables ti and tj 
        ti = DATA[DATA$WELL==well & DATA$DELTA==pos,]$ti
        tj = DATA[DATA$WELL==well & DATA$DELTA==pos+d,]$ti
        #I append the results into the once empty df "TABLE", and calculate p based on ti*tj
        TABLE<-rbind(TABLE,data.frame(well=well,d=d,p=ti*tj))
      }
    }
  }

Ссылки:

  1. "ХОРОШО" - категориальная переменная с указанием имен
  2. "DELTA" - это уже существующая переменная, присутствующая в обеих df
  3. Всего имеется 4 цикла : сначала для каждого ХОРОШО в df1. Во-вторых, для каждого ХОРОШО в df2. В-третьих, для каждого расстояния в векторе 1: (большое-1). Наконец, для каждой позиции в векторе 1: (large-1) и выполните симметричное вычисление c, сохраненное в df "TABLE".

Вот и все. Решение также может быть записано в Python, если необходимо.

Серьезно, спасибо !!

1 Ответ

2 голосов
/ 09 февраля 2020

Как уже упоминалось в комментариях, без воспроизводимого примера трудно помочь, хотя я попробую. Следующие изменения должны ускорить процесс:

1) не привязывать объект к себе повторно, а вставлять элементы в список и вызывать bind_rows после циклов.

2) подставьте DATA df в wells_df для каждой лунки во внешнем l oop.

Даже лучше, чем # 2, но не реализовано, вы можете разбить ДАННЫЕ на список на ХОРОШО перед циклами, чтобы вы только один раз проходили через ДАННЫЕ.

Я не запускал этот код.

table_agg <- list()

for (well in unique(DATA$WELL)){
  print(paste("Process...: ",well,sep=""))
  #I calculate variable "large",based on max value of the existing variable "DELTA" (numeric)
  wells_df <- DATA[DATA$WELL==well,]
  large = max(wells_df$DELTA)
  #cicle from 1 max.distance (large-1)
  for (d in c(1:(large-1))){
    #cicle from position 1 to large-distance (look how this turns to be symmetric)
    for (pos in (1:(large-d))){
      #I did all of this to calculate variables ti and tj 
      ti = wells_df[wells_df$DELTA==pos,]$ti
      tj = wells_df[wells_df$DELTA==pos+d,]$ti
      #I append the results into the once empty df "TABLE", and calculate p based on ti*tj
      table_agg[[length(table_agg)+1]]<-data.frame(well=well,d=d,p=ti*tj)
    }
  }
}

TABLE <- dplyr::bind_rows(table_agg)
...