首页 > 解决方案 > 跳过行,直到找到某个“值” - 批量 CSV 上传,行号模式不一致

问题描述

我正在尝试在 R 中批量加载和合并两打 CSV 文件。我正在向我的数据框中添加一列,以通过名为“file_name”的列中的文件名来识别每个文件。

每个文件的顶部都有许多多余的行。本来我以为是16行的一致模式。我利用 read_csv 函数中的“skiprow”命令来解决这个问题。

但是,经过仔细检查后,我发现文件之间的 16 行模式不一致。我发现唯一一致的模式是每个文件中的所有“好数据”都紧跟在“与会者详细信息”行之后

我试图找出一种方法来跳过之前的所有行,包括包含文本“与会者详细信息”的行。

到目前为止,这是我的代码:

list_of_files <- list.files(pattern='*.csv')

df <- list_of_files %>%
  setNames(nm = .) %>% 
  map_df(~read_csv(.x, col_types = cols(), col_names = FALSE), .id = "file_name") 

这是我的数据的样子: 我的数据是什么样的

这是我希望为每个文件加载的内容,同时也跳过该标题行: 在此处输入图像描述

我已经尝试重新设计/配置我在这个线程中找到的代码片段 - 不幸的是我遇到了错误并且有点卡在从这里去哪里。

跳过数据文件中的所有行,并在 R 中的循环中包含常规字符串

for (x in list.files(pattern="*.csv", recursive=TRUE)) {
   all_content <- readLines(x)
   skip = all_content[-c(1:grep("Attendee Details",all_content))]
   input <- read.table(textConnection(skip))
   df <- rbind(df, input)
}

Error in scan(file = file, what = what, sep = sep, quote = quote, dec = dec, : line 1 did not have 13 elements

任何指针?另外,我知道最好在这里发布一个可重现的示例 - 我也不太清楚如何做到这一点。

标签: rcsvstringrread.tablereadr

解决方案


1)作为指针:

  • 您是否像示例中那样初始化df了?(cbind 需要相同数量的列,您显然在这里没有)
  • 标题字符串后是否有没有数据的文件?(您可能想在执行之前排除那些cbind,所以可能先将它们读入列表)
  • 文件在标题字符串之后有不同数量的列吗?(与以前相同的想法,排除那些或使用fill = TRUE

这是一个可能的解决方案data.table,它也说明了一个可重现的示例(但显然可能不考虑您的文件的细节):

library(data.table)

makeHeader <- function(x){
    fn <- paste0("myfile_", sprintf("%02d", x), ".csv")
    cat("Attendee report\n", file=fn, append = FALSE)
    cat("Report Generated,01/01/2020\n", file=fn, append = TRUE)
    cat("Topic,topic ", x, "\n", file=fn, append = TRUE)
    cat("Attendee Details\n", file=fn, append = TRUE)
}

# generate files:
set.seed(1)
bigdt <- data.table(col1 = sample(1:12, 1.2e4, replace = TRUE),
                    col2 = sample(LETTERS[1:26], 1.2e4, replace = TRUE),
                    col3 = sample(20:50, 1.2e4, replace = TRUE))
biglist <- split(bigdt, ceiling(seq_len(dim(bigdt)[1])/1e3))
rm(bigdt)
invisible(lapply(seq_along(biglist), makeHeader))
invisible(lapply(seq_along(biglist), 
    function(x) fwrite(biglist[[x]], 
        file=paste0("myfile_", sprintf("%02d", x), ".csv"), append=TRUE, col.names = TRUE)))

# read files and combine; add column for file name
files <- list.files(pattern="myfile_.*.csv")
DT <- lapply(files, function(x) fread(x, skip="Attendee Details", sep=","))
names(DT) <- files
rbindlist(DT, idcol = "file", fill=TRUE)
#>                 file col1 col2 col3
#>     1: myfile_01.csv    9    N   48
#>     2: myfile_01.csv    4    V   33
#>     3: myfile_01.csv    7    X   22
#>     4: myfile_01.csv    1    W   49
#>     5: myfile_01.csv    2    X   34
#>    ---                             
#> 11996: myfile_12.csv   10    S   29
#> 11997: myfile_12.csv    5    T   25
#> 11998: myfile_12.csv    8    B   34
#> 11999: myfile_12.csv   11    P   43
#> 12000: myfile_12.csv    1    O   37

reprex 包于 2020-05-31 创建(v0.3.0)


推荐阅读