循环访问CSV文件 - 为每个文件发出完成任务

时间:2017-10-06 16:37:03

标签: r loops csv

我试图遍历多个CSV文件并为每个文件完成相同的任务以节省自己的时间。首先,我跑了&list; list.files'列出文件夹中的所有文件(例如,GPS_Collar33800_13.csv,GPS_Collar33801_13.CSV等)。然后我开发了一个循环,但我正在努力研究如何构建代码的其他部分来处理每个单独的文件。我的最终目标是让24个文件在结构上看起来都一样,然后我需要将它们全部合并到一个主文件中。另一个问题是我需要为每个文件列出一个唯一的ID(为衣领ID添加列,例如33800,33801,33802等),但我不知道如何轻松地执行此操作而无需手动添加手动获取新的唯一ID(如果我知道它首先引入文件GPS_Collar33800_13.csv然后我可以使AnimalID列值= 33800并对GPS_Collar33801_13.csv执行相同的操作并添加AnimalID列值= 33801)。唯一ID基于文件名。我们欢迎所有的建议!

 ## List CSV files in folder
`files<-list.files()`

## Run a for loop to complete the same tasks for each
for (i in 1:length(files)){
## Read table
tmp<-read.table(files[i],header=FALSE,sep=" ")
## Keep certain columns
tmp1 <- tmp[c(2:5,9,10,12,13)]
#Name the remaining columns
names(tmp1) <- 
c("GMT_Date","GMT_Time","LMT_Date","LMT_Time","Latitude","Longitude","PDOP","2D_3D")
#Add column for collar ID
tmp1$AnimalID<-33800
#Cleanup dataframe by removing records with NAs
tmp1[tmp1 == "N/A"]  <- NA
tmp2<-na.omit(tmp1)

2 个答案:

答案 0 :(得分:1)

你可以尝试一下:

library(stringr)
## List CSV files in folder
files<-list.files()

big.df <- vector('list',length(files))

## Run a for loop to complete the same tasks for each
for (i in 1:length(files)){
  ## Read table
  tmp<-read.table(files[i],header=FALSE,sep=" ")
  ## Keep certain columns
  tmp1 <- tmp[c(2:5,9,10,12,13)]
  #Name the remaining columns
  names(tmp1) <- 
    c("GMT_Date","GMT_Time","LMT_Date","LMT_Time","Latitude","Longitude","PDOP","2D_3D")
  #Add column for collar ID
  tmp1$AnimalID<-str_match(files[i], 'Collar(\\d+)_')[,2]
  #Cleanup dataframe by removing records with NAs
  tmp1[tmp1 == "N/A"]  <- NA
  tmp2<-na.omit(tmp1)
  big.df[[i]] <- tmp2

}
final.df <- do.call('rbind', big.df)

它将需要stringr包并假设您的文件名都看起来像'GPS_Collar33801_13.csv'等。然后它读入每个文件,将其存储在一个大的列表中,移动到下一个文件...当它完成时,它会在名为final.df的数据框中将它们全部混合在一起。

编辑:修复了str_match参数。

答案 1 :(得分:0)

因此,在开始之前,请确保我理解问题:

  1. 对于文件夹中的每个文件,
    1. 将文件导入为数据框
    2. 删除一些列
    3. 重命名其余列
    4. 将数据框中的列设置为从文件名
    5. 获取的值
    6. 删除包含字符串&#34; N / A&#34;任何地方
  2. 然后,通过UNION方式将每个结果数据帧合并为一个数据帧(即,将列添加在一起,因为列应该相同)。
  3. 您向数据提供任何此类问题至关重要。如果您无法提供特定数据,请创建一些仍然可以解决手头问题的虚假数据。然后,提供一个操作完成后它应该是什么样子的示例。这可以减少回答您问题的人的猜测。

    所以尽管如此,让我们开始吧。

    通过假装我们有一个名为process_a_file的函数来完成任务#1的子部分,它将执行每个单独文件的步骤1-5并返回一个数据框。我可以解释一下这个功能如何运作。

    对于&#34;对于每个文件&#34;部分,您需要lapplylapply在您提供的列表的每个元素上运行给定函数,并返回函数返回的列表:

    results_list <- lapply(files, process_a_file)
    

    这将返回一个列表,其中列表的每个元素都是process_a_file返回的数据帧。然后你需要一个功能来组合它们 - 我建议bind_rows包中的dplyr

    results_df <- dplyr::bind_rows(results_list)
    

    这就是你需要做的一切!

    那么,现在,我们将process_a_file放入什么?这非常简单 - 您的代码大部分都是完成此操作,但有一些不同的方法可以做到我更喜欢:)

    process_a_file <- function(filename) {
        #???????
    }
    

    步骤1是将文件作为数据框导入。为此,我建议read_delim包中的readr - 它比默认的R方法快得多,有很好的默认值,让我们通过指定&#同时处理步骤5 34; N / A&#34;表示NA

    df <- readr::read_delim(filename, delim = " ", col_names = FALSE, na = "N/A")
    

    对于第2步,您的方式有效,但我也建议使用select中的dplyr功能:

    dplyr::select(df, 2:5,9,10,12,1)
    

    您还可以使用不带引号的名称对列进行索引,并使用-5-column_name删除列 - 您可以同时执行第3步!

    df <- dplyr::select(
      df,
      GMT_Date = 2,
      GMT_Time = 3,
      LMT_Date = 4,
      LMT_Time = 5,
      Latitude = 9,
      Longitude = 10,
      PDOP = 12,
      `2D_3D` = 13
      )
    

    你重命名列的方式也很好。顺便说一句,如果你用一个数字开始一个列名,你必须在任何地方都使用这种“反引号”语法,所以它很不方便你应该尽可能避免它。

    最后,我建议使用正则表达式从文件名中获取ID。我假设您可以编写该正则表达式,因为它实际上超出了范围 - 所以您可以使用basename(tools::file_path_sans_ext(filename)返回没有路径或扩展名的文件名,并使用stringr::str_extract来弹出ID,然后使用dplyr :: mutate

    将其添加到列中
    dplyr::mutate(df, animal_id = stringr::str_extract(basename(tools::file_path_sans_ext(filename)), "THE REGEX GOES HERE"))
    

    现在,把这一切放在一起 - 使用dplyr的管道语法%>%使其看起来很漂亮:

    process_a_file <- function(filename) {
      readr::read_delim(filename,
                        delim = " ",
                        col_names = FALSE,
                        na = "N/A") %>%
        dplyr::select(
          GMT_Date = 2,
          GMT_Time = 3,
          LMT_Date = 4,
          LMT_Time = 5,
          Latitude = 9,
          Longitude = 10,
          PDOP = 12,
          `2D_3D` = 13
        ) %>%
        dplyr::mutate(animal_id = stringr::str_extract(basename(tools::file_path_sans_ext(filename)), "THE REGEX GOES HERE"))
    }
    results_list <- lapply(files, process_a_file)
    results_df <- dplyr::bind_rows(results_list)