R, создание переменных на лету в списке с помощью оператора assign

Я хочу создавать имена переменных на лету внутри списка и присваивать им значения в R, но я не могу получить желаемый результат. Вот логика моего кода:

После вызова функции: dat_in <- readf(1,2)входной файл читается на основе продукта и сайта. После прочтения конкретный столбец (13-й здесь) назначается переменной aot500, Я хочу, чтобы эта переменная возвращалась из функции для каждой комбинации продукта и сайта. Например, мне нужно имя переменной в списке оператора как aot500.AF, aot500.CM, aot500.RB должен быть возвращен из этой функции. У меня проблемы с return заявление. Там нет ошибки, но нет ничего в dat_in, Я ожидаю, что это dat_in$aot500.AF и т.д. Пожалуйста, сообщите, что не так в return заявление. Кроме того, я хочу прочитать файлы для всех комбинаций за один вызов функции, скажем, с помощью цикла for, и мне интересно, как оператор return будет обрабатывать список других переменных.

prod <- c('inv','tot')
site <- c('AF','CM','RB')
readf <- function(pp, kk) {
            fname.dsa <- paste("../data/site_data_",prod[pp],"/daily_",site[kk],".dat",sep="")
            inp.aod <- read.csv(fname.dsa,skip=4,sep=",",stringsAsFactors=F,na.strings="N/A")
            aot500 <- inp.aod[,13]
            return(list(assign(paste("aot500",siteabbr[kk],sep="."),aot500)))
         }

2 ответа

Почти всегда нет необходимости использовать assign(), мы можем решить проблему в два этапа, прочитать файлы в список, а затем дать имена.

(Не проверено, так как у нас нет ваших файлов)

prod <- c('inv', 'tot')
site <- c('AF', 'CM', 'RB')

# get combo of site and prod
prod_site <- expand.grid(prod, site)
colnames(prod_site) <- c("prod", "site")

# Step 1: read the files into a list
res <- lapply(1:nrow(prod_site), function(i){
  fname.dsa <- paste0("../data/site_data_",
                      prod_site[i, "prod"],
                      "/daily_",
                      prod_site[i, "site"],
                      ".dat")
  inp.aod <- read.csv(fname.dsa, 
                      skip = 4,
                      stringsAsFactors = FALSE,
                      na.strings = "N/A")
  inp.aod[, 13]
})

# Step 2: assign names to a list
names(res) <- paste("aot500", prod_site$prod, prod_site$site, sep = ".")

Я предлагаю два ответа, один на основе dplyr и один на основе R. Вам, вероятно, придется адаптировать filename в readAOT_500 функция для вашего конкретного случая.

Base R ответ

#' Function that reads AOT_500 from the given product and site file
#' @param prodsite character vector containing 2 elements
#' name of a product and name of a site
readAOT_500 <- function(prodsite, 
                        selectedcolumn = c("AOT_500"),
                        path = tempdir()){
    cat(path, prodsite)
    filename <- paste0(path, prodsite[1],
                       prodsite[2], ".csv")
    dtf <- read.csv(filename, stringsAsFactors = FALSE)
    dtf <- dtf[selectedcolumn]
    dtf$prod <- prodsite[1]
    dtf$site <- prodsite[2]
    return(dtf)
}
# Load one file for example 
readAOT_500(c("inv", "AF"))


listofsites <- list(c("inv","AF"),
                    c("tot","AF"),
                    c("inv", "CM"),
                    c( "tot", "CM"),
                    c("inv", "RB"),
                    c("tot", "RB"))
# Load all files in a list of data frames
prodsitedata <- lapply(listofsites, readAOT_500)
# Combine all data frames together
prodsitedata <- Reduce(rbind,prodsitedata)

ответ dplyr

Я использую пакеты Хэдли Уикхем для очистки данных.

library(dplyr)
library(tidyr)

daily_CM <- read.csv("~/downloads/daily_CM.dat",skip=4,sep=",",stringsAsFactors=F,na.strings="N/A")

# Generate all combinations of product and site.
prodsite <- expand.grid(prod = c('inv','tot'),
                        site = c('AF','CM','RB')) %>%
    # Group variables to use do() later on
    group_by(prod, site)

Создайте 6 поддельных файлов путем выборки из предоставленных вами данных

Вы можете пропустить этот раздел, когда у вас есть реальные данные. Я использовал различную длину выборки, чтобы количество наблюдений отличалось для каждого участка.

prodsite$samplelength <- sample(1:495,nrow(prodsite)) 
prodsite %>% 
    do(stuff = write.csv(sample_n(daily_CM,.$samplelength),
                         paste0(tempdir(),.$prod,.$site,".csv")))

Чтение многих файлов с помощью dplyr::do()

prodsitedata <- prodsite %>%
    do(read.csv(paste0(tempdir(),.$prod,.$site,".csv"),
                stringsAsFactors = FALSE))
# Select only the columns you are interested in
prodsitedata2 <- prodsitedata %>%
    select(prod, site, AOT_500)
Другие вопросы по тегам