导入数据框时过滤多个csv文件

时间:2013-04-09 04:27:04

标签: r csv import filter

我有大量的csv文件要读入R.所有csvs中的列标题都是相同的。但我想只将每个文件中的那些行导入到变量在给定范围内的数据帧(高于最小阈值和低于最大阈值),例如

   v1   v2   v3
1  x    q    2
2  c    w    4
3  v    e    5
4  b    r    7

过滤v3(v3> 2& v3< 7)应导致:

   v1   v2   v3
1  c    w    4
2  v    e    5

因此,我将所有csvs中的所有数据导入一个数据帧,然后进行过滤:

#Read the data files
fileNames <- list.files(path = workDir)
mergedFiles <- do.call("rbind", sapply(fileNames, read.csv, simplify = FALSE))
fileID <- row.names(mergedFiles)
fileID <- gsub(".csv.*", "", fileID)
#Combining data with file IDs
combFiles=cbind(fileID, mergedFiles)
#Filtering the data according to criteria
resultFile <- combFiles[combFiles$v3 > min & combFiles$v3 < max, ]

我宁愿在将每个单个csv文件导入数据框时应用过滤器。我假设for循环是最好的方法,但我不知道如何。 我很感激任何建议。

Edit

在测试了mnel的建议后,我找到了一个不同的解决方案:

fileNames = list.files(path = workDir)
mzList = list()
for(i in 1:length(fileNames)){
tempData = read.csv(fileNames[i])
mz.idx = which(tempData[ ,1] > minMZ & tempData[ ,1] < maxMZ)
mz1 = tempData[mz.idx, ]
mzList[[i]] = data.frame(mz1, filename = rep(fileNames[i], length(mz.idx)))
}
resultFile = do.call("rbind", mzList)

感谢所有的建议!

3 个答案:

答案 0 :(得分:3)

以下是一种使用data.table的方法,您可以使用freadfaster than read.csv}和rbindlist这是superfast implementation of do.call(rbind, list(..))的完美之处情况。它还有一个函数between

library(data.table)
fileNames <- list.files(path = workDir)
alldata <- rbindlist(lapply(fileNames, function(x,mon,max) {
  xx <- fread(x, sep = ',')
  xx[, fileID :=   gsub(".csv.*", "", x)]
  xx[between(v3, lower=min, upper = max, incbounds = FALSE)]
  }, min = 2, max = 3))

如果单个文件很大并且v1总是整数值,那么可能值得设置v3作为密钥然后使用二进制搜索,导入所有内容然后运行过滤也可能更快。

答案 1 :(得分:2)

如果您想在导入数据之前进行“过滤”,请尝试使用sqldf package中的read.csv.sql

答案 2 :(得分:0)

如果你真的被内存困住,那么以下解决方案可能会有效。它使用LaF来只读取过滤所需的列;然后计算将要读取的总行数;初始化完整的data.frame,然后从文件中读取所需的行。 (它可能不会比其他解决方案更快)

library("LaF")

colnames <- c("v1","v2","v3")
colclasses <- c("character", "character", "numeric")

fileNames <- list.files(pattern = "*.csv")

# First determine which lines to read from each file and the total number of lines
# to be read
lines <- list()
for (fn in fileNames) {
  laf <- laf_open_csv(fn, column_types=colclasses, column_names=colnames, skip=1)
  d   <- laf$v3[] 
  lines[[fn]] <- which(d > 2 & d < 7)
}
nlines <- sum(sapply(lines, length))

# Initialize data.frame
df <- as.data.frame(lapply(colclasses, do.call, list(nlines)), 
        stringsAsFactors=FALSE)
names(df) <- colnames

# Read the lines from the files
i <- 0
for (fn in names(lines)) {
  laf <- laf_open_csv(fn, column_types=colclasses, column_names=colnames, skip=1)
  n   <- length(lines[[fn]])
  df[seq_len(n) + i, ] <- laf[lines[[fn]], ]
  i   <- i + n
}