【问题标题】:R, creating variables on the fly in a list using assign statementR,使用assign语句在列表中动态创建变量
【发布时间】:2016-06-22 05:19:53
【问题描述】:

我想在列表中动态创建变量名并在 R 中为它们分配值,但我无法获得所需的结果。这是我的代码的逻辑:

在函数调用时:dat_in <- readf(1,2),根据产品和站点读取输入文件。读取后,将特定列(此处为第 13 列)分配给变量aot500。对于产品和站点的每个组合,我希望从函数返回这个变量。例如,我需要列表语句中的变量名称为aot500.AFaot500.CMaot500.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)))
         }

【问题讨论】:

  • 我不太明白你在做什么,但你为什么需要assign?为什么不直接返回列表?
  • 尝试将参数 `env=.GlobalEnv` 放入函数的分配位。这应该将名为“aot500.XXXX”的对象返回到用户环境中。
  • 与其在列表中动态分配变量名称,不如使用一个函数返回完整的数据框inp.aod。然后是另一个功能,可以从那里过滤您想要的数据。提供 csv 文件的样本和所需输出的样本,以便我们帮助您设计此函数。
  • @AdamQuek 我已经尝试放置环境,但它仍然不能满足我的要求。我在下一条评论中分享了指向我的示例输入数据的链接。请帮忙!
  • @jkp 下面是如何制作reproducible example

标签: r list assign variable-names


【解决方案1】:

几乎总是不需要使用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 = ".")

【讨论】:

【解决方案2】:

我提出了两个答案,一个基于 dplyr,一个基于 base R。 您可能需要根据您的具体情况调整readAOT_500 函数中的filename

基础 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 答案

我使用 Hadley Wickham 的包来清理数据。

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)

【讨论】:

  • 谢谢!但是,没有一个库可用于 R-3.1.0,而且我不知道 '%>%' 和 'group_by'。没有一个适用于我的系统。很抱歉,但我想知道是否可以使用基本包本身来完成。
  • 你能把 R 更新到最新版本吗?然后dplyr 包应该安装没有问题。 %&gt;% 是一个链接运算符,也称为管道,您会在 dplyr vignette 中找到很好的示例解释。当然,通过使用 lapply 就像在 @zx8754 的答案中一样,使用基本 R 也可以做到这一点。
  • @jkp 我添加了一个基础 R 解决方案。
  • @Paulo Rougieux 谢谢!它有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
相关资源
最近更新 更多