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

patchwork plots cause internal data to be dumped into chunk outputs #13470

Open
kevinushey opened this issue Aug 8, 2023 · 2 comments
Open

Comments

@kevinushey
Copy link
Contributor

System details

RStudio Edition : 2023.08.0-daily+60
RStudio Version : Desktop [Open Source]
OS Version      : macOS Ventura 13.5
R Version       : R version 4.3.1 (2023-06-16)

Steps to reproduce the problem

From thomasp85/patchwork#231.

library(ggplot2)
library(patchwork)
gg1 <- ggplot(mtcars, aes(mpg, cyl)) + 
  geom_point()

gg2 <- ggplot(mtcars, aes(hp, disp)) + 
  geom_point()

foo <- gg1 + gg2 + plot_layout(ncol = 1)

Describe the problem in detail

A data.frame is printed, which is not expected.

Screenshot 2023-08-08 at 9 37 50 AM

Describe the behavior you expected

There shouldn't be any chunk outputs after executing this code.

Session Info
Tracing print(rInfo) on entry 
[1] "hi"
R version 4.3.1 (2023-06-16)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.5

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
Tracing print(strsplit(x$locale, ";", fixed = TRUE)[[1]], quote = FALSE,  .... on entry 
[1] "hi"
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Los_Angeles
tzcode source: internal

attached base packages:
Tracing print(x$basePkgs, quote = FALSE, ...) on entry 
[1] "hi"
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
Tracing print(mkLabel(x, "otherPkgs"), quote = FALSE, ...) on entry 
[1] "hi"
[1] patchwork_1.1.2 ggplot2_3.4.2  

loaded via a namespace (and not attached):
Tracing print(mkLabel(x, "loadedOnly"), quote = FALSE, ...) on entry 
[1] "hi"
 [1] vctrs_0.6.3       cli_3.6.1         knitr_1.43        rlang_1.1.1.9000 
 [5] xfun_0.39         DBI_1.1.3         generics_0.1.3    textshaping_0.3.6
 [9] labeling_0.4.2    glue_1.6.2        colorspace_2.1-0  htmltools_0.5.5  
[13] ragg_1.2.5        scales_1.2.1      fansi_1.0.4       rmarkdown_2.23   
[17] grid_4.3.1        evaluate_0.21     munsell_0.5.0     tibble_3.2.1     
[21] fastmap_1.1.1     yaml_2.3.7        lifecycle_1.0.3   compiler_4.3.1   
[25] dplyr_1.1.2       pkgconfig_2.0.3   rstudioapi_0.15.0 farver_2.1.1     
[29] systemfonts_1.0.4 digest_0.6.33     R6_2.5.1          tidyselect_1.2.0 
[33] utf8_1.2.3        pillar_1.9.0      magrittr_2.0.3    withr_2.5.0      
[37] tools_4.3.1       gtable_0.3.3     
@kevinushey
Copy link
Contributor Author

I've taken a look, and it looks like a bug in RStudio. To explain the behavior:

  1. When executing a Notebook chunk, RStudio inserts its own print() overrides, so that it can detect and capture attempts to print R objects. This is what allows RStudio to capture e.g. data.frame print-outs in a clean way.
  2. RStudio also tries to detect changes to objects in the Environment pane as code chunks are executed. When new objects are created, or changed, we try to introspect those new objects to learn a bit more about those objects.
  3. To that end, when inspecting the foo object, we call str(foo) -- but this involves calling print() when examining some of the internal data in foo.
  4. Unfortunately, because the print() overrides in (1) are still active, we end up inadvertently capturing that output into the Notebook chunk.

I think we can fix this on the RStudio side by making sure we deactivate our print overrides when updating the Environment pane.

@kevinushey
Copy link
Contributor Author

.rs.addFunction("dataCaptureOverrides", function(outputFolder, libraryFolder)
{
defaultOverride <- function(x, options) list(x = x, options = options, className = class(x), nRow = .rs.scalar(nrow(x)), nCol = .rs.scalar(ncol(x)))
c(
"print.data.frame" = defaultOverride,
"print.tbl_df" = defaultOverride,
"print.paged_df" = defaultOverride,
"print.grouped_df" = defaultOverride,
"print.rowwise_df" = defaultOverride,
"print.tbl_sql" = defaultOverride,
"print.data.table" = function(x, options) {
shouldPrintTable <- TRUE
if ("data.table" %in% loadedNamespaces() &&
exists("shouldPrint", envir = asNamespace("data.table")))
{
shouldPrint <- get("shouldPrint", envir = asNamespace("data.table"))
shouldPrintTable <- tryCatch(
shouldPrint(x) || !inherits(x, "data.table"),
error = function(e) TRUE
)
}
if (!shouldPrintTable) {
return(NULL)
}
list(x = x, options = options, className = class(x), nRow = .rs.scalar(nrow(x)), nCol = .rs.scalar(ncol(x)))
},
"print.tbl_lazy" = function(x, options) {
tblLazyData <- lapply(dplyr::tbl_vars(x), function(e) character(0))
names(tblLazyData) <- dplyr::tbl_vars(x)
lazyFrame <- do.call("data.frame", tblLazyData)
list(
x = lazyFrame,
options = options,
className = class(x),
nRow = "?",
nCol = "?"
)
}
)
})

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

No branches or pull requests

3 participants