% do% Vs. % dopar%,% dopar% не вносит никаких изменений, никаких предупреждений - PullRequest
0 голосов
/ 08 ноября 2018

(Нет тега для r-параллельной обработки или пакета foreach для R, если бы он был, я бы отметил их здесь. Приветствуются предложения тегов).

У меня есть фрейм данных "training_data" и вектор "cats" (для категориальных данных).

кошка выглядит как c("fruits", "vegetables", "meats")

Я хочу перебрать каждую из кошек в данных тренировки и заменить любые низкочастотные уровни просто «Другие».

Это работает:

library(foreach)
foreach(c = cats) %do% { # not parallel processing
  print(c)
  freqs <- table(training_data[c])
  low_freqs <- names(which(freqs < 20000))
  training_data[c][[1]] <- ifelse(training_data[c][[1]] %in% low_freqs, "Other", training_data[c][[1]])
  return(NULL) # otherwise spits out the whole thing
}

На каждой итерации в первой строке print (c) выводится значение оперируемого вектора cat, и я вижу его в консоли:

"фрукты" "овощи" "мясо"

После этих кошек на терминал выводятся 3 экземпляра NULL, ожидаемые из-за последней строки в цикле. Когда я проверяю свой фрейм данных training_data, категориальные переменные были преобразованы, как и ожидалось. Любой уровень с частотой менее 20 КБ был заменен другим.

Однако, если я попытаюсь использовать параллель:

library(foreach)
foreach(c = cats) %dopar% { # parallel (I have 8 cores)
  print(c)
  freqs <- table(training_data[c])
  low_freqs <- names(which(freqs < 20000))
  training_data[c][[1]] <- ifelse(training_data[c][[1]] %in% low_freqs, "Other", training_data[c][[1]])
  #return(NULL) # otherwise spits out the whole thing
}

Все, что происходит, это то, что NULLS печатаются на консоли. Данные обучения не преобразуются, и на консоли не отображается отпечаток (c).

Почему работает только%%, а не% dopar%?

1 Ответ

0 голосов
/ 08 ноября 2018

Вот подход, использующий некоторые другие примеры данных. Параллельно данные итератора копируются в подпроцесс, поэтому ограничение копируемого важно для производительности и использования памяти.


library(doParallel)

# make a cluster

cl <- makeCluster(2)
registerDoParallel(cl)

# sample data

cats <- c("fruits", "vegetables", "meats")
df <- read.csv(text = "
cat,n
fruits,1
fruits,2
vegetables,4
meats,5
", stringsAsFactors = FALSE)

# Use foreach to iterate over a split dataframe, so only the subset data
# will be copied into each parallel process. Specify .combine = rbind to
# bind the resulting dataframe into one dataframe parallel 

result <- foreach(dfs = split(df, df$cat), .combine = rbind) %dopar% {

 # Print to show the structure of each split - Won't print in parallel
 # because the output .. will go to the console output of each process


  cat("Inside...\n")
  print(dfs)

  # Derive a new column
  dfs$new_col <- ifelse(dfs$n > 2, ">2", "<=2")

  # Return the result without printing
  invisible(dfs)  
}

# Print the combined new dataframe
print(result)
#>          cat n new_col
#> 1     fruits 1     <=2
#> 2     fruits 2     <=2
#> 4      meats 5      >2
#> 3 vegetables 4      >2
...