【问题标题】:Return a data frame from function从函数返回一个数据框
【发布时间】:2014-08-04 10:48:15
【问题描述】:

我在函数中有以下代码

Myfunc<- function(directory, MyFiles, id = 1:332) {
# uncomment the 3 lines below for testing
#directory<-"local"
#id=c(2, 4)
#MyFiles<-c(f2.csv,f4.csv)
idd<-id

df2 <- data.frame()

for(i in 1:length(idd)) {
  EmptyVector <- read.csv(MyFiles[i])  
  comp_cases[i]<-sum(complete.cases(EmptyVector))
  print(comp_cases[[i]])
  id=idd[i]
  ret2=comp_cases[[i]]
  df2<-rbind(df2,data.frame(id,ret2))
 }
print(df2)
return(df2)
}

当我尝试通过选择函数内的代码并注释掉返回值来在 R 中运行它时,这很有效。我从 print 语句中得到了一个不错的数据框:

> df2
 id ret2
1 2  994
2 4  7112

但是,当我尝试从函数返回数据帧 df2 时,它只返回第一行,而忽略所有其他值。我的问题是它在函数中适用于我尝试过的各种值(打开具有各种组合的多个文件),而不是在我尝试返回数据框时。有人可以帮忙吗。非常感谢提前。

【问题讨论】:

  • 你是如何调用你的函数的?

标签: r function dataframe


【解决方案1】:

如果我理解正确,您正在尝试创建一个数据框,其中包含每个 id 的完整案例数。假设您的文件是具有您指定的 id 编号的名称(例如f2.csv),您可以按如下方式简化您的功能:

myfunc <- function(directory, id = 1:332) {
  y <- vector()
  for(i in 1:length(id)){
    x <- id
    y <- c(y, sum(complete.cases(
      read.csv(as.character(paste0(directory,"/","f",id[i],".csv"))))))
  }
  df <- data.frame(x, y)
  colnames(df) <- c("id","ret2")
  return(df)
}

你可以这样调用这个函数:

myfunc("name-of-your-directory",25:87)

上面代码的解释。您必须将问题分解为几个步骤:

  1. 你需要一个 id 的向量,这是由x &lt;- id 完成的
  2. 对于每个id,您需要完整案例的数量。为了得到它,你必须先阅读文件。这是由read.csv(as.character(paste0(directory,"/","f",id[i],".csv"))) 完成的。要获取该文件的完整案例数,您必须将 read.csv 代码包装在 sumcomplete.cases 中。
  3. 现在您想将该数字添加到向量中。因此,您需要一个空向量 (y &lt;- vector()),您可以将步骤 2 中的完整案例数添加到该向量中。这是通过将步骤 2 中的代码包装在 y &lt;- c(y, "code step 2") 中来完成的。这样,您可以将每个 id 的完整案例数添加到向量 y
  4. 最后一步是将这两个向量组合成一个带有df &lt;- data.frame(x, y) 的数据框,并分配一些有意义的colnames

通过在 for 循环中包含步骤 1、2 和 3(y &lt;- vector() 部分除外),您可以遍历指定 id 的列表。使用y &lt;- vector() 创建空向量必须在for 循环之前完成,以便for 循环可以将值添加到y

【讨论】:

  • @Japp - 效果很好。代码更干净。是的,我试图返回带有 ID 的完整案例的数据框。如果你告诉我哪里出错了,它仍然会有所帮助。
  • @user3127034 - 你出错的主要部分是在你的函数中包含Myfiles 参数。它不是必需的,因为您的文件名具有所有相同的结构并且可以从 id 派生。我添加了一个解释。我希望这会有所帮助。
【解决方案2】:

这个其实很容易通过改变范围来解决。

问题是您最初将初始数据框创建为局部变量,然后您只是交换了行,因此您最终只会得到数据框中的第一个和最后一个结果。

当我使用 R 创建一个 for 循环并希望将连续查询等的结果添加到某个初始数据帧时,我会这样做:

function(<some_args>){ 
main_dataframe <<- do something to generate the first set of results from 
whatever you want to iterate, like 1:10, a given list, etc. and create the 
initial dataframe from the first iteration and use the global assignment 
('<<-'), not '<-' or '='

main_dataframe <<- do_something(whatever_you're_iterating_over[1])

for (i in 2:length(whatever_you're_iterating_over)) {
next_dataframe = do_something(whatever_you're_iterating_over[i])

main_dataframe <<- rbind(main_dataframe, next_dataframe)
    }
}

范围将允许每次迭代创建一个数据框,您可以将其附加到原始数据框,而不会丢失第一次和最后一次之间的任何迭代。

【讨论】:

  • 感谢您提及&lt;&lt;- 全局赋值运算符。这在我的上下文中很有帮助
猜你喜欢
  • 2017-11-05
  • 1970-01-01
  • 2022-01-21
  • 2016-11-22
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多