DeclareDesign / fabricatr

fabricatr: Imagine Your Data Before You Collect It
https://declaredesign.org/r/fabricatr
Other
91 stars 11 forks source link

catch error when variables in formula for reveal_outcomes do not exist #181

Closed graemeblair closed 2 years ago

graemeblair commented 3 years ago

Currently:

> library(tidyverse)
> library(DeclareDesign)
> fabricate(
+   N = 100,
+   potential_outcomes(Ystar ~ 0.5 * Z),
+   Z = rbinom(N, 1, 0.5)
+ ) %>% 
+   mutate(
+     Y = reveal_outcomes(Ystar ~ D)
+   )
Error: Problem with `mutate()` input `Y`.
x cannot coerce class ‘"function"’ to a data.frame
ℹ Input `Y` is `reveal_outcomes(Ystar ~ D)`.
Run `rlang::last_error()` to see where the error occurred.
nfultz commented 3 years ago

It looks like it is using DeclareDesign::reveal_outcomes and not fabricatr::reveal_outcomes ???

nfultz commented 3 years ago

Running this in the debugger, it is correctly delegating to fabricatr::reveal_outcomes (and not the step creator in DeclareDesign) - however, the NSE is resolving D to the distance function stats::D.

You do get a slightly different error message when doing what I thought it was doing:

> fabricate(
+   N = 100,
+   potential_outcomes(Ystar ~ 0.5 * Z), 
+   Z = rbinom(N, 1, 0.5)
+ ) %>% 
+   mutate(
+     Y = DeclareDesign::declare_reveal(Ystar ~ Z)
+   )
Error: Problem with `mutate()` input `Y`.
✖ Input `Y` must be a vector, not a `design_step/dd/function` object.
ℹ Input `Y` is `DeclareDesign::declare_reveal(Ystar ~ Z)`.
Run `rlang::last_error()` to see where the error occurred.

The problematic line is

https://github.com/DeclareDesign/fabricatr/blob/789b2d9ab46f85642948d1f2a3a9212df0cabfd1/R/reveal_outcomes.R#L52

Instead of going through eval_tidy and failing deep in the call stack, you can retrieve assignment vars directly, and specify a custom error message using a single mget. Something like this would probably suffice:

mget(x=assignment_variables,envir=environment(x), mode="integer", inherits=TRUE,  ifnotfound=list(function(x) stop(x, " not found", call.=FALSE)))
Error: D not found
graemeblair commented 2 years ago

Feel like this is very specific to the case where you hit on an object that happens to exist. The error when you put in a variable that doesn't exist (object 'Q' not found) is pretty clear to me. Closing.