R中奇怪的NA行为

时间:2013-12-21 12:08:03

标签: r

在R中合并数据帧时,我注意到了一些奇怪的行为。

合并时,我在合并的数据帧中获得额外的NA行。如果显示数据框并且不影响length()的输出,则不会出现,但在编制索引时会变得明显。有一种解决方法,但并不是特别令人满意。我根本不会有这种奇怪的行为。

使用plyr包中的join()会发生这种情况,并且在使用RODBC连接sql查询中的表时也可能发生这种情况。它也可能与其他软件包一起发生。

任何人都可以解释这里发生了什么,以及如何避免它?我在winXP和win8,R版本3.0.1中使用RStudio。

> library(plyr)
> # example adapted from http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
> 
> a <- as.data.frame(cbind(seq(1, 4, 1), c("Pirate", "Monkey", "Ninja", "Spaghetti")), stringsAsFactors = FALSE)
> names(a) <- c("a.id", "name")
> a
  a.id      name
1    1    Pirate
2    2    Monkey
3    3     Ninja
4    4 Spaghetti
> 
> b <- as.data.frame(cbind(seq(1, 5, 1), c("Pirate", "Rutabaga", "Darth Vader", "Ninja", "Ninja")), stringsAsFactors = FALSE)
> names(b) <- c("b.id", "name")
> b
  b.id        name
1    1      Pirate
2    2    Rutabaga
3    3 Darth Vader
4    4       Ninja
5    5       Ninja
> 
> z <- join(a, b, by = "name", type = "left", match = "all")
> z
  a.id      name b.id
1    1    Pirate    1
2    2    Monkey <NA>
3    3     Ninja    4
4    3     Ninja    5
5    4 Spaghetti <NA>
> z$compare <- ifelse(z$a.id==z$b.id, 1, 0)
> z # shows dataframe of 5 rows
  a.id      name b.id compare
1    1    Pirate    1       1
2    2    Monkey <NA>      NA
3    3     Ninja    4       0
4    3     Ninja    5       0
5    4 Spaghetti <NA>      NA
> z[z$compare==0 ,] # shows extra rows with row names of NA and NA.1
     a.id  name b.id compare
NA   <NA>  <NA> <NA>      NA
3       3 Ninja    4       0
4       3 Ninja    5       0
NA.1 <NA>  <NA> <NA>      NA
> 
> z <- z[!is.na(z$a.id),]
> z[z$compare==0 ,] # NA rows retained
     a.id  name b.id compare
NA   <NA>  <NA> <NA>      NA
3       3 Ninja    4       0
4       3 Ninja    5       0
NA.1 <NA>  <NA> <NA>      NA

# work around to produce expected output
> z[z$compare==0 & !is.na(z$compare) ,]
  a.id  name b.id compare
3    3 Ninja    4       0
4    3 Ninja    5       0

2 个答案:

答案 0 :(得分:2)

如果要提取compare等于0的行,则必须排除NA个案例。

查看专栏compare

z$compare
[1]  1 NA  0  0 NA

当您使用比较时,即==NA将导致NA s。 @Codoremifa也在他的回答中表明了这一点。

z$compare == 0
# [1] FALSE    NA  TRUE  TRUE    NA

您应该同时执行以下操作(a)将compare0进行比较,并将NA!is.na()排除在一起:

z$compare == 0 & !is.na(z$compare)
# [1] FALSE FALSE  TRUE  TRUE FALSE

此命令仅返回TRUEFALSE

此输出可用于子集化:

z[z$compare == 0 & !is.na(z$compare), ]
#   a.id  name b.id compare
# 3    3 Ninja    4       0
# 4    3 Ninja    5       0

关于用于索引数据帧行的NA的行为。

如果您使用NA进行索引,则所有值都将被NA替换:

z[NA, ]
#      a.id name b.id compare
# NA   <NA> <NA> <NA>      NA
# NA.1 <NA> <NA> <NA>      NA
# NA.2 <NA> <NA> <NA>      NA
# NA.3 <NA> <NA> <NA>      NA
# NA.4 <NA> <NA> <NA>      NA

(此行为是由于向量回收。该命令与z[rep(NA, nrow(z)), ]相同。)

如果您使用包含NA s的索引向量,则相应的行也将仅包含NA

例如:

z[c(TRUE, NA, FALSE, NA, TRUE), ]
#      a.id      name b.id compare
# 1       1    Pirate    1       1
# NA   <NA>      <NA> <NA>      NA
# NA.1 <NA>      <NA> <NA>      NA
# 5       4 Spaghetti <NA>      NA

正如预期的那样,此命令返回第一行和第五行,但也返回与索引向量中的NA对应的两个NA行。

答案 1 :(得分:1)

您的行子集条件返回的NA既不是TRUE也不是FALSE。 NA行指的是data.frame的第二行和第五行。

例如 -

> z$compare==0
[1] FALSE    NA  TRUE  TRUE    NA
> z[NA,]
     a.id name b.id compare
NA   <NA> <NA> <NA>      NA
NA.1 <NA> <NA> <NA>      NA
NA.2 <NA> <NA> <NA>      NA
NA.3 <NA> <NA> <NA>      NA
NA.4 <NA> <NA> <NA>      NA