【问题标题】:Combination of match and lapply in RR中match和lapply的组合
【发布时间】:2014-03-20 17:43:01
【问题描述】:

这是我的问题。

我有 8 * 3 个数据帧。 8 年(2005 年到 2012 年),每年我都有对应于生态学、花卉分布和位置的三个数据框。 csv 文件的名称基于相同的类型(flowerdistrib_2005.csv、ecology_2005.csv、...)

我想为每一年构建一个数据框,其中包含“flowerdistrib”文件的所有列以及“生态”和“位置”的一部分。

感谢这个脚本,我全部导入了:

listflower = list.files(path = "C:/Directory/.../", pattern = "flowerdistrib_")

for (i in listflower) {
filepath1 <- file.path("C:/Directory/.../",paste(i))
assign(i,read.csv(filepath1, sep=";", dec=",", header=TRUE))
}

生态和位置相同。

然后我想对具有某些特定列的三个文件进行每年的 vlookup。 每年的csv文件生态、位置和flowerdistrib都有一个名为“idp”的列。

我知道该怎么做一年。我使用以下脚本:

2005 示例,提取文件 location_2005.csv 中名为“xl93”的列:

flowerdistrib_2005[, "xl93"] = location_2005$"xl93"[match(flowerdistrib_2005$"idp", location_2005$"idp")]

但多年来我不知道如何继续这样做。我正在考虑将 for 循环与 lapply 函数结合使用,但由于我是 R 初学者,所以我不能很好地处理它。

我将不胜感激。

非常感谢。

PS:我不是英语母语,对于可能的误解和可能的语言错误,我深表歉意。

【问题讨论】:

    标签: r match lapply


    【解决方案1】:

    这是对您的 read.csv 过程的重新组织,但您可以使用类似下面的脚本来完成您需要做的事情。它将创建一个列表data,其中包含指定年份的所有数据框。如果输入表都具有完全相同的结构,您还可以将所有这些数据帧合并为一个。

    希望这会有所帮助,如果您复制粘贴并更新路径,不确定下面的代码是否有效,但与此非常相似的东西可能对您有用。

    # Prepare empty list
    data <- list()
    
    # Loop through all years
    for(year in 2005:2012){
    
        # Load data for this year
        flowers <- read.csv(paste('C:/Directory/.../a/flowerdistrib_', year, '.csv', sep=''), sep=";", dec=",", header=TRUE)
        ecology <- read.csv(paste('C:/Directory/.../a/ecology_', year, '.csv', sep=''), sep=";", dec=",", header=TRUE)
        location <- read.csv(paste('C:/Directory/.../a/location_', year, '.csv', sep=''), sep=";", dec=",", header=TRUE)
    
        # Merge data for this specific year, using idp as identifier    
        all <- merge(flowers, ecology, by = "idp", all = TRUE)
        all <- merge(all, location, by = "idp", all = TRUE)
    
        # Add a year column with constant year value to data
        all$year <- year
    
        # Drop unused columns
        dropnames = c('column_x', 'column_y')
        all <- all[,!(names(all) %in% dropnames)]
    
        # Or alternatively, only keep wanted columns
        keepnames = c('idp', 'year', 'column_z', 'column_v')
        all <- all[keepnames]
    
        # Append data to list
        data[[as.character(year)]] <- all
    }
    
    # At this point, data should be a list of dataframes with all data for each year
    # so this should print the summary of the data for 2007
    summary(data[['2007']])
    
    # If all years have the very same column structure,
    # you can use use rbind to combine all years into one big dataframe
    data <- do.call(rbind, data)
    
    # This would summarize the data frame with all data combined
    summary(data)
    

    【讨论】:

    • 好的,非常感谢,它运行良好。但是,我在 rbind 步骤有一个快速的问题(将所有年份合并到一个数据框中)。事实上,如果所有的 csv 文件都具有相同的结构,那么 2009 年到 2012 年的 csv 文件会有一些其他的没有的列。我想删除这些补充列来执行 rbind 步骤。它在脚本中的位置以及如何正确编写?再次感谢。
    • 很高兴它成功了!我在答案中添加了两个选项:要么创建要删除的列列表,要么指定要保留的列列表。两者都应该工作,但“保留”版本会明确保留哪些行,从而明确data 中的所有数据帧具有相同的行以及哪些行。
    • 非常感谢! “drop”版本运行良好。不幸的是,“keep”版本中的语法all[keepnames]有问题,我想不通。
    • 好吧,如果“drop”有效,那么问题似乎就解决了。如果是这样,您能否将此答案标记为已接受?
    【解决方案2】:

    这是一个使用一些函数式编程概念的较短版本。首先,我们编写一个函数read_and_merge,它接受年份作为参数,构造一个年份文件列表,将它们读入data_,这是一个由三个文件组成的列表。最后一个技巧是使用 Reduce 函数递归合并三个数据帧。我假设唯一的公共列是idp

    read_and_merge <- function(year, mydir = "C:/Directory/.../a/"){
      files_ = list.files(mydir, pattern = paste("*_", year, ".csv"))
      data_ = lapply(files_, read.csv, sep = ";", dec = ",", header = TRUE)
      Reduce('merge', data_)
    }
    

    第二步是创建年份列表,并使用lapply为每一年创建数据集。

    mydata = lapply(2005:2012, read_and_merge)
    

    【讨论】:

    • 非常感谢您的回答。它似乎非常有效,但我在正确应用它时遇到了一些问题。所以,当我这样做时: read_and_merge
    • (抱歉前面的帖子空间不够),R 说:[[1]] NULL ... [[8]] NULL。我确认唯一常见的 cloumn 是 idp。
    • 那么mydata 是否包含您要查找的输出?
    • 不,mydata 包含 8 个 NULL 值。注意:我使用的脚本read_and_merge &lt;- function(year, mydir = "C:/Dir/.../"){ flower_ = list.files(mydir, pattern = paste("flower_", year, ".csv")) ecology_ = list.files(mydir, pattern = paste("ecology_", year, ".csv")) location_ = list.files(mydir, pattern = paste("location_", year, ".csv")) data_ = lapply(c(flower_, ecology_, location_), read.csv, sep = ";", dec = ",", header = TRUE) Reduce('merge', data_) } mydata = lapply(2005:2012, read_and_merge)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    • 2016-09-29
    • 2018-08-25
    • 1970-01-01
    相关资源
    最近更新 更多