我试图在dplyr中总结(/ mutate)每行中非NA的数量...一直给出错误答案。
像sum(FALSE + TRUE + FALSE + TRUE + TRUE)
这样的布尔值的算术确实加起来为3,所以问题出在哪里?为什么dplyr没有发现错误?
N = 9
set.seed(1234)
df <- data.frame(id=c(1,1,1,2,2,2,3,3,3), date=c('2005','2006','2007'),
Field1 = ifelse(runif(N)>.5, runif(N, 5,30), NA),
Field2 = ifelse(runif(N)>.5, runif(N, 4,22), NA),
Field3 = ifelse(runif(N)>.5, runif(N, 7,18), NA),
Field4 = ifelse(runif(N)>.5, runif(N, 9,25), NA),
Field5 = ifelse(runif(N)>.5, runif(N, 3,30), NA) )
# > df
# id date Field1 Field2 Field3 Field4 Field5
# 1 1 2005 NA NA NA NA NA
# 2 1 2006 22.33978 NA NA 12.824412 6.850614
# 3 1 2007 18.62437 NA 12.334904 NA NA
# 4 2 2005 12.06834 NA 9.683217 13.929516 8.296716
# 5 2 2006 28.08584 NA 15.420058 NA NA
# 6 2 2007 12.30790 NA 7.811579 9.826346 NA
# 7 3 2005 NA NA NA 18.033117 NA
# 8 3 2006 NA 7.259732 14.889989 NA 7.320774
# 9 3 2007 11.67052 17.674071 NA NA 27.197018
# Trying to summarize by the count of non-NAs in each row...!
df %.% regroup(list(quote(id),quote(date))) %.%
summarize(nna_count = sum(!is.na(Field1) + !is.na(Field2) + !is.na(Field3) + !is.na(Field4) + !is.na(Field5)))
# TOTALLY WRONG?!
# Source: local data frame [9 x 3]
# Groups: id
#
# id date nna_count
# 1 1 2005 0
# 2 1 2006 1
# 3 1 2007 1
# 4 2 2005 1
# 5 2 2006 1
# 6 2 2007 1
# 7 3 2005 0
# 8 3 2006 0
# 9 3 2007 0
通过使用格雷码进行调试,除了Field1之外,我看到所有!is.na()
表现得很奇怪:
mutate(na_count = sum(16*!is.na(Field1) + 8*!is.na(Field2) + 4*!is.na(Field3) + 2*!is.na(Field4) + !is.na(Field5)))
只能给出16或0
答案 0 :(得分:2)
我怀疑这与!
和+
运算符的优先级有关,与dplyr
本身几乎没有任何关系。请参阅上一篇文章:Behavior of summing is.na results
通过添加一些额外的括号,我可以使用summarise
使其工作:
df %.%
group_by(id,date) %.%
summarise(new=
(!is.na(Field1)) + (!is.na(Field2)) + (!is.na(Field3)) +
(!is.na(Field4)) + (!is.na(Field5))
) %.%
arrange(id,date)
#Source: local data frame [9 x 3]
#Groups: id
#
# id date new
#1 1 2005 0
#2 1 2006 3
#3 1 2007 2
#4 2 2005 4
#5 2 2006 2
#6 2 2007 3
#7 3 2005 1
#8 3 2006 3
#9 3 2007 3
答案 1 :(得分:1)
由于某些奇怪的原因,当我们传递一个包含多个子表达式的表达式时,dplyr行为很奇怪,每个子表达式都包含对Field [1-5]的引用。只有第一个参考似乎有效。
解决方法是将所有Field[1-5]
引用与c()
连接起来,然后执行is.na()
和sum()
向量。
但这似乎是一个dplyr错误。任何人都可以确认/否认/解释吗?
> df %.% regroup(list(quote(id),quote(date))) %.%
+ summarize(na_count = sum(!is.na(c(Field1,Field2,Field3,Field4,Field5))))
Source: local data frame [9 x 3]
Groups: id
id date na_count
1 1 2005 0
2 1 2006 3
3 1 2007 2
4 2 2005 4
5 2 2006 2
6 2 2007 3
7 3 2005 1
8 3 2006 3
9 3 2007 3