Уменьшите ненужные повторные чтения из файлов во вложенных для l oop R - PullRequest
0 голосов
/ 19 апреля 2020

Я пишу код R для обработки пар файлов, Excel и CSV (Imotions.txt). Мне нужно извлечь столбец из Excel и объединить его в CSV, попарно. Ниже приведен мой сокращенный сценарий: мой сценарий теперь находится в полиномиальном времени и продолжает повторять тело вложенного элемента l oop 4 раза вместо того, чтобы просто делать это один раз.

В принципе, существует ли общий способ мышления о запуске некоторого кода через парный набор файлов, которые я могу перевести на этот и другие языки?

excel_files <- list.files(pattern = ".xlsx"    , full.names = TRUE)
imotion_files <-list.files(pattern = 'Imotions.txt', full.names = TRUE)

for (imotion_file in imotion_files) {
  for (excel_file in excel_files) {

    filename <- paste(sub("_Imotions.txt", "", imotion_file))

    raw_data <- extract_raw_data(imotion_file)

    event_data <- extract_event_data(imotion_file)


    #convert times to milliseconds
    latency_ms <- as.data.frame(
      sapply(
        df_col_only_ones$latency,
        convert_to_ms,
        raw_data_first_timestamp = raw_data_first_timestamp
      )
    )

    #read in paradigm data
    paradigm_data <- read_excel(path = excel_file, range = "H30:H328")

    merged <- bind_cols(latency_ms, paradigm_data)

    print(paste("writing = ", filename))
        write.table(
        merged,
        file = paste(filename, "_EVENT", ".txt", sep = ""),
        sep = '\t',
        col.names = TRUE,
        row.names = FALSE,
        quote = FALSE
        )
  }
}

Ответы [ 2 ]

1 голос
/ 19 апреля 2020

Исходя из именования raw_data_first_timestamp, я предполагаю, что он создан функцией extract_raw_data - в противном случае вы можете полностью переместить latency_ms за пределы l oop, как упоминал Акрун.

Если вы этого не сделаете хотите использовать tidyverse, смотрите измененную версию вашего кода внизу. Обратите внимание, что циклы были разбиты для сокращения дублирующихся действий.

Некоторые общие советы по повышению эффективности при работе с циклами:

  • Прежде чем пытаться улучшить вложенные l oop Эффективность, подумайте, можно ли разбить циклы так, чтобы данные из предыдущих циклов сохранялись для использования в более поздних циклах. Это также можно сделать с помощью вложенных циклов и переменных, отслеживающих, были ли уже установлены данные, но обычно проще разбить циклы и устранить необходимость в переменных отслеживания.
  • Создавать переменные и вызывать функции до того, как l oop где возможно. В зависимости от языка и / или компилятора (если он используется), создание переменных вне циклов может не помочь с эффективностью, но все же это хорошая практика.
  • Переменные и функции, которые должны создаваться или вызываться внутри циклов, должны сделано в наивысшей возможной области видимости - или в крайнем случае l oop -

Отказ от ответственности - Я никогда не использовал R, поэтому возможны синтаксические ошибки.

excel_files <- list.files(pattern = ".xlsx"    , full.names = TRUE)
imotion_files <-list.files(pattern = 'Imotions.txt', full.names = TRUE)
paradigm_data_list <- vector("list", length(excel_files))

for (i in 1:length(excel_files)) {
  #read in paradigm data
  paradigm_data_list[[i]] <- read_excel(path = excel_files[[i]], range = "H30:H328")
}

for (imotion_file in imotion_files) {
  filename <- paste(sub("_Imotions.txt", "", imotion_file))
  raw_data <- extract_raw_data(imotion_file)
  event_data <- extract_event_data(imotion_file)

  #convert times to milliseconds
  latency_ms <- as.data.frame(
    sapply(
      df_col_only_ones$latency,
      convert_to_ms,
      raw_data_first_timestamp = raw_data_first_timestamp
    )
  )

  for (paradigm_data in paradigm_data_list) {
    merged <- bind_cols(latency_ms, paradigm_data)

    print(paste("writing = ", filename))
    write.table(
      merged,
      file = paste(filename, "_EVENT", ".txt", sep = ""),
      sep = '\t',
      col.names = TRUE,
      row.names = FALSE,
      quote = FALSE
    )
  }
}
1 голос
/ 19 апреля 2020

Не совсем понятно про некоторые операции. Вот опция в tidyverse

library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
out <- crossing(excel_files, imotion_files) %>%
            mutate(filename = str_remove(imotion_file, "_Imotions.txt"),
                    raw_data = map(imotion_files, extract_raw_data), 
                     event_data = map(imption_filess, extract_event_data),
                     paradigm_data = map(excel_files, ~ 
                           read_excel(.x, range = "H30:H328") %>%
                                        bind_cols(latency_ms, .))

На основе кода OP, latency_ms может быть создан вне l oop один раз и использоваться при привязке столбцов

...