如何使用'sapply'或'lapply'来计算n csv文件中的行数?

时间:2014-01-20 20:27:22

标签: r loops lapply sapply

我需要编写一个带有两个参数的函数:directoryiddirectory本质上是直接使用R. id是文件的名称。所有文件的扩展名为csv,名称介于001到332之间。

该函数应返回包含两列的数据框:idnrowid是文件的名称,nrow是该文件中的行数。

我从以下代码开始,但这仅适用于只有1 id传递给函数的情况:

directory = 'specdata'
id = 1 # this should be able to take a list of numbers i.e. 1:332
id1 = if(nchar(id) == 1) {paste("00",id,sep="")}
      else if (nchar()== 2) {paste("0",id,sep="")})
file = paste(directory,"/",as.character(id1),".csv", sep="")
data = read.csv(file)
casenum = nrow(data)
output = c(id1, casenum)

如何修改代码,以便在传递超过1 id时函数可以重复。例如,行id = c(1,2,3,5,6)正在通过? 我正在考虑使用lapplysapply,但不知道从哪里开始。 谢谢,

2 个答案:

答案 0 :(得分:4)

  • 如果您只想拥有每个文件中的行数,那么我实际上建议您使用命令行工具wc:它会更快。
    wc -l *.csv将为您提供一个ASCII表,其中包含第一列中的行数和其后的文件名 (GNU core utilities用于Windows命令行的wc可用,例如{{3}}的一部分。)

  • 如果要为目录中的每个 .csv文件执行某些操作,请使用
    file = Sys.glob (paste0 (directory, "/*.csv")

无论如何,这是你要求更具体的内容:

directory = 'specdata'
id = 1:17

file = sprintf ("%s/%03i.csv", directory, id) # now a vector with file names

casenum = sapply (file, function (f) nrow (read.csv (f)))

cbind (id, casenum) 

# or, if you prefer a data.frame

data.frame (id = id, casenum = casenum)

答案 1 :(得分:2)

虽然没有必要,但如果在命名函数中包装操作,则更容易阅读。这可以在另一个功能中:

countall <- function(directory, ids) {
  countlines <- function(id) {
    ## Your code, copied from the question
    id1 = if(nchar(id) == 1) {paste("00",id,sep="")}
      else if (nchar(id)== 2) {paste("0",id,sep="")}
    file = paste(directory,"/",as.character(id1),".csv", sep="")
    data = read.csv(file)
    casenum = nrow(data)
    ## No need to attach the id here, as you can use the names
    return(casenum)
  }

  retval <- lapply(ids, countlines)  # or sapply, to return a vector instead of a list
  names(retval) <- ids

  return(retval)
}

使用以下命令运行:

countall('specdata', 1:10)