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

Pass variables between exercises #72

Closed
rachelss opened this issue May 8, 2017 · 24 comments
Closed

Pass variables between exercises #72

rachelss opened this issue May 8, 2017 · 24 comments

Comments

@rachelss
Copy link

rachelss commented May 8, 2017

If I load data into a variable in one exercise that variable is not found in the next exercise.

@jjallaire
Copy link
Member

That's by design so that each exercise is completely independent (users can execute any exercise without worrying about whether they completed previous exercises correctly). You can compensate for this with setup chunks that "prime" each exercise with the correct preconditions. See the documentation here: https://rstudio.github.io/learnr/exercises.html#exercise_setup

@rachelss
Copy link
Author

I was hoping to use this for a class but students would need to enter the data. I can see the advantage of independent exercises, but the tutorial creator could make them independent even if you allow connections among the exercises.

@jjallaire
Copy link
Member

jjallaire commented May 15, 2017 via email

@dtkaplan
Copy link

#rachelss I'd like to talk with you about this. I also have been having to work around the each-exercise-it's-own-session design. I've been finding ways to do this, but I'm still trying to sort out whether the difficulty is my limited imagination of how to write exercises or a genuine need for communication among the exercise chunks. Could you describe to me the problem you're facing? With modest probability, I might help you find a work around, but I know it would help me sharpen my thinking about this situation.

@jjallaire
Copy link
Member

jjallaire commented May 15, 2017 via email

@rachelss
Copy link
Author

@dtkaplan I would like students in our intro bio course to graph in R. To do this they need a very low barrier so they can (initially) focus on how to load data and make a single graph. Exercise 1 is then load data. Assume example data given. Student then changes the data file. Student loads data with and without header, and with/without rownames as data. Exercise 2 is make graph. Instructions are shown with initial data (loaded and hidden by author). Student then changes to their data. Students could be asked questions after each exercise. The goal is to break it up as much as possible to allow focusing on a single task. Finally students would need to be able to print.

@jjallaire If there are concerns about sharing data among exercises but you're willing to allow this can you write in warnings that come up when publishing that alert the author about using data that is not built in. I can see where it could be done unintentionally and with problematic results.

I do understand I am asking you to extend learnr to a whole new use that might be beyond its scope. However, I think this interface would be appealing to students. It is currently challenging to get students over the initial learning curve for R and I am looking for anything to help.

@dtkaplan
Copy link

This is exactly the sort of situation I've faced, @rachelss. Here are some of the ways to deal with it with stand-alone exercises, although you know best what would work for your students.

  1. You can read in data from a web site from within a chunk. Then the question is how to get the student data on a web site. One way that I find works well with students is Google spreadsheets. They create a publicly readable spreadsheet on Google, copy out the sharing link, then paste this into the chunk.
  2. I also want to break things into bite-sized chunks. I've taken to repeating the command lines that the student needs in the next exercise. Here's an example

I can certainly be wrong about (2) --- I'll have my first chance to test it out this week at USCOTS.

@jjallaire, I think the policy decision you made is a good one, since it's good to encourage people to make the exercises as independent as possible. One way that I've thought my encourage the independent-exercise model while allowing an override by the exercise author would be to have a exercise-environment knitr argument that is given the name of an environment and makes sure that the code in the exercise is evaluated in that environment. But I haven't thought deeply about this and what problems it might cause.

@rachelss
Copy link
Author

rachelss commented May 15, 2017

@dtkaplan I do like the Google sheets idea and that is the plan.
The idea to copy previous lines of code into the current chunk is a thought. It results in a complete script at the end, which I like. I'll work up exercises this way and get back to this. Thanks for the idea.

@jjallaire
Copy link
Member

jjallaire commented May 15, 2017 via email

@rachelss
Copy link
Author

@jjallaire I will try having students
(1) run example data to focus on what the single line of code does
(2) copy code from previous chunks to accumulate a script that isn't dependent on previous chunks

thanks for all the discussion and advice

@jjallaire
Copy link
Member

You can also "seed" code from the previous chunks in the new chunks (this would work especially well with progressive reveals of sections, https://rstudio.github.io/learnr/exercises.html#progressive_reveal). In other words, you just insert the correct solution from the previous chunks at the beginning of the new chunks. This allows "building on" the previous chunks in a fashion but still preserves independent execution.

@alex23lemm
Copy link

Recently, I taught a bunch of people (all R newbies) the data science process. The emphasis was on understanding the DS process and not on learning R. Within the tutorial the students went through the typical phases: Importing data, exploring, transforming, modeling, evaluating models.
Especially in the the later phases 'exercise chaining' would have been beneficial. For instance, when you let your students build several models in upstream chunks , you would like to have those models available further downstream in chunks in which you ask them to make predictions using the test data. Another example of objects which you would need in several exercise chunks is the training and test set.

What I ended up doing was to calculate and to put all major results of the different DS process steps either into the global environment or into setup chunks which were shared by several exercises . Within the tutorial the students themselves calculated those results again in the respective chunks. However, all of the results were already available to them right from the start (As R newbies they did not know the ls() command :-))

You can also "seed" code from the previous chunks in the new chunks (this would work especially well with progressive reveals of sections. ... This allows "building on" the previous chunks in a fashion but still preserves independent execution.

Well, this could be one solution but can result in an ugly one: Continuing with the DS process example, you would need to "seed" the complete code for splitting the data into a training and test set plus the model building steps in order to predict new values using the respective model and the test set in an exercise at the end. In tutorials in which you really follow a certain kind of process this setup/solution seems to be too much of a repetition.

Long story short, I think "exercise chaining" would be a valuable feature.

@daob
Copy link

daob commented Aug 2, 2017

+1 on this one. Allowing input from Shiny widgets (sliderInput, numericInput, ...) would be incredibly useful as well.

@larssk
Copy link

larssk commented Aug 15, 2017

Environment sharing would be very valuable for my teaching project as well. I'm currently exploring exercise setup, https://rstudio.github.io/learnr/exercises.html#exercise_setup, but this does not suffice when I need the first chunk to be an exercise. I'm voting for an option where you can explicitly define the environment for each chunk.

@profandyfield
Copy link

I agree - chaining is useful, but so far not having a problem with self-generating the chain in a series of setup code chunks. Obviously it is laborious writing lots of setup chunks, but it at least makes you think explicitly about what an exercise relies on.

@kmishra9
Copy link

kmishra9 commented May 4, 2018

I will also agree having the option to chain would be incredibly useful for a class I'm helping develop. The idea would be to have learnR simulating what is essentially a Jupyter Notebook for students and that could definitely come in handy without requiring the setup to just run code in the browser

@kmishra9
Copy link

kmishra9 commented Jun 28, 2018

Because the chaining options don't exist in LearnR, we're unfortunately going to have to migrate our development thus far to RTutor, which offers very similar features to LearnR but with chaining enabled.

@ries9112
Copy link

really wish this was an option in learnr :)

@timchurches
Copy link

timchurches commented Dec 3, 2018

+1 for adding optional environment sharing between code chunks in learnr. We have been (painstakingly) recreating environments in setup chunks, but we are now writing a new course (for an MSc in Health Data Science) on deep learning, and re-running the set-up code before each chunk is no longer viable, nor is pre-computing everything and stuffing it in the .GlobalEnv at start-up ideal (which is what the "setup" chunk does).

You can of course explicitly assign objects to the global environment, and they are then available to subsequent code chunks, like this:


Write the R code required to add two plus two:

```{r two-plus-two, exercise=TRUE}
four <- 2 + 2
assign("four", four, envir=globalenv())
```

Exercise with Code

```{r what-is-four, exercise=TRUE}
four
```


but you need to explain to the students that all those assign() calls are needed as a consequence of using the learnr environment, and aren't otherwise required That's ugly, and confusing for the students. If there were post-chunk hooks that shared the chunk environment, then certain objects could be assigned invisibly to .GlobalEnv and it would all just work. Well, if the execution order of chunks is correct... ways around this might be to support pre-chunk check function calls, or maintain a list of chunks on which the current chunk depends and whether they have all been run in the correct order. That sounds messy and complex... How does Jupyter handle this issue?

Actually, maybe just a chunk option that causes that chunk to execute in the global environment? such chunks could even be rendered with slightly different background colour to distinguish them from stand-alone chunks. We teach our students about R environments and scoping rules when we introduce functions. It confuses them at first, but it is worth it later on. Thus explaining that some code chunks in a learnr document execute in the global environment and thus share their state isn't a problem for us. So a single flag on a code chunk to make it a global environment chunk would suffice, I think. This could use the same hook as the special-casing of the chunk name 'setup" which causes it to execute in teh global environment. Hmmm, this might be a very easy change indeed.

@ashgreat
Copy link

Has there been any progress on this issue? I spent my whole day today learning Learnr and porting a tutorial on MNL, SVM, and Ordinal regression to Learnr only to meet with a terrible error message that it couldn't find the data set that we read in the previous chunk! It's a great package but unfortunately, I can't use it. I looked at RTutor but it's not as polished as Learnr.

@timchurches
Copy link

timchurches commented Apr 27, 2019

@ashgreat, yes, each learnr chunk executes in its own environment. There are chunk hooks provided to allow other chunks to set up the environment for a target chunk, or all chunks. You just need to use those. They work well provided the chunk set-up is fast and simple. If it involves a lot of code or computation however, it's a problem. See my comment above for some work-arounds for that, but a proper solution is needed. Apart from that major flaw, learnr is very good.

@ashgreat
Copy link

ashgreat commented May 1, 2019

@ashgreat, yes, each learnr chunk executes in its own environment. There are chunk hooks provided to allow other chunks to set up the environment for a target chunk, or all chunks. You just need to use those. They work well provided the chunk set-up is fast and simple. If it involves a lot of code or computation however, it's a problem. See my comment above for some work-arounds for that, but a proper solution is needed. Apart from that major flaw, learnr is very good.

Thanks @timchurches. Yes, I saw your solution. Unfortunately, my exercise is pretty complex and using assign() in each case is guaranteed to create confusion as the class is big with large variation in programming skills.

@jjallaire, you wrote above

BTW it's not technically difficult to allow the sharing, it's more of a
policy decision. I'm open to doing whatever the consensus is here.

Could you please consider altering the policy? It looks like many of us would like to have the option of passing objects between chunks.

@crecapet
Copy link

+1 to be able to define the environment in which code chunks are run, while keeping them independent as default

@schloerke
Copy link
Collaborator

@nischalshrestha has created a fair compromise by allowing for setup chunks to be chained together. in #390 which was just merged.

  • All setup chunks must be explicitly declared. (Except for the default NAME-setup exercise setup chunk.)
  • The chain of setup chunks must not form a cycle
  • Setup chunks are allowed to point to other exercise chunks, however it will be treated like a regular Rmd chunk and not look for the default NAME-setup chunk and will use the code provided in the document. (Not the user's latest submission.)

Example:

```{r setup, include = FALSE}
library(learnr)
d <- 3
``` 

```{r setupA}
a <- 5 
``` 

```{r setupB, exercise.setup = "setupA"}
b <- a + d
``` 


Default behavior.
Chunks that will be executed: setup, user submission for ex0
```{r ex0, exercise=TRUE} 
d # 3
```

Chain setup values.
Chunks that will be executed: setup, setupA, setupB, user submission for ex1
```{r ex1, exercise=TRUE, exercise.setup = "setupB"} 
x <- b + 1
x # 9
```

Do not need to use the full chain.
Chunks that will be executed: setup, setupA, user submission for ex2
```{r ex2, exercise=TRUE, exercise.setup = "setupA"}
y <- a + 1 
y # 6
```

Use other exercise's pre-filled code chunk. 
Chunks that will be executed: setup, setupA, setupB, ex1, user submission for ex3
```{r ex3, exercise=TRUE, exercise.setup = "ex1"}
z <- x + 6 
z
```

Closing as fixed in #390

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