【问题标题】:Iterate import of excel files and averaging matched values by file name in R迭代导入excel文件并在R中按文件名平均匹配值
【发布时间】:2020-01-31 05:28:01
【问题描述】:

我有一个包含 630 个 excel 文件的文件夹,所有文件名都相似。每个文件代表特定地理区域特定年份一个月的气候数据。我的目标是找到一种方法来迭代这些文件的导入并找到特定变量的平均值。所有文件的标题如下:

PRISM_ppt_stable_4kmM3_201201_bil

其中“ppt”代表数据所涉及的气候变量,“2012”代表 2012 年,“01”代表 1 月份。文件夹中下一个文件的标题为:

PRISM_ppt_stable_4kmM3_201202_bil

其中“ppt”代表同一个变量,“2012”再次代表 2012 年,“02”这次代表 2 月份。这些重复每年的每个月和 7 个不同的变量。变量的标题为:

ppt, vpdmax, vpdmin, tmax, tmin, tdmean, tmean

每个 excel 文件包含 11 个变量的 >1500 个观察值,我感兴趣的是在所有匹配的 tl_2016_us 变量中找到平均 MEAN 变量。一些快速的示例数据如下所示:

tl_2016_us MEAN
14136      135.808
14158      132.435
etc.       etc.

这很棘手,因为我只想找到指定冬季(在本例中为 11 月到 3 月)的平均值。所以文件名中包含201211、201212、201301、201302和201303的所有文件都应该用tl_2016_us和对应的MEAN变量进行平均匹配。理想情况下,这个过程会重复到下一年 201311、201312、201401、201402、201403。至此,我已经使用了

list.files(path = "filepath", pattern ="*ppt*")

为 7 个变量中的每一个创建我的文件名列表。

【问题讨论】:

    标签: r import iterator


    【解决方案1】:

    我真的不明白“tl_2016_us”变量是什么意思。

    但是,您可以使用如下一些正则表达式轻松获取仅冬季月份的列表:

    library(tidyverse) 
    
    # Assuming your files are already in your working directory
    all_files <- list.files(full.names = TRUE, pattern = "*ppt*")
    winter_mos <- str_subset(files, "[01, 02, 03, 11, 12]_\\w{3}$")
    

    之后,您可以使用map() from purrr 将所有文件迭代读入数据框:

    
    library(readxl)
    
    data <- map(winter_mos, ~ read_xlsx(.x)) %>% bind_rows(.id = "id")
    
    

    之后,你应该可以选择你想要的变量,使用group_by()分组id(即每个Excel文件的id),然后summarize_all(mean)

    【讨论】:

    • 我的理解是有两个嵌套属性:(1)“变量”ppt、vpdmax等; (2) 变量的 tl_2016_us 值(无论是什么)。
    • 您的回答中有一些好东西。它比我想象的要优雅。
    【解决方案2】:

    也许像(不是很优雅):

    filetypes = c("ppt", "vpdmax", "vpdmin", "tmax", "tmin", "tdmean", "tmean")
    data_years = c(2012,2013,2014)
    
    df <- NULL
    
    for (i in 1:length(data_years)) {
      yr <- data_years[i]
      datecodes <- c(paste(yr,"11",sep=""), 
                     paste(yr,"12",sep=""),                 
                     paste(yr+1,"01",sep=""),
                     paste(yr+1,"02",sep=""),
                     paste(yr+1,"03",sep=""))
      for (j in 1:length(filetypes)) {
         filetype <- filetypes[j]
         file_prefix <- paste("PRISM",filetype,"stable_4kmM3",sep="_")
    
         for (k in 1:length(datecodes)) {           
            datecode <- datecodes[k]
            filename <- paste(file_prefix,datecode,"bil",sep="_")
            dk <- read_excel(filename)
            M <- dim(dk)[1]
            dk$RefYr <- rep(yr,M)
            dk$DataType <- rep(filetype,M)
            if (is.null(df_new)) {
              df <- dk
            } else {
              df <- rbind(df,dk) 
            }
         }
      }
    }
    

    运行后,您将拥有一个数据框,其中包含计算平均值所需的所有数据(我认为)。

    然后您可以执行以下操作:

    df_new <- NULL
    
    for (i in 1:length(data_years)) {
      yr <- data_years[i]
      di <- df[df$RefYr==yr,]
      for (j in 1:length(filetypes)) {
         filetype <- filetypes[j]
         dj <- di[di$DataType==filetype,]
         tls <- unique(dj$tl_2016_us)
         for (k in 1:length(tls)) {
           tl <- tls[k] 
           dk <- dj[dj$tl_2016_us==tl,]
           dijk <- data.frame(RefYr=yr,TL2016=tl,DataType=filetype,
                              SeasonAverage=mean(dk$MEAN))
           if (is.null(df)){
             df_new <- dijk
           } else {
             df_new <- rbind(df_new,dijk) 
           }
         }
      }
    }
    

    我确信有更优雅的方法可以做到这一点,并且上面有一些错误,因为我无法真正运行代码,但我认为你应该留下一个包含你正在寻找的数据框为。

    【讨论】:

    • 感谢@guero64,现在正在处理它。第一个代码块运行良好,除了 file_prefix &lt;- paste("PRISM_",filetype,"stable_4kmM3",sep="_") PRISM_ 后面不需要下划线。其次,df_new 在最后的 if else 语句中使用之前没有定义。
    • 哇,我很惊讶它有点工作:)。我修正了你突出显示的内容。
    • 刚刚用你的修复程序运行它。运行上面的两个代码块时,它可以正常工作。快速提醒一下,对于我个人而言,我对 2012-2018 年很感兴趣,所以我将 data_years 向量调用更改为这些数字。运行这两个代码块后,df_new 是一个包含 63651 个观察值和 4 个变量的数据框。 4 个变量是RefYr TL2016 DataType SeasonAverage。作为最后的检查,63651/1299 是 49,相当于 7 年的 7 个变量。干得好!
    • 谢谢。我很高兴它有帮助。我最近不得不处理一些类似的数据,所以它一直留在我的脑海里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-05
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    相关资源
    最近更新 更多