Conflict between DT::datatable and haven_labelled
bjcarothers opened this issue · 3 comments
There seems to be a conflict between DT::datatable
and haven_labelled
data types that might be caused by recent versions of htmltools
.
This works fine:
library(dplyr)
library(DT)
library(labelled)
testDf <- tibble(a=c("one","two"),
b=c(1,2))
datatable(testDf)
This does not:
test2Df <- testDf %>%
set_value_labels(b = c("First"=1, "Second"=2))
datatable(test2Df)
Yielding the following error:
Error: C stack usage 15923728 is too close to the limit
Running the following versions:
- R version 4.3.1 (2023-06-16 ucrt)
- Platform: x86_64-w64-mingw32/x64 (64-bit)
- Running under: Windows 10 x64 (build 19044)
- labelled_2.12.0 DT_0.29 dplyr_1.1.2
C stack errors are generally the result of deep recursive functions, which a 2x2 table is not. I've used DT
to display dataframes with haven_labelled
data types in the past, so this is a recent bug. I posted the issue at https://stackoverflow.com/questions/77026027/conflict-between-dtdatatable-and-haven-labelled and it did not replicate with htmltools_0.5.3
but does replicate with htmltools_0.5.6
. Ritchie Sacramento's theory is that "it's an issue with htmltools
when it tries to print the DT object - it gets stuck in a loop checking for tags and trying to add tags..."
Thanks for the report @bjcarothers. I'm not sure how much htmltools
(or even DT
) has to do with this bug. Calling traceback()
after hitting the C stack usage error shows me that R gets stuck recursively calling jsonlite::toJSON()
while trying to turn the data frame with a labelled column into JSON.
Here's an almost minimal reprex:
df_labelled <-
dplyr::tibble(a = c("one", "two"), b = c(1, 2)) |>
labelled::set_value_labels(b = c("First" = 1, "Second" = 2))
jsonlite::toJSON(df_labelled)
#> Error: C stack usage 7954232 is too close to the limit
Since the label attributes aren't useful to what's shown in the datatable, I'd recommend casting labelled columns to characters or factors before creating the datatable:
library(dplyr)
df_labelled <-
dplyr::tibble(a = c("one", "two"), b = c(1, 2)) |>
labelled::set_value_labels(b = c("First" = 1, "Second" = 2))
df_labelled |>
mutate(across(where(labelled::is.labelled), labelled::to_factor)) |>
DT::datatable()
It turns out that simply trying to jsonify a labelled vector enters the infinite recursion loop. I opened an issue with jsonlite: jeroen/jsonlite#424
labelled::labelled(1:3) |> jsonlite::toJSON()
#> Error: C stack usage 7955752 is too close to the limit
Stumbled across this issue and found that jsonify::to_json()
works in this instance
labelled::labelled(1:3) |> jsonify::to_json()
[1,2,3]
(if it's any help)