r-在Hmisc之后加载tidyverse时的评估错误



我使用r 3.3.3、dplyr 0.7.4和Hmisc 4.1-1。我注意到我加载包的顺序会影响dplyr::summarys函数是否工作。我知道以不同的顺序加载包会屏蔽某些函数,但我使用package::function()语法来避免这个问题。确切的问题围绕着标记的变量。我知道过去有一些关于tidyverse和变量标签的问题,但似乎没有一个能解决为什么会出现这种特殊情况。

第一个有效的例子-我只加载Hmisc,然后加载dplyr,我能够总结数据-

#this works fine
library(Hmisc)
library(dplyr)
Hmisc::label(iris$Petal.Width) <- "Petal Width"
sumpct <- iris %>% 
dplyr::group_by(Species) %>% 
dplyr::summarise(med =median(Petal.Width),A40 = round(100*ecdf(Petal.Width)(.40),1),
A50 =round(100*ecdf(Petal.Width)(.50),1),
mns = mean(Petal.Width),
lowermean = mean(Petal.Width)-sd(Petal.Width),
lowermedian = median(Petal.Width) - sd(Petal.Width))

下面的第二个例子中断了。我启动了一个新的会话,并在Hmisc之后加载tidyverse,仍然使用package::function()语法,但这会引发错误:

summary_impl中的错误(.data,dots):评估错误:xlabels必须是相同的类型。

第二个例子:

###restart session 
#this example does not work
library(Hmisc)
library(tidyverse)

Hmisc::label(iris$Petal.Width) <- "Petal Width"
sumpct <- iris %>% 
dplyr::group_by(Species) %>% 
dplyr::summarise(med =median(Petal.Width),A40 = round(100*ecdf(Petal.Width)(.40),1),
A50 =round(100*ecdf(Petal.Width)(.50),1),
mns = mean(Petal.Width),
lowermean = mean(Petal.Width)-sd(Petal.Width),
lowermedian = median(Petal.Width) - sd(Petal.Width))

然而,第三个例子确实有效,我只需重新启动会话并在Hmisc 之前加载tidyverse

第三个例子:

###switch order of loading packages and this works
library(tidyverse)
library(Hmisc)

Hmisc::label(iris$Petal.Width) <- "Petal Width"
sumpct <- iris %>% 
dplyr::group_by(Species) %>% 
dplyr::summarise(med =median(Petal.Width),A40 = round(100*ecdf(Petal.Width)(.40),1),
A50 =round(100*ecdf(Petal.Width)(.50),1),
mns = mean(Petal.Width),
lowermean = mean(Petal.Width)-sd(Petal.Width),
lowermedian = median(Petal.Width) - sd(Petal.Width)) 

所以我的问题是,当我使用package::function()语法时,为什么我加载包的顺序很重要,特别是对于标记的变量和tidyverse?

更新:以下错误的会话信息:

sessionInfo()

R 3.3.3版(2017-03-06)运行环境:Windows 7 x64附加的基本包:[1]统计图形grDevices utils数据集方法基本

其他附加包:[1]bindrcpp_0.2 forcats_03.0
stringr_1.3.0 dplyr_07.4[5]purrr_0.2.4 readr_1.1.1
tidyr_08.0 tibble_1.4.2[9]tidyverse_2.1 Hmisc_4.1-1
ggplot2_2.2.1 Formula_1.2-2[13]survival_2.41-3 lattice_.20-35

通过命名空间加载(未附加):[1]reshape2_1.4.3
splines_3.3.3 haven_1.1.1[4]colorspace_1.3-2
htmltools_0.3.6 base64enc_0.1-3[7]rlang_0.2.0
pilla_1.2.1 foreign_0.8-69[10]glue_1.2.0
RColorBrewer_1.1-2 readxl_1.0.0[13]modelr_0.1.1
ply_1.8.4 bindr_0.1.1[16]cellranger_1.1.0
1munsell_04.3gtable_0.2.0[19]服务器_0.3.2
htmlwidgets_1.0心理_1.7.8[22]网格附加_0.6-28针织品_1.20平行_3.3.3[25]htmlTable_1.11.2
扫帚_0.4.3 Rpp_0.12.16[28]acepack_1.4.1
比例尺-0.5.0后门_1.1.2[31]检查材料_1.8.5
jsonlite_1.5网格附加_2.3[34]mnormt_1.5-5
hms_04.2摘要_0.6.15[37]字符串_1.1.7
网格3.3.3 cli_1.0.0[40]工具_3.3.3
magrittr_1.5lazyeval_0.2.1[43]cluster_2.0.6
crayon_1.3.4 pkgconfig_2.0.1[46]Matrix_1.2-12
xml2_1.2.0数据表_1.10.4-3[49]lubridate_1.7.3
断言_0.2.0 httr_1.3.1[52]rstudioapi_0.7
R6_2.2.2 rpart_4.1-13[55]nnet_7.3-12
nlme_3.1-131.1

更新:haven2.0.0版本起,此问题已得到解决,因为haven"labeled"类已重命名为"haven_labelled",以避免与Hmisc发生冲突。


tl;dr:订单很重要。

要获得更详细的答案,让我们首先重现错误:

library(Hmisc)
#> Loading required package: lattice
#> Loading required package: survival
#> Loading required package: Formula
#> Loading required package: ggplot2
#> 
#> Attaching package: 'Hmisc'
#> The following objects are masked from 'package:base':
#> 
#>     format.pval, units
library(tidyverse)
#> Warning: package 'forcats' was built under R version 3.4.4

在从原始CCD_ 4示例中逐个地去除元素之后,我设法将复制错误减少到只有以下几行代码:

Hmisc::label(iris$Petal.Width) <- "Petal Width"
head(iris)
#> Error: `x` and `labels` must be same type

我们可以查看回溯,看看是否可以找到可能导致错误的函数:

traceback()
#> 8: stop("`x` and `labels` must be same type", call. = FALSE)
#> 7: labelled(NextMethod(), attr(x, "labels"))
#> 6: `[.labelled`(xj, i)
#> 5: xj[i]
#> 4: `[.data.frame`(x, seq_len(n), , drop = FALSE)
#> 3: x[seq_len(n), , drop = FALSE]
#> 2: head.data.frame(iris)
#> 1: head(iris)

[.labelled呼叫看起来可疑。为什么叫它?

lapply(iris, class)
#> $Sepal.Length
#> [1] "numeric"
#> 
#> $Sepal.Width
#> [1] "numeric"
#> 
#> $Petal.Length
#> [1] "numeric"
#> 
#> $Petal.Width
#> [1] "labelled" "numeric" 
#> 
#> $Species
#> [1] "factor"

啊,用Hmisc::labelPetal.Width设置标签也添加了S3类。我们可以用getAnywhere:检查方法的定义

getAnywhere("[.labelled")
#> 2 differing objects matching '[.labelled' were found
#> in the following places
#>   registered S3 method for [ from namespace haven
#>   namespace:Hmisc
#>   namespace:haven
#> Use [] to view one of them

实际上,havenHmisc都定义了该方法。并且由于haven是在Hmisc之后加载,它的定义首先被找到,因此被使用:

getAnywhere("[.labelled")[1]
#> function (x, ...) 
#> {
#>     labelled(NextMethod(), attr(x, "labels"))
#> }
#> <environment: namespace:haven>

haven期望labelled对象具有labels属性Hmisc::label未创建:

attr(iris$Petal.Width, "labels")
#> NULL

这就是错误的来源。


但请稍候:为什么haven已加载?它没有附带library(tidyverse)。结果发现CCD_ 19在CCD_,这导致它在包裹被连接时被装载(参见例如。此处)。并且装载一个包裹,除其他外,注册其S3方法:这就是冲突所在来自。

实际上,如果您想同时使用Hmisctidyverse,那么顺序很重要。为了进一步解决这个问题,可能需要在包对CCD_ 23 S3类的使用。

创建于2018-03-21由reprex包(v0.2.0)。

最新更新