R中的Read.CSV无法按预期工作

7

我被难住了。通常来说,read.csv 函数按预期工作,但是我遇到了一个行为不符合预期的问题。很可能是我的使用方法有误,但任何帮助都将不胜感激。

以下是文件的 URL:

http://nces.ed.gov/ipeds/datacenter/data/SFA0910.zip

这是我的代码,用于获取文件、解压缩并读取它:

 URL <- "http://nces.ed.gov/ipeds/datacenter/data/SFA0910.zip"
 download.file(URL, destfile="temp.zip")
 unzip("temp.zip")
 tmp <- read.table("sfa0910.csv", 
                   header=T, stringsAsFactors=F, sep=",", row.names=NULL)

这是我的问题。当我在Excel中打开csv数据时,数据看起来符合预期。但是当我将数据读入R中时,第一列实际上被命名为row.names。R会读入一行额外的数据,但是我无法确定“错误”发生的位置,导致row.names成为了一列。简单地说,数据似乎移位了。
然而,奇怪的是,在R中的最后一列似乎包含了正确的数据。
这里是前几列的几行数据:
tmp[1:5,1:7]
  row.names UNITID XSCUGRAD SCUGRAD XSCUGFFN SCUGFFN XSCUGFFP
1    100654      R     4496       R     1044       R       23
2    100663      R    10646       R     1496       R       14
3    100690      R      380       R        5       R        1
4    100706      R     6119       R      774       R       13
5    100724      R     4638       R     1209       R       26

您认为我可能做错了什么吗?


5
永远不要假定Excel正确地呈现了您的CSV文件的内容。相反,应该在文本编辑器中打开CSV文件(虽然这不一定是问题的原因,但作为一个通用原则)。 - Joshua Ulrich
请移除 row.names = NULL 参数。 - mnel
@ttmaccer - 这很奇怪,您不需要在网站上进行身份验证。我刚刚从网页尝试了一下,它自动将文件下载到我的计算机上。我正在使用Chrome浏览器。 - Btibert3
@mnel - 我也尝试过这个方法,但是它没有起作用。奇怪的是,在R中数据的最后一列似乎是正确的。我不能只是移动列名。 - Btibert3
2
我认为这指向了问题所在,但我无法在csv中找到有问题的那一行。dim(read.csv("sfa0910.csv", header = F, skip = 1))6852 452length(unlist(strsplit(readLines('sfa0910.csv',1), ',')))451 - mnel
显示剩余2条评论
4个回答

17

我的建议:当分隔文件不按预期工作时,使用count.fields()作为快速诊断工具。

首先,使用table()计算字段数:

table(count.fields("sfa0910.csv", sep = ","))
# 451  452 
#   1 6852

这告诉你除了一行外,所有行都包含452个字段。那么哪一行是异常的呢?

which(count.fields("sfa0910.csv", sep = ",") != 452)
# [1] 1

第一行是问题所在。经检查,除第一行外的所有行都以两个逗号结尾。

现在的问题是:这是什么意思?标题行中是否应有一个额外的字段被省略了?还是其他行中的2个逗号是错误添加的?如果可能的话,最好联系生成数据的人员以澄清这种不确定性。


1
+1 赞同强调 count.fields。看起来这是一种很好的处理方式的函数。 - thelatemail

5
我有一个解决方法,可能基于mnel的评论。
dat<-readLines(paste("sfa", '0910', ".csv", sep=""))
ncommas<-sapply(seq_along(dat),function(x){sum(attributes(gregexpr(',',dat[x])[[1]])$match.length)})
> head(ncommas)
[1] 450 451 451 451 451 451

第一列之后的所有列都有一个额外的分隔符,Excel 会忽略它。

for(i in seq_along(dat)[-1]){
dat[i]<-gsub('(.*),','\\1',dat[i])
}
write(dat,'temp.csv')

tmp<-read.table('temp.csv',header=T, stringsAsFactors=F, sep=",")

> tmp[1:5,1:7]
  UNITID XSCUGRAD SCUGRAD XSCUGFFN SCUGFFN XSCUGFFP SCUGFFP
1 100654        R    4496        R    1044        R      23
2 100663        R   10646        R    1496        R      14
3 100690        R     380        R       5        R       1
4 100706        R    6119        R     774        R      13
5 100724        R    4638        R    1209        R      26

故事的寓意是...听从Joshua Ulrich的建议 ;)
快速解决方法。在Excel中打开文件并保存即可。这也会删除额外的分隔符。
或者,您可以...
dat<-readLines(paste("sfa", '0910', ".csv", sep=""),n=1)
dum.names<-unlist(strsplit(dat,','))
tmp <- read.table(paste("sfa", '0910', ".csv", sep=""), 
                   header=F, stringsAsFactors=F,col.names=c(dum.names,'XXXX'),sep=",",skip=1)
tmp1<-tmp[,-dim(tmp)[2]]

好的,很棒!这正是我的问题。 - ZnArK

2

我知道你已经找到了答案,但是由于你的答案帮助我找到了解决方法,所以我也分享一下:

如果你要在R中读取一个不同行有不同列数量的文件,就像这样:

1,2,3,4,5
1,2,3,4
1,2,3

如果读入的数据缺少列,可以使用NAs来填充这些列,就像这样:

1,2,3,4,5
1,2,3,4,NA
1,2,3,NA,NA

但是! 如果最大列数的行不是第一行,就像这样:

1,2,3,4
1,2,3,4,5
1,2,3

那么它将以有点令人困惑的方式阅读:

1,2,3,4
1,2,3,4
5,NA,NA,NA
1,2,3,NA

(在你找到问题之前,可能会让人感到无法承受,但是一旦找到问题,就变得非常简单了!)

希望这可以帮助到某些人!


1
我找到的最佳答案!! - Laurence_jj

-1
如果您使用本地数据,请确保它位于正确的位置。为了确保,请将其放在您的工作目录中,并通过以下方式直接在R控制台中更改: setwd("C:/[User]/[MyFolder]")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接