首页 文章

使用for循环在多个数据帧上基于ID过滤行

提问于
浏览
0

如何根据R中名为“Camera”的另一个df中的匹配ID,从我的全局目录中过滤180个.csv文件?当我试图将我的逐个文件过滤代码(参见步骤3b)合并到for循环中时(参见步骤3a),我得到错误:

粘贴错误(“i”)$ SegmentID:$运算符对原子向量无效 .

我对循环函数很新,所以我非常感谢你的帮助!所有180个文件都有一个唯一的名称,长度不同,但具有相同的列结构和名称 . 他们看着像是:

df 'File1'             df 'Camera'
 ID  Speed  Location      ID  Time  
 1   30    4              1   10
 2   35    5              3   11
 3   40    6              5   12
 4   30    7
 5   35    8

 Filtered df 'File1'            
 ID  Speed  Location 
 1   30    4
 3   40    6
 5   35    8

这些是我的代码的一些示例:

#STEP 1: read files
filenames <- list.files(path="06-06-2017_0900-1200uur",
                        pattern="*.csv")

# STEP 2: import files
for(i in filenames){
  filepath <- file.path("06-06-2017_0900-1200uur",paste(i))
  assign(i, read.csv2(filepath, header = TRUE, skip = "1"))
}

# STEP 3a: delete rows that do not match ID in df 'Cameras'
for(i in filesnames){
    paste("i") <- paste("i")[paste("i")$ID %in% Cameras$ID,]
}

#STEP 3b: filtering one by one
    File1  <- File1[File1$ID   %in% Camera$ID,]

2 回答

  • 1

    这是一种利用列表的方法(通常是更好的方法) . 首先,在 list.files() 中使用 include.names 参数:

    fns <- list.files(
      path = "06-06-2017_0900-1200uur",
      pattern = "*.csv",
      include.names = T
      )
    

    现在您有一个文件名列表 . 接下来,将 read.csv2 应用于列表中的每个文件名:

    dat <- lapply(fns, read.csv2, header = T, skip = 1)
    

    现在您有一个数据框列表(调用 read.csv 的输出) . 最后,将 subset() 应用于每个数据框,以仅保留与ID列匹配的行:

    out <- lapply(dat, function(x) subset(x, ID %in% Camera$ID))
    
  • 0

    如果我理解了这个问题,那么输出应该是来自file1的数据框,其中所有行的ID与Camera文件中的一行匹配 .

    使用 sqldf() 包和结构化查询语言可以轻松完成此操作 .

    rawFile1 <- "ID  Speed  Location
    1   30    4  
    2   35    5  
    3   40    6  
    4   30    7  
    5   35    8  
    "
    
    rawCamera <- "      ID  Time  
    1   10    
    3   11    
    5   12    
    "
    file1 <- read.table(textConnection(rawFile1),header=TRUE)
    Camera <- read.table(textConnection(rawCamera),header=TRUE)
    
    library(sqldf)
    sqlStmt <- "select * from file1 where ID in(select ID from Camera)"
    sqldf(sqlStmt,drv="SQLite")
    

    ......和输出:

    ID Speed Location
    1  1    30        4
    2  3    40        6
    3  5    35        8
    >
    

    要将此逻辑扩展到许多csv文件,首先我们使用 list.files() 函数从存储它们的子目录中获取文件列表 . 例如,如果文件位于R工作目录的 data 子目录中,则可以使用以下函数调用 .

    theFiles <- list.files("./data/",".csv",full.names=TRUE)
    

    我们可以使用 read.table() 读取这些文件以创建 list() 数据帧 .

    theData <- lapply(theFiles,function(x) { 
                          read.table(x,header=TRUE)})
    

    要将文件合并到一个数据框中,我们执行 do.call() .

    combinedData <- do.call(rbind,theData)
    

    现在我们可以读取相机数据并使用 sqldf 仅保留与相机数据匹配的ID .

    Camera <- read.table(...,header=TRUE)
    library(sqldf)
    sqlStmt <- "select * from combinedData where ID in(select ID from Camera)"
    sqldf(sqlStmt,drv="SQLite")
    

相关问题