如何从列表循环中创建R数据帧

时间:2018-03-19 21:15:39

标签: r for-loop dataframe

我在从R中的循环返回数据帧时遇到问题。我有一组函数可以读入文件并将它们转换为数据框,供更大的项目使用/可视化。

我有一个要传递的文件名列表:

populateFrames <- function(){
    for (frame in frameList){
        if (exists(frame) && is.data.frame(get(frame))){
            # do nothing
        }
        else {
            frame <- clean_data(gather_data(frame))
        }
    }
}

此函数遍历列表并运行函数以创建数据框(如果它们尚不存在)。

# manually create "apples" data frame
apples <- clean_data(gather_data(frameList[1]))

执行时,该函数运行时没有错误,但不会将任何数据帧保存到环境中。

我可以手动运行相同的东西并保存数据框:

# returns a data frame, "apples" to the environment 
assign(x = frame[1], value = clean_data(gather_data(frame[1])))

从我在这里阅读类似的问题,我看到assign()用于类似的事情。但是和以前一样,我可以手动运行代码;但是当放入循环内部时,没有数据框保存到环境中。

seqno

2 个答案:

答案 0 :(得分:1)

解决方案,遵循“尽可能少地改变OP实施”的原则。

这里有两个问题。

  1. 您的函数没有返回任何内容,因此发生的任何更改都会卡在函数的环境中
  2. 我认为您期望在frame语句中重新分配else以将其重新分配给frameList中的该元素。不是。
  3. 这是不推荐*的方法,在函数的父环境中分配变量。在这种情况下,您将 populatingFrames 作为副作用,改变父环境中的frameList。如果你想练习防御性编程,那么你想要避免改变输入。

    populateFrames <- function(){
        for (i in seq_along(frameList)){
            if (exists(frameList[[i]]) && is.data.frame(get(frameList[[i]]))){
                # do nothing
            }
            else {
                frameList[[i]] <<- clean_data(gather_data(frameList[[i]]))
            }
        }
    }
    

    这是RECOMMENDED版本,您可以在其中返回新的frameList(这意味着您必须将其分配给值)。

    populateFrames <- function(){
        for (i in seq_along(frameList)){
            if (exists(frameList[[i]]) && is.data.frame(get(frameList[[i]]))){
                # do nothing
            }
            else {
                frameList[[i]] <- clean_data(gather_data(frameList[[i]]))
            }
        }
        frameList
    }
    

答案 1 :(得分:1)

避免全局变量赋值,这通常是禁忌,尝试lapply:

lapply(
  frameList,
  function(frame){
    if(exists(frame) && is.data.frame(get(frame))){
      frame
    }else{
      clean_data(gather_data(frame))
    }
  }
)