r - 从杂乱的 .csv 文件创建数据框列表(或其他结构)

标签 r csv

;博士——我相信这实际上是一个简单的问题,只需要详细的解释来建立上下文。传递一次文件并构建一个 data.frames 列表

我有一个凌乱的 .csv 文件,如下所示。它包含许多“垃圾”行 -- 包含很少用/感兴趣的数据的行或带有嵌入空格、制表符等的行。有值(value)的行包括:

(a) 细节
(b) 子细节
(c) DETAIL 和 Sub-Detail 行之后的“类数据框”对象。

但是,(a)、(b) 和 (c) 之间的垃圾行数量可能会有所不同,例如示例 (testing.csv)。我想返回的是 data.frame 对象的列表,例如 results 或非常相似的东西(例如,我考虑了 Detail 的结果SubDetail 被捕获为 data.frame 中的附加列):

df1 <- data.frame(Item = 1:3, Val1 = c(50, 20, 30), Val2 = c(100, 30, 50))
df2 <- data.frame(Item = 1:2, Val1 = c(20, 30), Val2 = c(30, 50))
df3 <- data.frame(Item = 1:2, Val1 = c(10, 30), Val2 = c(20, 40))
df4 <- data.frame(Item = 1:3, Val1 = c(50, 30, 70), Val2 = c(30, 40, 80))

# One possible desired result structure
results <- list(list(Detail = "01", SubDetail = "ABC", data = df1),
                list(Detail = "01", SubDetail = "XYZ", data = df2),
                list(Detail = "02", SubDetail = "ABC", data = df3),
                list(Detail = "02", SubDetail = "XYZ", data = df4))

str(results)

示例 .csv 文件 (testing.csv) 类似于以下代码段:

xxx
  
xx
DETAIL: Detail 01
Sub-Detail: ABC
x
xxxx
x
Item, Val1, Val2
1, 50, 100
2, 20, 30
3, 30, 50
x
xx
xxx
x
  
    
DETAIL: Detail 01
Sub-Detail: XYZ
x
Item, Val1, Val2
1, 20, 30
2, 30, 50
x
x
DETAIL: Detail 02
Sub-Detail: ABC
Item, Val1, Val2
1, 10, 20
2, 30, 40
xxx
xx
x
x

DETAIL: Detail 02
Sub-Detail: XYZ
Item, Val1, Val2
1, 50, 30
2, 30, 40
3, 70, 80
x
xx


假设我已经有办法识别文件中的“坏行”。这意味着,我可以像这样有效地打印这些行:

badLine <- function(line) grepl(pattern = "^$|^\\s|^\\t|^x", line)

con <- file("testing.csv", open = "r")

while (length(oneLine <- readLines(con, n = 1, warn = FALSE)) > 0) {
  if (badLine(oneLine)) next else print(oneLine)
} 

close(con)

产生:

# [1] "DETAIL: Detail 01"
# [1] "Sub-Detail: ABC"
# [1] "Item, Val1, Val2"
# [1] "1, 50, 100"
# [1] "2, 20, 30"
# [1] "3, 30, 50"
# [1] "DETAIL: Detail 01"
# [1] "Sub-Detail: XYZ"
# [1] "Item, Val1, Val2"
# [1] "1, 20, 30"
# [1] "2, 30, 50"
# [1] "DETAIL: Detail 02"
# [1] "Sub-Detail: ABC"
# [1] "Item, Val1, Val2"
# [1] "1, 10, 20"
# [1] "2, 30, 40"
# [1] "DETAIL: Detail 02"
# [1] "Sub-Detail: XYZ"
# [1] "Item, Val1, Val2"
# [1] "1, 50, 30"
# [1] "2, 30, 40"
# [1] "3, 70, 80"

如何在不再次传递文件的情况下构建results 对象(或类似对象)?

可以安全地假设可以利用以下辅助函数来识别它们各自的行:

detailLine <- function(line) grepl(pattern = "^DETAIL: ", line)
subDetailLine <- function(line) grepl(pattern = "^Sub-Detail: ", line)
dfHeaderLine <- function(line) grepl(pattern = "^Item", line)
dfLine <- function(line) grepl(pattern = "^[[:digit:]]", line)

最佳答案

最好先读入数据然后应用过滤器,而不是逐行阅读时应用它们。

#Read in data
alltext <- readLines("testing.csv")

#Apply filter to isolate headers and lines
onedf <- read.csv(text=alltext[dfHeaderLine(alltext) | dfLine(alltext)], stringsAsFactors=FALSE, header=FALSE)

#Split by header
alldfs <- split(onedf, cumsum(dfHeaderLine(onedf[,1])))

#Correct column names
alldfs <- lapply(alldfs, function(x) {names(x) <- unlist(x[1,]);x[-1,]})

#Make Detail and Subheader lists
dtl <- as.list(alltext[detailLine(alltext)])
sub <- as.list(alltext[subDetailLine(alltext)])

#Combine all lists
results <- Map(list, dtl, sub, alldfs)
# [[1]]
# [[1]][[1]]
# [1] "DETAIL: Detail 01"
# 
# [[1]][[2]]
# [1] "Sub-Detail: ABC"
# 
# [[1]][[3]]
# Item  Val1  Val2
# 2    1    50   100
# 3    2    20    30
# 4    3    30    50
# 
# 
# [[2]]
# [[2]][[1]]
# [1] "DETAIL: Detail 01"
# 
# [[2]][[2]]
# [1] "Sub-Detail: XYZ"
# 
# [[2]][[3]]
# Item  Val1  Val2
# 6    1    20    30
# 7    2    30    50

关于r - 从杂乱的 .csv 文件创建数据框列表(或其他结构),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37256888/

相关文章:

R:从Companies House API获取pdf文档

mysql - 在 osx 上的 mysql 中更改 secure-file-priv

c++ - 在字段中用逗号解析 csv

java - 使用 OpenCSV 从 CSV 中提取特定数字

r - 使用单个函数将 colsum 和 rowsum 应用于矩阵中的每个元素

r - 使用数据帧列表中数据帧的相应元素应用函数(例如平均值)

r - 尝试平衡 grid.arrange 和arrangeGrob 中图的底部。还尝试移动 Y 轴标签

r - 如何使用 R 中的 emo 包在 ggplot2 中显示表情符号?

python - 如何使用 Python 在多个实例中将 CSV 中的重复项添加到特定行的末尾?

java - 通过 JDBC 将 CSV 内容加载到 mysql 数据库中?