2015-06-13 2 views
0

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

pollutantmean <- function(directory, pollutant, id = 1:332) { 
    filepath <- "/Users/jim/Documents/Coursera/2_R_Prog/Data" 
    for(i in seq_along(id)) { 
      if(id < 10) { 
        name <- paste("00", id[i], sep = "") 
      } 
      if(id >= 10 && id < 100) { 
        name <- paste("0", id[i], sep = "") 
      } 
      if(id >= 100) { 
        name <- id[i] 
      }  
    } 
    file <- paste(name, "csv", sep = ".") 
    station <- paste(filepath, directory, file, sep = "/") 
    monitor <- read.csv(station) 
    if(pollutant == "nitrate") { 
      x <- mean(monitor$nitrate, na.rm = T) 
    } 
    if(pollutant == "sulfate") { 
      x <- mean(monitor$sulfate, na.rm = T) 
    } 
    x 
} 

Однако, если я введу более одного файла (например, 70:72) Я получаю среднее значение для последнего файла только (72). Это подсказывает мне, что он вычисляет среднее значение для каждого файла и затем перезаписывает его средним значением следующего, так что выводится только последнее. Я смог бы решить это с помощью rbind(), но не могу понять, как назначить уникальные имена для каждой переменной, которые затем станут аргументами для rbind(). Я был бы признателен за любую помощь, которую может предложить любой. Cheers, Jim

+0

http://stackoverflow.com/questions/23640594/reading-multiple-files-and-calculating-mean-based-on-user-input – user227710

+0

Вы не»цикл по файлам! –

+0

Спасибо за помощь, Жюльен. Вы дали мне полезные советы о «sprintf» и работе с циклами. Однако ваш код дает такое же количество средств, что и «длина (id)». То, что мне нужно в конце, - это всего лишь одно среднее, поэтому мне нужно найти способ поместить все данные в один вектор, а затем вычислить среднее из этого. –

ответ

0

Вы не зацикливаете файлы.

И вы получаете среднее значение для последнего файла, потому что, когда вы перебираете идентификаторы для создания имен, ваш цикл возвращает созданную фамилию.

Вам следует создать вектор имен, затем станции и перебрать его!

Советы: для создания ваших имен вам не нужны петлевые и условные операторы, вы можете использовать sprintf, определяя размер строки, которую вы ожидаете (3), и что вы хотите «развернуть» строку (0)

> id <- c(1, 10, 100) 
> names <- sprintf("%03d", id) 
> names 
[1] "001" "010" "100" 

и это должно роботи:

pollutantmean <- function(directory, pollutant, id = 1:332) { 
    filepath <- "/Users/jim/Documents/Coursera/2_R_Prog/Data" 

    names <- sprintf("%03d", id) 
    files <- paste0(names, ".csv") # Or directly : files <- sprintf("%03d.csv", id) 
    station <- file.path(filepath, directory, files) 

    means <- numeric(length(station)) 

    for (i in seq_along(station)) { 
    monitor <- read.csv(station[i]) 
    if(pollutant == "nitrate") { 
     means[i] <- mean(monitor$nitrate, na.rm = T) 
    } else if(pollutant == "sulfate") { 
     means[i] <- mean(monitor$sulfate, na.rm = T) 
    } 
    } 
    return(means) 
} 

EDIT: Если вы хотите одного среднего значения, вы можете использовать код выше и ponderate каждый подразумевает под nrow, не НС. Заменить петлю на:

means <- numeric(length(station)) 
counts <- numeric(length(station)) 

for (i in seq_along(station)) { 
    monitor <- read.csv(station[i]) 
    if(pollutant == "nitrate") { 
    means[i] <- mean(monitor$nitrate, na.rm = TRUE) 
    counts[i] <- sum(!is.na(monitor$nitrate)) 
    } else if(pollutant == "sulfate") { 
    means[i] <- mean(monitor$sulfate, na.rm = TRUE) 
    counts[i] <- sum(!is.na(monitor$sulfate)) 
    } 
} 

myMean <- sum(means * counts)/sum(counts) 
return(myMean) 

Поскольку ваше первое намерение состояло в том, чтобы собрать ваши ДАННЫЕ в один вектор, вот это решение, которое создает список, в котором каждый элемент является желание «загрязнитель» переменным каждого datasframes, unlist собираются все векторы в 1, а затем мы можем вычислить среднее значение для этого вектора.

pollutantmean <- function(directory, pollutant, id = 1:332) { 
    filepath <- "/Users/jim/Documents/Coursera/2_R_Prog/Data" 

    names <- sprintf("%03d", id) 
    files <- paste0(names, ".csv") # Or directly : files <- sprintf("%03d.csv", id) 
    station <- file.path(filepath, directory, files) 

    li <- lapply(station, function(x) { 
    monitor <- read.csv(x) 
    if(pollutant == "nitrate") { 
     monitor$nitrate 
    } else if(pollutant == "sulfate") { 
     monitor$sulfate 
    } 
    }) 

    myMean <- mean(unlist(li)) 

    return(myMean) 
} 
0

Небольшая коррекция в функции второго загрязнителя Жюльена Наварры. При вычислении среднего значения он не игнорирует значения NA, которые могут повлиять на общий результат. Поэтому строка, вычисляющая среднее значение, должна быть такой.

myMean <- mean(unlist(l), na.rm=TRUE) 
Смежные вопросы