【问题标题】:Loop through dataframes in global environment and apply function to them循环遍历全局环境中的数据框并将功能应用于它们
【发布时间】:2021-06-11 03:50:18
【问题描述】:

我将解释我的代码应该做什么:

首先,我导入任意数量的具有相同列数且名称有些相似的数据框(它们是股票行情)。

其次,我创建了一个函数来更改第一列的数据类型(从因子到日期),删除一列,最后添加任意数量的列作为其他列的函数(如返回、移动平均值等.)

最后,由于我正在处理大量数据帧,因此我想通过循环将上述函数应用于所有数据帧。

现在,听起来很简单,但我在第三步遇到了很多问题。

我在网上找到的是这样的,以获取我环境中数据框的所有名称:

dfs <- ls()[sapply(mget(ls(), .GlobalEnv), is.data.frame)]

它给出了数据帧名称字符串的向量。由于这些是字符而不是实际的数据框对象,我无法遍历它们,所以我添加了:

sapply( dfs, function(x) {
  get(x) <- formatear(get(x))
  })

这可能是个坏主意,因为我不熟悉 sapply 函数。

现在,我使用的 sapply 函数返回错误::

Error in get(x) <- formatear(get(x)) : 
  no se pudo encontrar la función "get<-"

我读到 get(x) 函数搜索在向量“x”上具有名称的变量,所以我想我可以这样使用它,我的错。

其中 formatear() 是我在第二步中的函数:

formatear <- function(eq){
  eq$Volume <- NULL
  eq$Date <- as.Date(eq$Date)

  nt <- eq$Adj.Close[1:nrow(eq)-1]
  nt1 <- eq$Adj.Close[2:nrow(eq)]
  eq$return <- percent(c(NA, nt1/nt-1), accuracy = 0.0001)
  return(eq) 
  }

它将数据框作为参数并返回以我打算使用的方式转换的数据框。

当我将函数的值分配给它之后,在单个数据帧上使用它时效果很好,这就是我尝试将它分配给 get(x) 的原因。

接下来我想修改我的函数,这样我只需要在 sapply 中调用它,而不必使用 assign() 函数将其分配给任何东西,因此它会直接更改全局环境中的变量。像这样的:

sapply( dfs, function(x) {formatear(get(x))})

通过将 formatear() 更改为:

formatear <- function(eq){
  eq$Volume <- NULL
  eq$Date <- as.Date(eq$Date)

  nt <- eq$Adj.Close[1:nrow(eq)-1]
  nt1 <- eq$Adj.Close[2:nrow(eq)]
  eq$return <- percent(c(NA, nt1/nt-1), accuracy = 0.0001)
  assign(deparse(substitute(eq)), eq, envir = globalenv()) #Changed here
  }

我使用了 deparse(substitute(eq)) 因为 assign() 只需要字符串来查找全局环境中的变量。我也在网上找到了那段代码。 这不起作用,它创建了具有奇怪名称的新数据框(格式正确):

structure(list(Date = structure(c(16962, 16965, 16966, 16967, #this is one of the names of these new dataframes

它也返回:

In assign(deparse(substitute(eq)), eq, envir = globalenv()) : only the first element is used as variable name

它甚至没有遍历所有数据帧,只有两个。 所以这就是整个故事,我不知道还能做什么,谷歌搜索似乎没有帮助。欢迎对我解释的任何问题提出建议。另外,也许想知道是否有一种方法可以将我的环境中的所有数据帧存储到一个向量中,以便我可以使用 for 循环? 无论如何,提前谢谢你。

【问题讨论】:

  • 最终我认为这归结为与 R 对抗而不是与它一起工作。如果您将相关数据保存在正确命名的列表中,而不是在您的全局环境中漂浮一堆 data.frame,那么思考会容易得多。见how to make a list of data.frames。你最好避免get/mget/assign之类的东西
  • 您是否考虑过将您的 data.frames 读入一个列表开始?您可以使用例如lapply() 循环来阅读它们。这可能是开始解决这类问题的一种便捷方式(即,您想要对许多相似的数据集做同样的事情)。

标签: r


【解决方案1】:

保留您原来的formatear 功能

formatear <- function(eq){
  eq$Volume <- NULL
  eq$Date <- as.Date(eq$Date)
  
  nt <- eq$Adj.Close[1:nrow(eq)-1]
  nt1 <- eq$Adj.Close[2:nrow(eq)]
  eq$return <- percent(c(NA, nt1/nt-1), accuracy = 0.0001)
  return(eq) 
}

您可以使用mget 获取数据框列表并使用lapply 应用该函数。

clean_list_data <- lapply(mget(dfs), formatear)

clean_list_data 应该是您想要的格式的数据框列表。您可以使用clean_list_data[[1]]clean_list_data[[2]] 等访问单个数据框。如果将数据保存在这样的列表中,而不是在全局环境中创建多个数据框,则管理数据会更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 2022-11-22
    • 2021-01-19
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多