R:为什么我没有得到按预期返回向量的函数?

时间:2016-09-04 16:24:13

标签: r for-loop return

    corr <- function(directory, threshold) { 
          files <- list.files(directory, full.names = TRUE)
          nu <- numeric()
          for(i in length(files)) {
            my_data <- read.csv(files[i])
            if (sum(complete.cases(my_data)) >= threshold) {
              vec_sul <- my_data[complete.cases(my_data),]$sulfate
              vec_nit <- my_data[complete.cases(my_data),]$nitrate
              nu <- c(nu, cor(vec_sul, vec_nit))
            }
          }
      nu
    }

我有一个.csv文件列表,这些文件位于我希望作为参数传递给上述函数的目录中。我也传递阈值作为第二个参数。目标是读取目录参数中的所有文件,并检查文件是否具有超过作为第二个arg传递的阈值的完整案例。

将进一步检查那些通过此标准的文件,并评估其中的两个变量之间的相关性:硫酸盐和硝酸盐。与具有比阈值更完整的情况的文件相关联的一系列这样的相关值将被连接到数值变量向量。在循环执行结束时,我希望函数返回包含在&#34中评估的一系列相关值的向量;如果&#34;循环。

cr&lt; - corr(&#34; specdata&#34;,150) 当我在控制台中运行上面的代码行时,我得到一个null的数字变量。有人可以帮我修复代码吗?

2 个答案:

答案 0 :(得分:0)

虽然已经多次看到这种错误,但它仍然会发生。你想要

i in 1:length(files)

你得到numeric(0)(&#34;数字空&#34;你谈到),因为你的循环只读取最终文件。我猜最终文件不满足sum(complete.cases(my_data)) >= threshold,因此nu没有添加任何内容,初始化为numeric(0)

另外,我想指出

vec_sul <- my_data[complete.cases(my_data),]$sulfate
vec_nit <- my_data[complete.cases(my_data),]$nitrate
nu <- c(nu, cor(vec_sul, vec_nit))

可以替换为

nu <- c(nu, with(my_data, cor(sulfate, nitrate, use = "complete.obs")))

答案 1 :(得分:0)

考虑跨文件列表的向量化lapply(),避免扩展预设向量。唯一的调整是lapply将返回等于输入列表files的长度,因此添加else语句以填充具有未满足阈值条件的数据帧。但是在循环之外,nu被删除了这些NAs。

corr <- function(directory, threshold) { 

           files <- list.files(directory, full.names = TRUE)
           nu <- lapply(files, function(i) {
               my_data <- read.csv(i)
               if (sum(complete.cases(my_data)) >= threshold) {
                   vec_sul <- my_data[complete.cases(my_data),]$sulfate
                   vec_nit <- my_data[complete.cases(my_data),]$nitrate
                   temp <- cor(vec_sul, vec_nit)
               } else {
                   temp <- NA           # SET NAs   
               }
               return(temp)
           })

       nu <- nu[!is.na(nu)]             # REMOVE NAs
       return(nu)
}

或者,尝试使用vapply()(可以说稍快一点)来指定数字向量返回

corr <- function(directory, threshold) { 

           files <- list.files(directory, full.names = TRUE)          
           nu <- vapply(files, function(i) {
               my_data <- read.csv(i)
               if (sum(complete.cases(my_data)) >= threshold) {
                   vec_sul <- my_data[complete.cases(my_data),]$sulfate
                   vec_nit <- my_data[complete.cases(my_data),]$nitrate
                   temp <- cor(vec_sul, vec_nit)
               } else {
                   temp <- NA           # SET NAs    
               }
               return(temp)
           }, numeric(1))          

       nu <- nu[!is.na(nu)]             # REMOVE NAs
       return(nu)
}