将read.csv中的空白字段转换为NA。

27
我有一个名为'a.txt'的制表符分隔文本文件。D列为空。
 A       B       C    D
10      20     NaN
30              40
40      30      20
20      NA      20

我希望数据框与文本文件完全一致,第二行和第二列有一个空格。不幸的是,read.csv将所有空白和NA转换为“NA”。 我想将NA和NaN读取为字符。
 b<- read.csv("a.txt",sep="\t", skip =0, header = TRUE, comment.char = "",check.names = FALSE, quote="", )

总结一下:我希望在不修改输出值的情况下复制相同的值:

  • 如果输入中有空格,则输出应为空白。
  • 如果输入中有NA或Nan,则输出也应为NA或NaN。
4个回答

38
晚些时候编辑:在编辑和扩展评论之后重新阅读此内容后,我想知道所需的内容(或至少要求的内容)是否与我下面建议的完全相反。这个请求:

不幸的是,read.csv将所有空白和NA转换为“NA”。 我想将NA和NaN读取为字符。

可能已经通过参数得到了满足:`colClasses="character",stringsAsFactors=FALSE,na.strings="."`
然后,任何包括空字符串在内的字符值都会以其本身出现。 反对这一点的是接受将空字符值(“”)转换为R `_NA_character`值的答案。
以下是带有各种结果的测试示例:
 sapply(read.csv(text='A\tB\tC\tD\na\t""\tNA\tNaN', sep='\t', na.strings=""), class )
#        A         B         C         D 
# "factor" "logical"  "factor" "numeric" 
 sapply(read.csv(text='A\tB\tC\tD\na\t""\tNA\tNaN', sep='\t', na.strings="x"), class )
#        A         B         C         D 
# "factor" "logical"  "factor" "numeric" 
 sapply(read.csv(text='A\tB\tC\tD\na\t""\tNA\tNaN', sep='\t', na.strings="x", stringsAsFactors=FALSE), class )
#          A           B           C           D 
#"character"   "logical" "character"   "numeric" 

#Almost the expressed desired result
 sapply(read.csv(text='A\tB\tC\tD\na\t""\tNA\tNaN', sep='\t', #colClasses="character", stringsAsFactors=FALSE), class )
#          A           B           C           D 
#"character" "character" "character" "character" 
#But ... still get a real R <NA>
read.csv(text='A\tB\tC\tD\na\t""\tNA\tNaN', sep='\t', colClasses="character", stringsAsFactors=FALSE)
#  A B    C   D
#1 a   <NA> NaN
#So add all three
 read.csv(text='A\tB\tC\tD\na\t""\tNA\tNaN', sep='\t', colClasses="character", stringsAsFactors=FALSE,na.strings=".")
#  A B  C   D
#1 a   NA NaN
# Finally all columns are character and no "real" R NA's

na.strings 的默认值只是 "NA",因此您可能需要添加 "NaN"。真正的空白 ("") 会被设置为缺失值,但空格 (" ") 不会:

 b<- read.csv("a.txt",  skip =0,  
               comment.char = "",check.names = FALSE, quote="",
               na.strings=c("NA","NaN", " ") )

由于您的数据示例格式不正确且没有逗号,因此不清楚这是否是问题。这可能是根本问题,因为read.csv不允许使用制表符分隔。如果您的数据使用制表符分隔,请使用read.delimread.table

b<- read.table("a.txt", sep="\t" skip =0, header = TRUE, 
               comment.char = "",check.names = FALSE, quote="",
               na.strings=c("NA","NaN", " ") )

# worked example for csv text file connection
 bt <- "A,B,C  
10,20,NaN
30,,40
40,30,20
,NA,20"

 b<- read.csv(text=bt, sep=",", 
                comment.char = "",check.names = FALSE, quote="\"",
                na.strings=c("NA","NaN", " ") )
 b
#--------------
   A  B  C
1 10 20 NA
2 30 NA 40
3 40 30 20
4 NA NA 20

示例2:

bt <- "A,B,C,D
10,20,NaN
30,,40
40,30,20
,NA,20"

 b<- read.csv(text=bt, sep=",", 
                comment.char = "",check.names = FALSE, quote="\"",
                na.strings=c("NA","NaN", " ") , colClasses=c(rep("numeric", 3), "logical")) 
 b
#----------------
   A  B  C  D
1 10 20 NA NA
2 30 NA 40 NA
3 40 30 20 NA
4 NA NA 20 NA
> str(b)
'data.frame':   4 obs. of  4 variables:
 $ A: num  10 30 40 NA
 $ B: num  20 NA 30 NA
 $ C: num  NA 40 20 20
 $ D: logi  NA NA NA NA

有趣的是,在数值向量中 NA 和 NaN 并不相同。NaN 是由没有数学意义的运算返回的(但是如在?NaN的帮助页面中所述,操作的结果可能取决于特定的操作系统)。对于 NaN 或 NA,等号测试都不适用。它们各有特定的 is 函数:

> Inf*0
[1] NaN

> is.nan(c(1,2.2,3,NaN, NA) )
[1] FALSE FALSE FALSE  TRUE FALSE
> is.na(c(1,2.2,3,NaN, NA) )
[1] FALSE FALSE FALSE  TRUE  TRUE  # note the difference

这将会把目前的NA和NaN值转换为"",我将无法取回它们。我需要保留NA、NaN和空白值。 - user1631306
我深入挖掘我的数据...列D完全为空,类别为“逻辑”。 - user1631306
某个逻辑类的东西怎么可能是完全空的?请发布您的数据。您还没有向我们展示文本文件的样子,也许您正在展示屏幕输出……这不是同一件事情。 - IRTFM
列D为空。如果您执行sapply(b,class) ..,您将得到A B C D ""integer" "integer" "numeric" logical"。 - user1631306
你还没有告诉我们你的数据文件长什么样子。如果我使用colClasses,我可以创建一个空的逻辑列。请参见上文。 - IRTFM
显示剩余4条评论

12
读取 CSV 文件后,请尝试以下操作。它将用空字符串替换 NA 值。
b[is.na(b)]<-""

相当确定那样做不能解决你的 NaN 值。这需要在另一条语句中解决。

b[is.nan(b)]<-""

2
这将把所有列转换为字符串变量。第二个则不会修复NaN,因为在使用第一个后,b的所有列都将是字符串。 - Brian Diggs
这将把当前的NA和NaN值转换为""。我将无法恢复它们。我需要保留NA、NaN和空白值。 - user1631306
不会的,它会把它们全部转换为NA。 - IRTFM

5

使用na.string参数。
na.string用于定义要从数据中读取为NA值的参数。因此,如果您提到

read.csv(text=bt, na.string = "abc")

每当您的数据中出现值“abc”时,它将转换为na。
由于在您的数据中找不到“abc”,因此不会将任何值转换为na。


2

您可以在read.csv语句中指定colClasses,将列读取为文本。


2
这不正确。colClasses 在这里没有帮助。或者更准确地说,我认为有一个更合适的参数可用。 - joran
非常神秘... stringsAsFactors=FALSE - beroe
我不理解。当OP说他/她想要将DataFrame与文本文件完全一致时,他们是否意味着我们应该得到三列,其中一个为空白,一个为“NA”,另一个为“NaN”,如问题所示? - TheComeOnMan
我同意楼主的问题有点不清楚。我的观点仅仅是,正如DWin所指出的那样,在这里na.strings参数似乎比colClasses更可能是罪魁祸首。 - joran
抱歉造成困惑。我有一个文件,其中一列为空,某些列包含 Na 和 NaN。我正在对该文件进行一些计算,并将其写入新文件,同时添加一些列。但现在空白列不再为空白,而是为 NA。我想要的是和原始文件格式完全相同的输出格式。 - user1631306
显示剩余4条评论

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