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

时间:2013-09-20 17:24:26

标签: r csv import read.table sparse-columns

我有一个稀疏数据集,其列数以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将数据放在更多列中?

5 个答案:

答案 0 :(得分:57)

?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

答案 1 :(得分:7)

你可以读取这样的数据:

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, ",")

这会产生一个列表。

答案 2 :(得分:3)

这似乎有效(遵循@ 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

答案 3 :(得分:1)

尝试一下,它会更加动态。

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)
}

答案 4 :(得分:1)

我也面临类似的挑战,但是Blue Magister的回答中的count.fields无效,可能是因为字段内的逗号与sep=","冲突。此外,列的数量因文件而异。 因此,我只是在col.names中定义了多余的read.table(在我的情况下,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,]))]