如何在 R 中读取具有不同列数的 CSV 文件

Posted

技术标签:

【中文标题】如何在 R 中读取具有不同列数的 CSV 文件【英文标题】:How can you read a CSV file in R with different number of columns 【发布时间】:2013-09-26 04:18:42 【问题描述】:

我有一个稀疏数据集,它的列数长度各不相同,采用 csv 格式。这是文件文本的示例。

12223, University
12227, bridge, Sky
12828, Sunset
13801, Ground
14853, Tranceamerica
14854, San Francisco
15595, shibuya, Shrine
16126, fog, San Francisco
16520, California, ocean, summer, golden gate, beach, San Francisco

当我使用时

read.csv("data.txt", header = F)

R 会将数据集解释为具有 3 列,因为大小是根据前 5 行确定的。无论如何强制 r 将数据放在更多列中?

【问题讨论】:

你知道你的数据集中的最大列数吗? 是的,最大列数已知 我的直觉是在read.table 中指定colClasses 参数(具有最大列数)并结合fill = TRUE 应该读入文件。 @BlueMagister 我也是这么想的,但是没用。 你能不能用 2 行和正确的列数创建一个虚拟的 data.frame,然后将 rbind 文本文件添加到它? 【参考方案1】:

我遇到了类似的挑战,但 Blue Magister 的回答中的 count.fields 不起作用,可能是因为字段内的逗号与 sep="," 冲突。此外,列数因文件而异。 所以我只是在read.table中定义了多余的col.names(在我的情况下100就足够了),然后我使用which(!is.na())去除多余的列。

dat <- read.table("path/to/file.csv", col.names = paste("V",1:100), fill = T, sep = ",")
dat <- dat[,which(!is.na(dat[1,]))]

【讨论】:

【参考方案2】:

试试这个,它更有活力..

readVariableWidthFile <- function(filePath)
  con <-file(filePath)
  lines<- readLines(con)
  close(con)
  slines <- strsplit(lines,",")
  colCount <- max(unlist(lapply(slines, length)))

  FileContent <- read.csv(filePath,
                        header = FALSE,
                        col.names = paste0("V",seq_len(colCount)),
                        fill = TRUE)
  return(FileContent)

【讨论】:

请为您的答案添加更多解释。您的答案在当前接受的答案中没有添加什么? 我同意这更动态,因为它允许您循环通过 csvs 而无需指定列数【参考方案3】:

?read.table 文档的深处有以下内容:

数据列的数量是通过查看前五个来确定的 输入行(如果文件少于五行,则为整个文件),或 从col.names 的长度开始,如果它被指定并且更长。这 如果fillblank.lines.skip are true 可能是错误的,所以 如有必要,请指定 col.names(如“示例”中所示)。

因此,让我们将 col.names 定义为长度 X(其中 X 是数据集中的最大字段数),并设置 fill = TRUE

dat <- textConnection("12223, University
12227, bridge, Sky
12828, Sunset
13801, Ground
14853, Tranceamerica
14854, San Francisco
15595, shibuya, Shrine
16126, fog, San Francisco
16520, California, ocean, summer, golden gate, beach, San Francisco")

read.table(dat, header = FALSE, sep = ",", 
  col.names = paste0("V",seq_len(7)), fill = TRUE)

     V1             V2             V3      V4           V5     V6             V7
1 12223     University                                                          
2 12227         bridge            Sky                                           
3 12828         Sunset                                                          
4 13801         Ground                                                          
5 14853  Tranceamerica                                                          
6 14854  San Francisco                                                          
7 15595        shibuya         Shrine                                           
8 16126            fog  San Francisco                                           
9 16520     California          ocean  summer  golden gate  beach  San Francisco

如果不知道最大字段数,可以使用漂亮的实用函数count.fields(我在read.table示例代码中找到):

count.fields(dat, sep = ',')
# [1] 2 3 2 2 2 2 3 3 7
max(count.fields(dat, sep = ','))
# [1] 7

可能有帮助的相关阅读:Only read limited number of columns in R

【讨论】:

谢谢,非常有帮助 这花了我很长时间。非常感谢!【参考方案4】:

这似乎确实有效(遵循@BlueMagister 的建议):

tt <- read.table("~/Downloads/tmp.csv", fill=TRUE, header=FALSE, 
          sep=",", colClasses=c("numeric", rep("character", 6)))
names(tt) <- paste("V", 1:7, sep="")

     V1             V2             V3      V4           V5     V6             V7
1 12223     University                                                          
2 12227         bridge            Sky                                           
3 12828         Sunset                                                          
4 13801         Ground                                                          
5 14853  Tranceamerica                                                          
6 14854  San Francisco                                                          
7 15595        shibuya         Shrine                                           
8 16126            fog  San Francisco                                           
9 16520     California          ocean  summer  golden gate  beach  San Francisco

【讨论】:

我刚刚又试了一次。如果我使用 text 参数,这将不起作用。 啊哈..这就是原因..很高兴知道这种差异!感谢您的回信。【参考方案5】:

你可以这样读取数据:

dat <- textConnection("12223, University
12227, bridge, Sky
12828, Sunset
13801, Ground
14853, Tranceamerica
14854, San Francisco
15595, shibuya, Shrine
16126, fog, San Francisco
16520, California, ocean, summer, golden gate, beach, San Francisco")

dat <- readLines(dat)
dat <- strsplit(dat, ",")

这会产生一个列表。

【讨论】:

我拥有的数据集很大。我正在寻找一种无需复制和粘贴文件内容的解决方案。我知道我可以在 ruby​​ 中打开文件并在一行中搜索最大数量的逗号并将该行移动到第一行。然后我可以在 R 中打开文件,一切都会得到解决,但我希望在 R 中有一个简单的解决方案。 好吧,显然你会使用文件连接(阅读?connection)。但我无权访问您的文件... @CompChemist 将您的文件对象 (data.txt) 替换为 dattextConnection 用于快速读取您的示例文件。 谢谢!我现在知道了。感谢您的帮助

以上是关于如何在 R 中读取具有不同列数的 CSV 文件的主要内容,如果未能解决你的问题,请参考以下文章

自动 CSV 文件生成,在 Oracle 10g 中具有不同列数的两个标题级别的标题

将具有未知列数的数据导入R?

如何使用 vim 命令或 sed/awk 命令将具有不同列数的行分隔到另一个文件中? [关闭]

Dataprep将具有不同列数的文件导入数据集

我们如何在 Spark 中使用 Dataframes(由 structtype 方法创建)合并具有不同列数的 2 个表?

如何在 R 中读取和命名不同的 CSV 文件