R 从332.csv文件中提取数据,并返回文件中每个变量的观察案例数
我正在编写一个R函数,它读取一个包含332.csv文件的目录,并报告每个数据文件中完全观察到的案例数。函数返回一个数据帧,其中第一列是文件名,第二列是完整案例数。例如:R 从332.csv文件中提取数据,并返回文件中每个变量的观察案例数,r,csv,R,Csv,我正在编写一个R函数,它读取一个包含332.csv文件的目录,并报告每个数据文件中完全观察到的案例数。函数返回一个数据帧,其中第一列是文件名,第二列是完整案例数。例如: ID OBS 1 233 2 149 etc. 以下是我编写的代码: complete <- function(directory, id = 1:332) { files_full <- list.files(directory, full.names = TRUE) nobs <
ID OBS
1 233
2 149
etc.
以下是我编写的代码:
complete <- function(directory, id = 1:332) {
files_full <- list.files(directory, full.names = TRUE)
nobs <- sum(complete.cases(files_full[id]))
data <- data.frame(id, nobs)
return(data)
}
这里的问题是,虽然函数确实在运行,但它为我的列中的每个nob提供了一个值1。sumplete.casesfiles\u full[i]没有多大意义,这可能是您出错的地方
我会这样做
1-定义一个函数来处理单个数据集
read_and_summarise <- function(f, ...) {d <- read.csv(f, ...) ; sum(complete.cases(d))}
2-将此功能应用于所有文件
lf <- list.files(directory, full.names = TRUE)
vapply(lf, read_and_summarise, 0L)
未经测试的有点不同的方法:
complete <- function(directory, pattern = "csv$") {
setNames(as.data.frame(do.call(
rbind,
lapply(
list.files(directory, pattern = pattern, full.names=TRUE),
function(fname) list(fname, sum(complete.cases(read.csv(fname))))
)
)), c("file", "complete"))
}
让我们看一下您的代码实际在做什么:
complete <- function(directory, id = 1:332) {
# list files
files_full <- list.files(directory, full.names = TRUE)
# create an empty placeholder, to grow sequentially. Known in some circles as R Inferno
# http://www.burns-stat.com/documents/books/the-r-inferno/
dat <- data.frame()
for (i in id) { # select filenames based on their position in the list
# (prone to errors, because it depends on the order)
dat <- rbind(dat, read.csv(files_full[i])) # read the data, and append it
# to previous data.frame. Why??
nobs <- sum(complete.cases(files_full[i])) # number of complete cases...
# in a character vector of length 1
data <- data.frame(id, nobs) # this gets overwritten every time
}
data
}
以下是您可能想写的内容:
complete <- function(directory, id = 1:332) {
# list files
files_full <- list.files(directory, full.names = TRUE)
files_toread <- files_full[id] # filter out unwanted files (tip: ?grep is better)
output <- data.frame(id = id, nobs = 0)
for (i in id) {
tmp <- read.csv(files_toread[i]) # read the data
nobs <- sum(complete.cases(tmp)) # number of complete cases
output[i, "nobs"] <- nobs
}
output
}
编辑:
此代码将id与文件名匹配,而不是按编号id对所有文件进行子集设置。将创建一个嵌套函数来读取和分析文件。在data.frame中,新函数列表应用于匹配文件路径的向量,在一个非列表中,仅返回完整案例的数量。这是我的解决方案,看起来更容易阅读:
complete <- function(directory,id=1:332){
filenames <- sprintf("%03d.csv", id)
filePaths <- paste(directory, filenames, sep="/")
nFiles=length(id)
output <- matrix(ncol=2, nrow=nFiles)
for(i in 1:nFiles){
output[i,]= c(id[i],sum(complete.cases(read.csv(filePaths[i]))))
}
output <- setNames(data.frame(output),c("id","nobs"))
output
}
希望这对某人有所帮助。我认为这更简单,更容易理解:
complete <- function(dir, id = 1:332){
dir <- list.files(dir, full.names = T)
count <- data.frame()
for(i in id){
ok <- sum(complete.cases(read.csv(dir[i])))
count <- rbind(count, ok)
}
count_table <- cbind(id, count)
colnames(count_table) <- c("id", "nobs")
count_table
}
在保持初始functiondirectory,id=1:332不变的情况下,有没有办法做到这一点?我想知道是否有人会建议使用lf%>%read.csv%>%complete.cases%>%sum%>%setNamesalternative@Daniel现在还不完全清楚使用id=1:332时的真正目的是什么?只选择前332个文件?但是如果您意外地在列表中有其他文件,该怎么办?在list.files之后对特定的文件名进行grep不是更好吗?@baptiste谢谢你的帮助,我真的很感激。我已经更新了代码,将dat[ID]编辑为刚才的ID。fx似乎工作正常一半:它在一个整洁的小列表中打印每个csv文件的正确ID,但它没有显示每个文件的非NA观察的正确数量。我应该如何编辑我的代码来修复此问题?@zero323非常感谢!这个函数可以工作,但我想知道是否有办法不在数据框中显示文件和文件名?我想展示一个更简单的列表。非常感谢@baptiste!是的,我确实知道我不需要重新查找文件。删除后,我在OP中更新了以下代码。您将如何修改此代码以获得所需的结果?我不完全清楚你所说的文件是什么意思?完整是长度为1的字符向量,我如何更改它以查找每个单独的CSV并提取该文件中每个列的完整案例?请以更详细的方式描述你的解决方案。1。在目录中创建文件列表。2.创建文件编号列表并将其格式设置为数字。3.从ID参数与数字列表匹配的文件列表中选择文件。4.为选定文件创建文件路径。5.创建函数以对所选文件中的完整记录求和。5.创建id为column1和column2的数据帧,作为应用于选定文件的上一个求和函数的结果。
complete <- function(directory,id=1:332){
filenames <- sprintf("%03d.csv", id)
filePaths <- paste(directory, filenames, sep="/")
nFiles=length(id)
output <- matrix(ncol=2, nrow=nFiles)
for(i in 1:nFiles){
output[i,]= c(id[i],sum(complete.cases(read.csv(filePaths[i]))))
}
output <- setNames(data.frame(output),c("id","nobs"))
output
}
complete <- function(dir, id = 1:332){
dir <- list.files(dir, full.names = T)
count <- data.frame()
for(i in id){
ok <- sum(complete.cases(read.csv(dir[i])))
count <- rbind(count, ok)
}
count_table <- cbind(id, count)
colnames(count_table) <- c("id", "nobs")
count_table
}