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

时间:2017-12-05 23:22:32

标签: r for-loop

如何根据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 个答案:

答案 0 :(得分:1)

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

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))

答案 1 :(得分: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")