tazinho / advanced-r-solutions Goto Github PK
View Code? Open in Web Editor NEWSet of solutions for the Advanced R programming book
Home Page: https://advanced-r-solutions.rbind.io/
Set of solutions for the Advanced R programming book
Home Page: https://advanced-r-solutions.rbind.io/
master and dev-version should be enough for now, right?
Give a little more explanation what the book is about, where the project is at right now and where it is headed?
Deploys from Travis can be found here https://advanced-r-solutions.rbind.io
Next steps:
Let's eventually try to finish one chapter to see, what kind of result we are aiming for and what steps are needed to get there.
We can do this, once the 90% milestone is reached.
chapter expressions:
assign3 <- function(x, value, env = parent.frame()){
eval(substitute(x <- as.name(x)), env)
eval(substitute(x <- value), env)
}
Q: The following two calls look the same, but are actually different:
(a <- call("mean", 1:10))
#> mean(1:10)
(b <- call("mean", quote(1:10)))
#> mean(1:10)
identical(a, b)
#> [1] FALSE
What’s the difference? Which one should you prefer?
A: call evalulates its ... arguments. So in the first call 1:10 will be evaluated
to an integer (1, 2, 3, …, 10) and in the second call quote()
compensates the effect of the evaluation, so that b
’s second element will be
the expression 1:10 (which is again a call):
as.list(a)
#> [[1]]
#> mean
#>
#> [[2]]
#> [1] 1 2 3 4 5 6 7 8 9 10
as.list(b)
#> [[1]]
#> mean
#>
#> [[2]]
#> 1:10
We can create an example, where we can see the consequences directly:
# h <- call("mean", z)
##> Error: object 'z' not found
h <- call("mean", quote(z))
# eval(h)
##> Error in mean(z) : object 'z' not found
z <- 1:10
eval(h)
#> [1] 5.5
From my intuition I would prefer the second version,
since it behaves more like lazy evaluation,
but I am not sure if this is the correct answer as indended by the exercise.
Let's see what we still have to do content-wise.
Malte will create and commit an Rmd-file, which contains unsolved exercises. When new exercises should come up in the 2nd Ed. we will also add them here.
I would like to discuss this excercise in detail. (edit: the solution can be found here and looks really good https://github.com/asnr/advanced-r-answers/blob/master/metaprogramming/nse.md just want to understand a bit more in very detail before updating...)
Q: What happens if you use quote() instead of substitute() inside of subset2()?
A: We will get "Error in eval(expr, envir, enclos) : object 'x' not found" in the above example. We are not sure if the problem relates to finding the right expression or the correct environment for evaluation.
subset4 <- function(x, condition) {
condition_call <- substitute(condition)
r <- eval(condition_call, x)
x[r & !is.na(r), , drop = FALSE]
}
subset5 <- function(x, condition) {
condition_call <- quote(condition)
r <- eval(condition_call, x)
x[r & !is.na(r), , drop = FALSE]
}
sample_df2 <- data.frame(x = 1:10)
subset4(sample_df2, x > 8)
# x
# 9 9
# 10 10
subset5(sample_df2, x > 8)
# Error in eval(expr, envir, enclos) : object 'x' not found
# Why is this the case? Remember that the difference between `substitute` and `quote`
# is that `quote` just returns the expression whereas `substitute` can modify the
# expression within an environment, performing substitutions.
#
# Therefore `substitute` will contain the information about what the dataframe is, whereas
# `quote` will not.
I am not happy with both. The first one is not finished and the 2nd one is not detailed enough...
I would really like to understand better, why eval(condition, sample_df2) here (when called inside a function and condition is a supplied expression which is quoted inside the function) does not work, while many details are unclear. See the following:
> rm(list = ls(all = TRUE))
> # This works
> subset2 <- function(x, condition) {
+ condition_call <- substitute(condition)
+ r <- eval(condition_call, x)
+ x[r, ]
+ }
>
> sample_df2 <- data.frame(x = 1:10)
> subset2(sample_df2, x > 8)
[1] 9 10
>
> # This fails
> subset2q <- function(x, condition) {
+ condition_call <- quote(condition)
+ r <- eval(condition_call, x)
+ x[r, ]
+ }
> subset2q(sample_df2, x > 8)
Error in eval(expr, envir, enclos) : object 'x' not found
> # However, outside of a function both work
> eval(substitute(x>8), sample_df2)
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE
> eval(quote(x>8), sample_df2)
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE
>
> # It also does use x (or other vars), when x is in the global environment
> x = 1:100
> subset2q(sample_df2, x > 8)
[1] 9 10 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[22] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[43] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[64] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[85] NA NA NA NA NA NA NA NA
> rm(x)
> y = 1:100
> subset2q(sample_df2, y > 8)
[1] 9 10 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[22] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[43] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[64] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[85] NA NA NA NA NA NA NA NA
>
> # We can look where x is evaluated after substituting / quoting
> test_quote <- function(x, condition) {
+ condition_call <- quote(condition)
+ x <- list2env(x)
+ y <- environment()
+ list(x_env = x, env = y, eval(condition_call, x))
+ }
> test_quote(sample_df2, {list(eval_env = environment(), par_eval_env = parent.frame())})
$x_env
<environment: 0x00000000165fc0f0>
$env
<environment: 0x00000000165fad90>
[[3]]
[[3]]$eval_env
<environment: R_GlobalEnv>
[[3]]$par_eval_env
<environment: R_GlobalEnv>
>
> test_subs <- function(x, condition) {
+ condition_call <- substitute(condition)
+ x <- list2env(x)
+ y <- environment()
+ list(x_env = x, env = y, eval(condition_call, x))
+ }
> test_subs(sample_df2, {list(eval_env = environment(), par_eval_env = parent.frame())})
$x_env
<environment: 0x00000000165c5840>
$env
<environment: 0x00000000165fe478>
[[3]]
[[3]]$eval_env
<environment: 0x00000000165c5840>
[[3]]$par_eval_env
<environment: 0x00000000165c53e0>
> # So when quoted expressions are evaluated inside a function it seems that they
> # are always evaluated inside the global environment. Is that really the message
> # from this exercise or is sth. different happening here. Especially, what is
> # happening inside substitute, which is not happening inside quote ?
>
> # This doesn't seem to be the only difference.
> f_q <- function(cond)quote(cond)
> f_q(a > b)
cond
> f_s <- function(cond)substitute(cond)
> f_s(a > b)
a > b
> # Also note that this would work:
> subset2q_cheet <- function(x, condition) {
+ condition_call <- quote(condition)
+ r <- eval(quote(x > 8), x)
+ x[r, ]
+ }
> subset2q_cheet(sample_df2, anything)
[1] 9 10
> # Since this time the correct environment is found...
> subset2q_cheet2 <- function(x, condition) {
+ condition_call <- quote(condition)
+ x = list2env(x)
+ y = environment()
+ list(x_env = x, env = y, eval(quote({list(x > 8, environment())}), x))
+ # x[r, ]
+ }
> subset2q_cheet2(sample_df2, anything)
$x_env
<environment: 0x00000000157d63a8>
$env
<environment: 0x00000000157d5fa8>
[[3]]
[[3]][[1]]
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE
[[3]][[2]]
<environment: 0x00000000157d63a8>
> # Superstrange that this works
> subset2q <- function(x, condition) {
+ condition_call <- condition
+ r <- eval(condition_call, x)
+ x[r, ]
+ }
> subset2q(sample_df2, quote(x > 8))
[1] 9 10
Hadley has started to include some "Parts" from I
to V
in his book. -> compare https://adv-r.hadley.nz/
I think it would be nice to find out how, these were created and to style our sidebar in a similar way.
see here for the development version
http://adv-r.hadley.nz/
When the new version is available, we will change also the order of the solutions to match the new adv r version.
Excercises, which are not in the new version, will move to the appendix of the solutions book
Edit: Update Advanced R Version link to 2nd Edition, when we finished the exercises / review
... back to the old one.
Afterwards I will minimize the bookdown version into a one-page book and finish the redirection issue
#86
Goal:
Enable users and contributers which fork the project to directly build the book.
Next steps:
-enable-memory-profiling
so all exercises can be renderedList for @hadley
Will be updated soon.
In general the status of solutions is at the start of the solutions book prerequisites.
@henningsway Please post any questions to exercises, especially unclear exercises, here (if there is no better place). I will update posted questions in the start post to have everything in one place.
The order is the same as in the new version of Advanced R.
on.exit()
and capture.output()
/ capture.output2()
) is a bit cumbersome and our answer should be more precise. Maybe a hint in the question?new_lm()
, look like? Why is a constructor function less useful for linear models?"
ANY
method, but I am not sure if this is really the intention of this question.and also higher resolution for the cover.
Currently under revision:
Malte & Henning: OoField guide in new AdvR version
Peter: Expressions (mostly done in #33; some comments of the pull request have to be cleared)
Robert (+ help of Peter): Domain Specific Languages
this can be done via rmarkdowns spellchecker. after #14 and #15
Hey ya'll,
I appreciate you putting together solutions for this lovely book.
I don't think your solution to 32.1 is correct though. I believe we should be capturing the user input as part of the function like this:
is.expression_component <- function(x) {
x = substitute(x)
(is.atomic(x) & length(x) == 1) | is.call(x) | is.name(x) | is.pairlist(x)
}
The reason for this R will evaluate the input when you call is.atomic(x)
making the call is.expression_component(x <- 1)
return true because is.atomic(x)
is true. It should return true because is.call(x)
is true.
Let me know if you disagree!
When starting with an exercise a lot of things can be confusing. However, we already produced some content that might be easy to refactorize. Here is the place to collect any guidance on this topic.
This looks great. Can I "bless" this solution set in some way?
I can't remember exactly how you do this, but it would make it contributions from the community much more likely.
This would make pull requests more straightforward. It would seem also be preferable to name the files according to their chapter. :)
(At top page on https://github.com/Tazinho/Advanced-R-Solutions)
after solving #14
Thanks. :)
Process:
Will try to structure some of my open questions in this issue.
remove files that are not strictly necessary for the compilation of the book from version control.
Attempting to solve
E) 19.2.6.1 - E) 19.2.6.4
Use a tribble in the rmarkdown chunk instead of an external xls file.
moved to and merged with #123
18.3.3 Exercises ("Expressions") #5 asks:
How does
mode<-
work? How does it usecall()
?
The solution given in our book annotates a particular function. However, it looks like the book annotates mode
. It doesn't look like mode
contains call()
, though it does contain "call"
.
I think we should be annotating mode<-
, not mode
. But mode<-
also does not use call
at all.
The answer I gave in my repo states:
It dynamically creates a transformation function (e.g.,
as.numeric
,as.logical
, etc.) by usingpaste0
, and then executes that by usingeval(call())
with that function and the item to be transformed.
The first part is accurate but it doesn't look like mode<-
uses eval(call())
. I thought maybe this is an R version problem, but @robertzk confirms mode<-
in R 3.3 is still the same. I also can't find anything about it in the R CHANGELOG.
What am I missing?
The content and the exercises of Advanced R 2nd Ed are still changing (less and less), see hadley/adv-r#1259
At the moment the process of checking for changes in Adv R and updating our book accordingly (e.g. #74) is manual and somewhat tedious, but doable.
We also need to update a list of open exercises (#73), when Adv R changes.
If anyone has a smart ideas, how to improve these processes, please sketch them out here.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.