【问题标题】:Filtering multiple csv files while importing into data frame导入数据框时过滤多个csv文件
【发布时间】:2013-03-31 08:56:57
【问题描述】:

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

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

过滤 v3 (v3>2 & v3

   v1   v2   v3
1  c    w    4
2  v    e    5

到目前为止,我将所有 csv 中的所有数据导入到一个数据框中,然后进行过滤:

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

感谢所有建议!

【问题讨论】:

  • 为什么要在导入时过滤?您当前的解决方案是否存在速度或内存问题?如果它的速度那么问题可能是rbind。如果它是内存,那么它可能仍然是 rbind,但先过滤可能会有所帮助。
  • @Jan van der Laan - 是的,问题是内存...我快用完了,这就是为什么过滤掉不重要的东西应该是要走的路。
  • 我建议你查看sqldf 包,它应该可以帮助你。

标签: r csv import filter


【解决方案1】:

这是一种使用data.table 的方法,它允许您使用fread(即faster than read.csv)和rbindlistsuperfast 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 设置为键,然后使用二进制搜索,导入所有内容然后运行过滤也可能更快。

【讨论】:

  • 感谢您的建议,我试过了,确实更快。最后我得到了一个不同的解决方案,见上文。
  • @mnel:小错字:看起来你的“mon”应该在第 3 行读为“min”。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    如果您真的被卡住了,那么下面的解决方案可能会奏效。它使用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
    }
    

    【讨论】:

      猜你喜欢
      • 2019-09-05
      • 2021-10-14
      • 2022-07-29
      • 1970-01-01
      • 2023-01-15
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 2015-05-03
      相关资源
      最近更新 更多