首页 > 解决方案 > 将数据帧保存为函数中的 csv,而不是通过列表(iwalk?)

问题描述

我正在从 SQL 数据库中读取非常大的文件,进行一些数据处理并尝试将最终版本保存为csv文件,因为我默默地进行操作。我在这个主题上遇到的大多数问题都建议先将我的数据框保存在一个列表中,然后像这样单独保存它们,这在这个非常小的示例中有效:

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

df_3这有效并创建了 3 个名为,的dfs df_4df_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).

这是正确的方法吗?欢迎任何建议。

谢谢

标签: rcsvlapplypurrr

解决方案


我认为你的想法和方法是正确的。将函数中的一行更改为:

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 会被覆盖,因此您只剩下一个包含最新数据的 csv。现在检查是什么x

sql_fun4 <- function(x) {
   x
 }

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

#[[2]]
#[1] 4

#[[3]]
#[1] 5

因此,这将为您提供每次迭代的唯一 csv。


推荐阅读