数据框中选定列中包含NA(缺失)值的行子集

128
我们从CSV文件中得到了一个数据框。数据框 DF 中包含了包含观测值的列,还有一列 (VaR2) 包含了测量被采取的日期。如果日期没有被记录,CSV文件中会包含缺失数据的值 NA
Var1  Var2 
10    2010/01/01
20    NA
30    2010/03/01
我们希望使用subset命令来定义一个新的数据框new_DF,使其仅包含具有某一列(VaR2)中“NA”值的行。在给定的示例中,只有第二行将包含在新的DF中。 该命令为:
new_DF<-subset(DF, DF$Var2=="NA") 

代码不起作用,生成的数据框没有任何行。

如果在原始CSV文件中使用NULL替换值NA,则相同的命令会产生所需的结果:

new_DF <- subset(DF, DF$Var2=="NULL")

如果在原始CSV文件中提供了字符字符串的值NA,我该如何使此方法工作?

7个回答

188

不要使用“=='NA'”来测试缺失值。改用is.na()。这样应该可以:

new_DF <- DF[rowSums(is.na(DF)) > 0,]

或者,如果你想要检查特定的列,你也可以使用

new_DF <- DF[is.na(DF$Var),]

如果您有NA字符值,请先运行以下命令

Df[Df=='NA'] <- NA

用缺失值替换它们。


2
感谢您的快速回答(这很快)!由于数据以csv格式提供,“NA”是字符值,因此您的第二个语句可能非常有用。您能否澄清一下您的第一个语句?对我来说,使用rowSums()不太清楚,因为我只会检查特定列(有很多列)。如果该特定列(在示例中将是列Var2)有一个“NA”字符字符串(我将用您的第二个语句替换它),那么我想选择整行作为新数据框的一部分。 - John
@John:已更新。重点是使用is.na,我错误地理解了您想要检查所有变量的意思。 - Joris Meys
3
这句话的意思是:应该这样写 new_DF <- DF[is.na(DF$Var),],也就是说,在 DF[ 后面多了一个括号。 - PatrickT

62

complete.cases 在一行中所有值都不是 NA 时返回 TRUE

DF[!complete.cases(DF), ]

如果一个人更喜欢基本的R,这是一个很好的选择!@user3226167 - DataSci-IOPsy

42

在R中,NA是一个特殊的值,请不要将NA值与"NA"字符串混淆。根据数据导入方式的不同,“NA”和“NULL”单元格可能属于各种类型(默认行为是将“NA”字符串转换为NA值,并保留“NULL”字符串)。

如果使用read.table()或read.csv()函数,您应该考虑使用"na.strings"参数进行数据清洗导入,并始终使用真正的R NA值。

下面是一个同时适用于“NULL”和“NA”单元格的示例:

DF <- read.csv("file.csv", na.strings=c("NA", "NULL"))
new_DF <- subset(DF, is.na(DF$Var2))

1
感谢您的回答。如果我理解正确,第一个语句将与Joris的示例中的Df [Df == 'NA'] <- NA执行相同的操作吗?那么(小)区别就在于,在您的语句中直接在开始时创建数据框(这是一种非常清晰的编程方法,因此我喜欢它)。 - John
没错。Joris建议手动将“NA”字符串替换为NA值,而我只建议使用read.table()的“na.strings”功能来实现相同的目的。 - maressyl
Joris的回答实际上是实现这一目标的“首选”方式(如果您正在脚本中编写此内容)。请参见:https://dev59.com/52kw5IYBdhLWcg3wfKhB - Jonathan
@Jonathan:这里有两个不同的想法,你提到的主题说应该在“subset”上使用“[”,但我们正在讨论read.table()中的“na.strings”参数,我的子集只是为了可视化效果。 - maressyl

26
new_data <- data %>% filter_all(any_vars(is.na(.))) 

这应该创建一个新的数据框(new_data),其中只包含缺失值。

最好跟踪那些您可能会稍后删除的值,因为它们带有一些缺失观察(NA)的列。


7

尝试更改这个:

new_DF<-dplyr::filter(DF,is.na(Var2)) 

1
你能解释一下这个为什么有效,它是做什么的吗? - csilk
new_DF <- dplyr::filter(DF, is.na(Var2)),它基本上使用了dplyr包的filter函数,并过滤掉Var2列中满足is.na条件的任何观测值,即选择所有带有NA的观测值。 - drhnis
1
在使用library(dplyr)之后,更好地表达为DF %>% filter(is.na(Var2)) - Joe

6

由于dplyrfilter_all已被取代,

用现有动词中的across() 取代了作用域动词(_if,_at,_all)。

并且在filter()中使用across()已被弃用,因此Ronak Pol的回答需要做一些小改动。要查找任何地方出现NA的所有行,我们可以使用

library(dplyr)

DF %>% 
  filter(if_any(everything(), is.na))

获取

# A tibble: 1 x 2
   Var1 Var2  
  <dbl> <date>
1    20 NA   

-1

打印所有带有NA数据的行:

tmp <- data.frame(c(1,2,3),c(4,NA,5));
tmp[round(which(is.na(tmp))/ncol(tmp)),]

如果您不喜欢答案,可以简单地对其进行投票。编辑答案以推荐标记不是适当的操作。如果有需要,请留下评论。 - Manfred Radlwimmer

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