0

I get an error when I try to get the units attribute on a field, after I load the sf package.

Below is a reproducible example.

library(Hmisc)

fail.time <- c(10,20)
units(fail.time) <- "Day"

library(sf)
units(fail.time) <- "Day"

 Error: inherits(value, "units") || inherits(value, "symbolic_units") is not TRUE

if I specify the package and function I get the error, a different error message

Hmisc::units(fail.time) <- "Day"

Error: 'units<-' is not an exported object from 'namespace:Hmisc'

How can I get around this error

LyzandeR
  • 37,047
  • 12
  • 77
  • 87
user3357059
  • 1,122
  • 1
  • 15
  • 30

2 Answers2

3

Usually I find LyzandeR's answers to be helpful. This time not as much. The question posed an error message that was obviously not from the Hmisc::units<- function, because it did not occur with the first instance of units(fail.time) <- "Day" but rather occurred after the pkg:sf was loaded. If you look at the DESCRIPTION file for sf you find that it has Imports:units. In point of fact, then, it was units::unit<-.numeric that was throwing the initial cryptic error. If you restart R with only Hmisc (and not sf) loaded, you see that there are only two units<- methods:

> methods(`units<-`)
[1] units<-.default  units<-.difftime
see '?methods' for accessing help and source code

If you load the sf package you can now see that it is the (newly loaded) units::units<-.numeric function that is throwing the error because that package was loaded by sf and because there was not actually a pre-existing .numeric version of the function, there was a resultant "masking" (perhaps more accurately a "diversion") of the existing function's domain and there was no automatically generated warning.

> library(sf)
Linking to GEOS 3.6.1, GDAL 2.1.3, proj.4 4.9.3
> methods(`units<-`)
[1] units<-.default  units<-.difftime units<-.numeric* units<-.units*  
see '?methods' for accessing help and source code
> getAnywhere(`units<-.numeric`)
A single object matching ‘units<-.numeric’ was found
It was found in the following places
  registered S3 method for units<- from namespace units
  namespace:units
with value

function (x, value) 
{
    stopifnot(inherits(value, "units") || inherits(value, "symbolic_units"))
    if (inherits(value, "units")) 
        value <- units(value)
    attr(x, "units") = value
    class(x) <- "units"
    x
}
<environment: namespace:units>

The package's maintainer is now aware that some of us are having puzzlement:

 maintainer('sf')
[1] "Edzer Pebesma <edzer.pebesma@uni-muenster.de>"
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • Thanks for mentionin @42-. I guess it is not clear in my answer that I didn't even look at the `sf` error. My answer covers only the second error without even loading the `sf` library. If you don't load `sf` then `Hmisc::`units<-.default`(fail.time, "Day")` is actually called but I ll make sure it is clear. – LyzandeR Jan 06 '18 at 02:37
  • There is no masking: `units<-.default` is in `Hmisc`, `units<-.numeric` is in `units` (loaded by `sf`). Since `fail.time` is numeric, after loading `sf` the `units<-.numeric` method is chosen because it matches its class. – Edzer Pebesma Jan 06 '18 at 17:04
  • I (eventually) did realize that the `units.numeric` version was new and that was probably the reason for no warning. I eventually discovered that the reason for the error was the existence of a fixed set of units-values in the ud_units list that was loaded (with no real notice of such) as a side-effect of loading the `sf` package. I thought the error message should have made clear to look at `?units::ud_units` (once that help page was actually made helpful.) – IRTFM Jan 06 '18 at 17:21
2

I will cover the Error: 'units<-' is not an exported object from 'namespace:Hmisc' error below ignoring the sf one, which is covered in 42-'s anwser.

units<- is a replacement function. These are special functions that you see when the function is on the left hand side of the assingment operator like:

units(fail.time) <- "Day"

So, you wouldn't need Hmisc::units anyway. My initial guess would be that you need units<-. But that is not exported from Hmiscapparently (as you can see in your error too). What you actually need is the counter intuitive units<-.default method which is exported from Hmisc. This works:

fail.time <- c(10,20)
Hmisc::`units<-.default`(fail.time, "Day")
#[1] 10 20
#attr(,"units")
#[1] "Day"

When you use units(fail.time) <- "Day" the above is what you actually call.

Just for completion, this is what units<-.default looks like:

`units<-.default`
#function (x, value) 
#{
#    attr(x, "units") <- value
#    x
#}
#<environment: namespace:Hmisc>
LyzandeR
  • 37,047
  • 12
  • 77
  • 87