当没有非 NA 值时,summarize 不会 return 来自 max 的警告
summarise does not return warning from max when no non-NA values
当调用 max(x, na.rm = TRUE)
时没有非 NA
值,它 returns -Inf
,并带有警告。但是,在某些情况下,dplyr
中的 summarise
函数不会 return 警告:
library(magrittr)
library(dplyr)
df1 <- data.frame(a = c("a","b"), b = c(NA,NA))
df1 %>% group_by(a) %>% summarise(x = max(b, na.rm = TRUE))
# Three warnings, as expected.
df2 <- data.frame(a = c("a","b"), b = c(1,NA))
df2 %>% group_by(a) %>% summarise(x = max(b, na.rm = TRUE))
# No warning. Unexpected.
有趣的是,如果我重命名该函数,我会按预期收到警告:
# Pointer to same function.
stat <- max
df1 <- data.frame(a = c("a","b"), b = c(NA,NA))
df1 %>% group_by(a) %>% summarise(x = stat(b, na.rm = TRUE))
# Three warnings, as expected.
df2 <- data.frame(a = c("a","b"), b = c(1,NA))
df2 %>% group_by(a) %>% summarise(x = stat(b, na.rm = TRUE))
# Single warning, as expected.
其实我觉得应该是两个的警告,而不是三个,因为只有两组到summarise
。但我不确定内部警告系统是如何工作的,所以可能是预期的三个警告。
我的问题是:为什么 summarise
在特定情况下不输出警告,如果这是预期的,为什么简单重命名函数会改变这种行为?
我的sessionInfo()
:
R version 3.3.2 (2016-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.5 LTS
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] dplyr_0.5.0.9000 magrittr_1.5
loaded via a namespace (and not attached):
[1] lazyeval_0.2.0.9000 R6_2.2.0 assertthat_0.1
[4] tools_3.3.2 DBI_0.5-1 tibble_1.2
[7] Rcpp_0.12.8
虽然我使用的是dplyr
的"dev"版本,但我也在CRAN可用的版本上进行了测试,结果相同。
以下为部分诊断;证明 dplyr 以某种方式弄乱了对函数名称 max()
的引用。此外,dplyr 通常在其 args 上使用 SE(标准评估):lazyeval::lazydots(..., .follow_symbols=F))
,所以这可能会影响承诺,尽管我看不出如何:
A) group_by()
不是罪魁祸首。 df2 %>% group_by(a) %>% summarise(length(na.omit(b)))
确实证明组 b 正在将具有一个 NA 元素的向量传递给 max()
B) 当我们通过其限定名称 base::max
引用 max 时,我们会看到警告:
> df2 %>% group_by(a) %>% summarise(x = base::max(b, na.rm = TRUE))
a x
1 a 1
2 b -Inf
Warning message:
In base::max(NA_real_, na.rm = TRUE) :
no non-missing arguments to max; returning -Inf
而且我检查过没有 dplyr:::max()
,所以它不是命名空间阴影。
B2) 同样,do.call(max, ...)
给出预期的警告。
> df2 %>% group_by(a) %>% summarise(x = do.call(max, list(b, na.rm = TRUE)))
a x
1 a 1
2 b -Inf
Warning message:
In .Primitive("max")(NA_real_, na.rm = TRUE) :
no non-missing arguments to max; returning -Inf
C) 另外,请注意 dplyr 通常在其 args 上使用 SE(标准评估):lazyeval::lazydots(..., .follow_symbols=F))
,但我看不出这是怎么导致的。
C2) 我试图重新创建 group_by 的内部结果:
grouped_df(as.numeric(NA), list()), na.rm=T)
并用类似的东西重新创建承诺:
p <- lazyeval::lazy_dots( max, list( grouped_df(as.numeric(NA), list()), na.rm=T ) , .follow_symbols=F)
我无法用 .follow_symbols=T
来表达
我对标准评估几乎一无所知,所以在 http://adv-r.had.co.nz/Expressions.html#metaprogramming
继续侦查
使用的版本:dplyr 0.5.0; lazyeval 0.1.10 ;虽然 lazyeval 0.2.0 是 Hadley 的最新版本
对于 max()
,可以使用混合版本,它对分组数据框的处理速度更快,因为整个评估可以在 C++ 中执行,而无需为每个组进行 R 回调。在dplyr 0.5.0中,当满足以下所有条件时触发混合版本:
- 第一个参数指的是数据框中存在的变量
- 第二个参数是一个
logical
常量
有关详细信息,请参阅 hybrid vignette。
max()
的混合版本在某些方面与 R 实现不同:
- 没有针对空向量发出警告,静默 returning
-Inf
- 我认为情况一直如此;我们不妨在这里添加一个警告,但我怀疑 other users won't be happy about this
- 全
NA
向量将 return NA
即使 na.rm = TRUE
- 这肯定是个bug,我filed an issue
在您的示例中,c(NA, NA)
是 logical
的向量,因此 dplyr 回退到 "regular" 评估,每个组都有一个 R 回调。如果您需要原始行为,只需使用包装器或别名即可;混合评估器将回退到常规评估:
max_ <- max
data_frame(a = NA_real_) %>% summarise(a = max_(a, na.rm = TRUE))
## # A tibble: 1 × 1
## a
## <dbl>
## 1 -Inf
## Warning message:
## In max_(a, na.rm = TRUE) : no non-missing arguments to max; returning -Inf
当调用 max(x, na.rm = TRUE)
时没有非 NA
值,它 returns -Inf
,并带有警告。但是,在某些情况下,dplyr
中的 summarise
函数不会 return 警告:
library(magrittr)
library(dplyr)
df1 <- data.frame(a = c("a","b"), b = c(NA,NA))
df1 %>% group_by(a) %>% summarise(x = max(b, na.rm = TRUE))
# Three warnings, as expected.
df2 <- data.frame(a = c("a","b"), b = c(1,NA))
df2 %>% group_by(a) %>% summarise(x = max(b, na.rm = TRUE))
# No warning. Unexpected.
有趣的是,如果我重命名该函数,我会按预期收到警告:
# Pointer to same function.
stat <- max
df1 <- data.frame(a = c("a","b"), b = c(NA,NA))
df1 %>% group_by(a) %>% summarise(x = stat(b, na.rm = TRUE))
# Three warnings, as expected.
df2 <- data.frame(a = c("a","b"), b = c(1,NA))
df2 %>% group_by(a) %>% summarise(x = stat(b, na.rm = TRUE))
# Single warning, as expected.
其实我觉得应该是两个的警告,而不是三个,因为只有两组到summarise
。但我不确定内部警告系统是如何工作的,所以可能是预期的三个警告。
我的问题是:为什么 summarise
在特定情况下不输出警告,如果这是预期的,为什么简单重命名函数会改变这种行为?
我的sessionInfo()
:
R version 3.3.2 (2016-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.5 LTS
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] dplyr_0.5.0.9000 magrittr_1.5
loaded via a namespace (and not attached):
[1] lazyeval_0.2.0.9000 R6_2.2.0 assertthat_0.1
[4] tools_3.3.2 DBI_0.5-1 tibble_1.2
[7] Rcpp_0.12.8
虽然我使用的是dplyr
的"dev"版本,但我也在CRAN可用的版本上进行了测试,结果相同。
以下为部分诊断;证明 dplyr 以某种方式弄乱了对函数名称 max()
的引用。此外,dplyr 通常在其 args 上使用 SE(标准评估):lazyeval::lazydots(..., .follow_symbols=F))
,所以这可能会影响承诺,尽管我看不出如何:
A) group_by()
不是罪魁祸首。 df2 %>% group_by(a) %>% summarise(length(na.omit(b)))
确实证明组 b 正在将具有一个 NA 元素的向量传递给 max()
B) 当我们通过其限定名称 base::max
引用 max 时,我们会看到警告:
> df2 %>% group_by(a) %>% summarise(x = base::max(b, na.rm = TRUE))
a x
1 a 1
2 b -Inf
Warning message:
In base::max(NA_real_, na.rm = TRUE) :
no non-missing arguments to max; returning -Inf
而且我检查过没有 dplyr:::max()
,所以它不是命名空间阴影。
B2) 同样,do.call(max, ...)
给出预期的警告。
> df2 %>% group_by(a) %>% summarise(x = do.call(max, list(b, na.rm = TRUE)))
a x
1 a 1
2 b -Inf
Warning message:
In .Primitive("max")(NA_real_, na.rm = TRUE) :
no non-missing arguments to max; returning -Inf
C) 另外,请注意 dplyr 通常在其 args 上使用 SE(标准评估):lazyeval::lazydots(..., .follow_symbols=F))
,但我看不出这是怎么导致的。
C2) 我试图重新创建 group_by 的内部结果:
grouped_df(as.numeric(NA), list()), na.rm=T)
并用类似的东西重新创建承诺:
p <- lazyeval::lazy_dots( max, list( grouped_df(as.numeric(NA), list()), na.rm=T ) , .follow_symbols=F)
我无法用 .follow_symbols=T
我对标准评估几乎一无所知,所以在 http://adv-r.had.co.nz/Expressions.html#metaprogramming
继续侦查使用的版本:dplyr 0.5.0; lazyeval 0.1.10 ;虽然 lazyeval 0.2.0 是 Hadley 的最新版本
对于 max()
,可以使用混合版本,它对分组数据框的处理速度更快,因为整个评估可以在 C++ 中执行,而无需为每个组进行 R 回调。在dplyr 0.5.0中,当满足以下所有条件时触发混合版本:
- 第一个参数指的是数据框中存在的变量
- 第二个参数是一个
logical
常量
有关详细信息,请参阅 hybrid vignette。
max()
的混合版本在某些方面与 R 实现不同:
- 没有针对空向量发出警告,静默 returning
-Inf
- 我认为情况一直如此;我们不妨在这里添加一个警告,但我怀疑 other users won't be happy about this
- 全
NA
向量将 returnNA
即使na.rm = TRUE
- 这肯定是个bug,我filed an issue
在您的示例中,c(NA, NA)
是 logical
的向量,因此 dplyr 回退到 "regular" 评估,每个组都有一个 R 回调。如果您需要原始行为,只需使用包装器或别名即可;混合评估器将回退到常规评估:
max_ <- max
data_frame(a = NA_real_) %>% summarise(a = max_(a, na.rm = TRUE))
## # A tibble: 1 × 1
## a
## <dbl>
## 1 -Inf
## Warning message:
## In max_(a, na.rm = TRUE) : no non-missing arguments to max; returning -Inf