I am using r 3.3.3, dplyr 0.7.4, and Hmisc 4.1-1. I noticed that the order I load packages effects whether or not a dplyr::summaries function wold work or not. I understand that
UPDATE: As of haven version 2.0.0 this issue has been resolved, as the haven "labelled" class was renamed to "haven_labelled"
to avoid conflicts with Hmisc.
tl;dr: Order matters.
For a more detailed answer, let's first reproduce the error:
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
After removing elements piece by piece from the original summarise
example,
I managed to reduce reproducing the error to just these lines of code:
Hmisc::label(iris$Petal.Width) <- "Petal Width"
head(iris)
#> Error: `x` and `labels` must be same type
We can have a look at the traceback to see if we can locate a function that could be causing the error:
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)
The [.labelled
call looks suspicious. Why is it even called?
lapply(iris, class)
#> $Sepal.Length
#> [1] "numeric"
#>
#> $Sepal.Width
#> [1] "numeric"
#>
#> $Petal.Length
#> [1] "numeric"
#>
#> $Petal.Width
#> [1] "labelled" "numeric"
#>
#> $Species
#> [1] "factor"
Ah, setting a label for Petal.Width
with Hmisc::label
also added the S3 class.
We can inspect where the method is defined with 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
Indeed, both haven
and Hmisc
define the method. And since haven
is
loaded after Hmisc
, its definition is found first, and thus gets used:
getAnywhere("[.labelled")[1]
#> function (x, ...)
#> {
#> labelled(NextMethod(), attr(x, "labels"))
#> }
#> <environment: namespace:haven>
haven
expects labelled
objects to have a labels
attribute, which
Hmisc::label
doesn't create:
attr(iris$Petal.Width, "labels")
#> NULL
And that's where the error comes from.
haven
even loaded? It's not attached with library(tidyverse)
.
Turns out, that haven
is listed as an imported package in tidyverse
,
which causes it to be loaded when the package is attached (see e.g.
here). And loading a package,
among other things, registers its S3 methods: which is where the conflict
comes from.
As it is, if you want to use both Hmisc
and tidyverse
, order matters.
To address the issue further would likely require source level changes in
the packages' use of the labelled
S3 class.
Created on 2018-03-21 by the reprex package (v0.2.0).