Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

! Can't convert x <haven_labelled> to <character>. #1959

Open
avila opened this issue Jan 9, 2025 · 0 comments
Open

! Can't convert x <haven_labelled> to <character>. #1959

avila opened this issue Jan 9, 2025 · 0 comments

Comments

@avila
Copy link

avila commented Jan 9, 2025

I was facing this issue for a long time and finally found a way to reproduce it consistently. I am not sure here is the right place to submit the issue, but since vctrs is throwing the error, I think that it might good place to start.

In short, vctrs:::as.character.vctrs_vctr(y) throws conversion errors when working with labelled data, but only if dplyr (or tidyverse) is currently loaded AND haven is not loaded. If none of these packages are loaded it also works. So the question is: why loading dplyr affects how labelled data is handled?

I have a hunch that lines 43 and 42 of https://github.com/tidyverse/dplyr/blob/main/R/zzz.R might be the reason

import_vctrs <- function(name, optional = FALSE) {
  import_from(name, "vctrs", optional = optional)

reprex

The following reprex reproduces the issue. Imagine the case where you can start the analysis straight from file 2. In this case, depending on the packages loaded, the call with(df, table(y)) throws an error.

The quick solution was to always load haven and that's OK, but I think it is worth documenting this issue, because it might affect other people in different ways, as one can see here, where solutions suggested sound more like workaround than proper solutions, such as always loading haven or coercing the columns to factor beforehand.

# fi1e 1 (e.g gather data) ----
#* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(df <- tibble::tibble(
  x = 11:14,
  y = haven::labelled(
    c(1,1, 2,2),
    labels = c("yes"=1, "no"=2))
))

temp_file <- paste0(tempdir(), "/../", "temp_file.rds")
saveRDS(df, file.path(temp_file))
#* end of file 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# file 2 (analysis) ----
#* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#* restart session 
rstudioapi::restartSession(clean = TRUE)
sessionInfo()

temp_file <- paste0(tempdir(), "/../", "temp_file.rds")
df <- readRDS(temp_file)
with(df, table(y)) # WORKS

library(tidyverse)
with(df, table(y)) 
#' throws ERROR ! Can't convert `x` <haven_labelled> to <character>.
#' if {tidyverse} is loaded. 

library(dplyr)
with(df, table(y)) 
#' throws ERROR if {dplyr} is loaded (possibly other tidyverse packages as well)


haven::as_factor 
with(df, table(y)) 
#' no longer throws error if {haven::..} is called at some point or if 
#' haven is loaded onto the global environment
#* end of file 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error (backtrace)

> rlang::last_trace(drop = FALSE)
<error/vctrs_error_cast>
Error in `as.character()`:
! Can't convert `x` <haven_labelled> to <character>.
---
Backtrace:

  1. ├─base::with(df, table(y))
  2. ├─base::with.default(df, table(y))
  3. │ └─base::eval(substitute(expr), data, enclos = parent.frame())
  4. │   └─base::eval(substitute(expr), data, enclos = parent.frame())
  5. │     └─base::table(y)
  6. │       └─base::factor(a, exclude = exclude)
  7. │         ├─base::unique(as.character(y)[ind])
  8. │         ├─base::as.character(y)
  9. │         └─vctrs:::as.character.vctrs_vctr(y)
 10. │           └─vctrs::vec_cast(x, character())
 11. └─vctrs (local) `<fn>`()
 12.   └─vctrs::vec_default_cast(...)
 13.     ├─base::withRestarts(...)
 14.     │ └─base (local) withOneRestart(expr, restarts[[1L]])
 15.     │   └─base (local) doWithOneRestart(return(expr), restart)
 16.     └─vctrs::stop_incompatible_cast(...)
 17.       └─vctrs::stop_incompatible_type(...)
 18.         └─vctrs:::stop_incompatible(...)
 19.           └─vctrs:::stop_vctrs(...)
 20.             └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call)

notes

Unsure if helpful, but running sessionInfo() after running haven::as_factor (without parenthesis) shows that haven namespace is loaded but not attached. So running loadNamespace("haven") would also be a workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant