Проблема с использованием мутирования внутри цикла for - PullRequest
0 голосов
/ 14 марта 2020

Я пытаюсь написать функцию с именем complete, которая принимает файловый каталог (в котором есть csv-файлы с именем 1-332) и заголовок файла в виде числа, чтобы распечатать количество строк без NA в сульфате или нитратные колонны. Я пытаюсь использовать mutate для добавления столбца с заголовком nobs, который возвращает 1, если ни один из столбцов не равен na, а затем берет сумму nobs за мой ответ, но я получаю сообщение об ошибке, что объект nob не найден. Как я могу это исправить? Указанный каталог файлов c, о котором идет речь, загружается в этот блок кода.

library(tidyverse)
if(!file.exists("rprog-data-specdata.zip")) {
  temp <- tempfile()
  download.file("https://d396qusza40orc.cloudfront.net/rprog%2Fdata%2Fspecdata.zip",temp)
  unzip(temp)
  unlink(temp)
}

complete <- function(directory, id = 1:332){
  #create a list of files
  files_full <- list.files(directory, full.names = TRUE)
  #create an empty data frame
  dat <- data.frame()
  for(i in id){
    dat <- rbind(dat, read.csv(files_full[i]))
  }
  mutate(dat, nob = ifelse(!is.na(dat$sulfate) & !is.na(dat$nitrate), 1, 0))
  x <- summarise(dat, sum = sum(nob))

return(x)
}

Когда выполняется следующий код, nobs должен быть 117, но вместо этого я получаю сообщение об ошибке

complete("specdata", 1)

Ошибка: объект 'nob' не найден "

Ответы [ 2 ]

2 голосов
/ 14 марта 2020

Я думаю, что функция ниже должна получить то, что вам нужно. Вместо al oop я предпочитаю карту (или применять) в этой настройке. Трудно сказать, где ваш код не работает без сообщения об ошибке или примера, который я могу запустить на своем компьютере, однако.

Happy Coding, Daniel

library(tidyverse)
complete <- function(directory, id = 1:332){
  #create a list of files
  files_full <- list.files(directory, full.names = TRUE)

  # cycle over each file to get the number of nonmissing rows
  purrr::map_int(
    files_full,
    ~ read.csv(.x) %>% # read in datafile 
      dplyr::select(sulfate, nitrate) %>% # select two columns of interest
      tidyr::drop_na %>% # drop missing observations
      nrow() # get the number of rows with no missing data
  ) %>%
    sum() # sum the total number of rows not missing among all files
}
1 голос
/ 14 марта 2020

Как уже упоминалось, избегайте строительных объектов в al oop. Вместо этого рассмотрите возможность создания списка фреймов данных из каждого CSV, а затем вызовите rbind один раз. На самом деле, даже рассмотрите base R (то есть tinyverse ) для всех ваших потребностей:

complete <- function(directory, id = 1:332){
  # create a list of files
  files_full <- list.files(directory, full.names = TRUE)

  # create a list of data frames
  df_list <- lapply(files_full[id], read.csv)

  # build a single data frame with nob column
  dat <- transform(do.call(rbind, df_list), 
                   nob = ifelse(!is.na(sulfate) & !is.na(nitrate), 1, 0)
         )

  return(sum(dat$nob))
}
...