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

Handling of bang bang different in expandChain and metaExpr #53

Closed
zappingseb opened this issue Jul 12, 2019 · 8 comments
Closed

Handling of bang bang different in expandChain and metaExpr #53

zappingseb opened this issue Jul 12, 2019 · 8 comments

Comments

@zappingseb
Copy link

I was trying the example shown below (uploaded here) . It produces really nice reproducible code. My trouble is that the data of the metaReactive data() gets right into my lm call instead of storing it in the variable data. This makes my app ugly.

Is there a way to handle intermediate states through variables in metaReactives? Maybe an additional argument to !!?

app.R

   # Create dataset metaReactive
  data <- metaReactive({
        iris
      })

  # Create a linear model
  model <- metaReactive2({
        validate(need(is.data.frame(data()), "Data Set could not be created"))
        metaExpr({
              lm(formula = Sepal.Length ~ Sepal.Width, data = !!data())
            })
      })

  # show model summary
  output$text1 <- metaRender(renderPrint, {
        !!model() %>% summary()
      })

code produced

data <- iris
model <- lm(formula = Sepal.Length ~ Sepal.Width, data = data)
model %>%
  summary()

Code shown in App

Call:
lm(formula = Sepal.Length ~ Sepal.Width, data = structure(list(
    Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 
    4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 
    5.1, 4.6, 5.1, 4.8, 5, 5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 
    4.9, 5, 5.5, 4.9, 4.4, 5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 
    4.6, 5.3, 5, 7, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 
    5, 5.9, 6, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 
    6.1, 6.4, 6.6, 6.8, 6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 
    6.7, 6.3, 5.6, 5.5, 5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 
    5.1, 5.7, 6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 
    6.5, 6.4, 6.8, 5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 
    7.7, 6.3, 6.7, 7.2, 6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 
    6.1, 7.7, 6.3, 6.4, 6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 
    6.3, 6.5, 6.2, 5.9), Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 
    3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3, 3, 4, 4.4, 3.9, 3.5, 
    3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3, 3.4, 3.5, 3.4, 3.2, 
    3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3, 3.4, 3.5, 2.3, 
    3.2, 3.5, 3.8, 3, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3, 
    2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2, 3, 2.2, 2.9, 2.9, 3.1, 3, 
    2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3, 2.8, 3, 2.9, 2.6, 
    2.4, 2.4, 2.7, 2.7, 3, 3.4, 3.1, 2.3, 3, 2.5, 2.6, 3, 2.6, 
    2.3, 2.7, 3, 2.9, 2.9, 2.5, 2.8, 3.3, 2.7, 3, 2.9, 3, 3, 
    2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3, 2.5, 2.8, 3.2, 3, 3.8, 2.6, 
    2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2, 2.8, 3, 2.8, 3, 2.8, 3.8, 
    2.8, 2.8, 2.6, 3, 3.4, 3.1, 3, 3.1, 3.1, 3.1, 2.7, 3.2, 3.3, 
    3, 2.5, 3, 3.4, 3), Petal.Length = c(1.4, 1.4, 1.3, 1.5, 
    1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 
    1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 
    1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 
    1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5, 
    4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7, 3.6, 
    4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3, 4.4, 4.8, 
    5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 
    4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3, 3, 4.1, 6, 5.1, 
    5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5, 
    5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9, 6.7, 4.9, 5.7, 6, 4.8, 
    4.9, 5.6, 5.8, 6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 
    5.4, 5.6, 5.1, 5.1, 5.9, 5.7, 5.2, 5, 5.2, 5.4, 5.1), Petal.Width = c(0.2, 
    0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 
    0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 
    0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 
    0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 
    0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1, 1.3, 1.4, 1, 1.5, 
    1, 1.4, 1.3, 1.4, 1.5, 1, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 
    1.4, 1.4, 1.7, 1.5, 1, 1.1, 1, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 
    1.3, 1.3, 1.2, 1.4, 1.2, 1, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 
    2.5, 1.9, 2.1, 1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2, 1.9, 
    2.1, 2, 2.4, 2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2, 2, 1.8, 2.1, 
    1.8, 1.8, 1.8, 2.1, 1.6, 1.9, 2, 2.2, 1.5, 1.4, 2.3, 2.4, 
    1.8, 1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2, 2.3, 
    1.8), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("setosa", "versicolor", 
    "virginica"), class = "factor")), class = "data.frame", row.names = c(NA, 
-150L)))

Residuals:
    Min      1Q  Median      3Q     Max 
-1.5561 -0.6333 -0.1120  0.5579  2.2226 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   6.5262     0.4789   13.63   <2e-16 ***
Sepal.Width  -0.2234     0.1551   -1.44    0.152    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.8251 on 148 degrees of freedom
Multiple R-squared:  0.01382,	Adjusted R-squared:  0.007159 
F-statistic: 2.074 on 1 and 148 DF,  p-value: 0.1519
@zappingseb
Copy link
Author

by the way, I tried:

metaExpr({
  !!lm(formula = Sepal.Length ~ Sepal.Width, data = data())
})

which works fine for the app, but not for expandChain

@cpsievert
Copy link
Collaborator

cpsievert commented Jul 12, 2019

Yea, this is an unfortunate consequence of inlining !! into 'captured' function arguments (this isn't only a problem for summary.lm() but also plot(), hist() and basically any non-tidy function that quotes arguments and displays them later)

For a minimal example of the problem, consider:

library(rlang)
m <- expr(lm(Sepal.Length ~ Sepal.Width, data = !!iris))
summary(eval(m))

The !!iris is effectively inlining it's deparsed value into the function argument, which leads to the unfortunate display (note: this is basically what's happening when lm(Sepal.Length ~ Sepal.Width, data = !!data()) is evaluated outside of meta-mode). Perhaps we'll come up with a satisfying workaround for shinymeta, but my hunch is that regardless of what we come up with, you'll have unquote outside of the function argument. In this case, you can sort of workaround around the problem already by doing something like:

metaExpr({
      y <- !!data()$Sepal.Length
      x <- !!data()$Sepal.Width
      lm(y ~ x)
 })

Curious to hear what @jcheng5 thinks about better workarounds. Maybe something we could do is recognize a pattern like this:

metaExpr({
      data <- !!data()
      lm(Sepal.Length ~ Sepal.Width, data = data)
 })

and have it produce code like:

data <- iris
model <-  lm(Sepal.Length ~ Sepal.Width, data = data)
plot(model, which = 1)
model %>%
  summary()

instead of what it does currently

data <- iris
model <- {
  data <- data
  lm(Sepal.Length ~ Sepal.Width, data = data)
}
plot(model, which = 1)
model %>%
  summary()

@jcheng5
Copy link
Member

jcheng5 commented Jul 12, 2019

Ah, didn't think about that. Carson, it'll produce code like your suggestion, no? If metaExpr is passed bindToReturn=TRUE?

@cpsievert
Copy link
Collaborator

cpsievert commented Jul 12, 2019

This is what you get with bindToReturn = TRUE

data <- iris
data <- data
model <- lm(Sepal.Length ~ Sepal.Width, data = data)
plot(model, which = 1)
model %>%
  summary()

@jcheng5
Copy link
Member

jcheng5 commented Jul 12, 2019

Oh, haha. Sorry, I missed that line.

@zappingseb
Copy link
Author

I will close the issue. For me, it is fine now :)

metaExpr(bindToReturn = TRUE, {
  data <- !!data()
  lm(formula = Sepal.Length ~ Sepal.Width, data = data)
})

does exactly what is needed. You are right on lm and plot making it impossible not to have a second assignment.

The bindToReturn option is what I was searching for 👍

@jcheng5
Copy link
Member

jcheng5 commented Jul 22, 2019

We're going to try to have a nicer fix for this...

@cpsievert
Copy link
Collaborator

Done in #59 (use ..() now instead of !!)

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

3 participants