сохранить данные в виде csv в функции без вывода сообщений из списка (iwalk?) - PullRequest
1 голос
/ 06 апреля 2020

Я читаю в очень больших файлах из базы данных SQL, выполняю некоторую обработку данных и пытаюсь сохранить окончательную версию в виде csv файла как I go в автоматическом режиме. Большинство вопросов, с которыми я сталкивался в этой топи c, предлагают сначала сохранить мои фреймы данных в списке, а затем сохранить их по отдельности, как показано ниже.

library(tidyverse)
SQLlarge <- mtcars
SQLlarge2 <- mtcars
sql_fun <- function(x) {

  sql_large_filter <- SQLlarge %>% 
    filter(gear == {{x}})
  #other data processing

  sql_large_filter2 <- SQLlarge2 %>% 
    filter(gear == {{x}})
  #other data processing

  final <- sql_large_filter %>% 
    bind_rows(sql_large_filter2)
  final
}
sql_fun(3)
temp <- lapply(c(3, 4, 5), sql_fun)
names(temp) <- paste0("df_", 3:5)
lapply(1:length(temp), function(x) write_csv(temp[[x]], path = paste0("C:\\Users\\", names(temp[x]), ".csv")))

это работает и создает 3 dfs называются df_3, df_4, df_5, но поскольку мои файлы настолько большие, я не хочу сначала сохранять их в большом списке, поэтому я хочу сохранить в конце каждой итерации в конце функции или сохранить молча (iwalk?). Примерно так:

sql_fun2 <- function(x) {

  sql_large_filter <- SQLlarge %>% 
    filter(gear == {{x}})
  #other data processing

  sql_large_filter2 <- SQLlarge2 %>% 
    filter(gear == {{x}})
  #other data processing

  final <- sql_large_filter %>% 
    bind_rows(sql_large_filter2)


  arg_name <- deparse(substitute(x)) # Get argument name
  var_name <- paste("df", arg_name, sep = "_") 
  #assign(var_name, final, env = .GlobalEnv) 

  write_csv(final, path = paste0("C:\\Users\\", var_name, ".csv")) 

  #OR iwalk?
  # lst(final) %>%
  #   iwalk(., function(df, name) {
  #     write_csv(df, sprintf("C:\\Users\\%s.csv", name))
  #   })

}
sql_fun(3)
#works df_3 created but when calling over 3:5: 

map(3:5, sql_fun2)
#returns only one df called "df_.x[[i]].csv"

Это возвращает только один df с именем df_.x[[i]].csv, поэтому я неправильно индексирую в моем write_csv вызове внутри функции? Другой вариант состоял в том, чтобы сохранить его в режиме без вывода сообщений, используя iwalk, поэтому включите в sql_fun2 следующее:

lst(final) %>%       #not sure how to rename final within dataframe first?
  iwalk(., function(df, name) {
    write_csv(df, sprintf("C:\\Users\\%s.csv", name))
  })

, но я не уверен, как присвоить имя кадру данных, который я не назначаю для глобальная среда (обычно мы переименовываем фрейм данных в assign(var_name, final, env = .GlobalEnv).

Это правильный подход? Любые предложения приветствуются.

спасибо

1 Ответ

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

Я думаю, что ваше мышление и подход верны. Измените одну строку в функции на:

library(purrr)

sql_fun2 <- function(x) {
   #All other lines of the function as it is
   #Previous line
   #write_csv(final, path = paste0("C:\\Users\\", var_name, ".csv"))
   #New line
   write_csv(final, path = paste0("C:\\Users\\", x, ".csv")) 
}

и затем вызовите ее с помощью

purrr::map(3:5, sql_fun2)

Суть вопроса в том, как аргументы передаются в функцию. Основное замешательство - deparse(substitute(x)). Проверьте его значение:

sql_fun3 <- function(x) {
    deparse(substitute(x)) 
 }

map(3:5, sql_fun3)
#[[1]]
#[1] ".x[[i]]"

#[[2]]
#[1] ".x[[i]]"

#[[3]]
#[1] ".x[[i]]"

Поскольку в каждой итерации используется одно и то же значение, предыдущий csv get перезаписывается, и у вас остается только один csv с последними данными. Теперь проверьте, что такое x

sql_fun4 <- function(x) {
   x
 }

map(3:5, sql_fun4)
#[[1]]
#[1] 3

#[[2]]
#[1] 4

#[[3]]
#[1] 5

Так что это даст вам уникальный CSV для каждой итерации.

...