This is a solution, but it would be better if there is not restriction on the order of the variables. As I have describe in one of the above posts, what I really want to do is this:
User inputs a function, and a data.frame which contains all the variables that appear in the function. I will need to substitute the mean values of the variables into the function. (Actually for computing the marginal effects, one also needs to compute the average of the function values evaluated at all rows of the data.frame). So in order to use apply, I will need to extract the variable order and names from the user-defined function. This is because the function might be func(x,y,z), but the data.frame has the columns z, x, y, a, b, c, d (it has more columns than what are needed by the function, which is the usual case. And the order is different). So John Myles White's opinion is that this is very hard to do in the current Julia (see his post above). On Sunday, February 2, 2014 9:03:21 AM UTC-8, Johan Sigfrids wrote: > > Thinking about this, the whole let or macro might be overkill. If the > user provides both the function and the arguments, the user should be able > to provide the arguments in the correct form for the function, in which > case you need neither let nor macros. You could just call apply directly > on those two: > > user_function(x,y,z) = x + y + z^2 > user_arguments = (3, 4, 5) > > apply(user_function, user_arguments...) > > > On Sunday, February 2, 2014 6:49:52 PM UTC+2, Walking Sparrow wrote: >> >> I guess "apply" and "let" can do some work here. But I do not know the >> variable names and number that the user would use. >> >> So now I need a macro that can construct the let-apply block with the >> variable number undetermined. The macro should be able to accept any number >> of variables. >> >> Suppose that the user inputs >> >> func(x, y) = x+2y and x = 1, y = 2 >> >> @my_macro func (x=1, y=2) would be expanded to >> >> let x = 1, y = 2 >> apply(func,1, 2) >> end >> >> And if the user inputs >> >> func(a, b, c, d) = a + b + c + d, and a = 1, b = 2, c = 3, d=4 >> >> @my_macro func (a = 1, b = 2, c = 3, d = 4) would expand to >> >> let a = 1, b = 2, c = 3, d = 4 >> apply(func, 1,2,3,4) >> end >> >> How to write a macro like this? >> >> If I knew the function and the variables, of course I could directly call >> the function or use let-apply, but the problem is that these are the inputs >> of the user, which I cannot know beforehand. >> >> >> On Sunday, February 2, 2014 8:11:34 AM UTC-8, Keno Fischer wrote: >>> >>> Or you could just call the function directly: >>> >>> f = (x,y,z)->x+y+z^2 >>> let x=3, y=4, z=5 >>> f(x,y,z) >>> end >>> >>> or >>> >>> f((x,y,z)...) >>> >>> or >>> >>> f((1,2,3)...) >>> >>> >>> >>> On Sun, Feb 2, 2014 at 10:59 AM, Johan Sigfrids <[email protected]>wrote: >>> >>>> Can't you just do this with apply? Something like this: >>>> >>>> f = (x, y, z) -> x + y + z^2 >>>> let x=3, y=4, z=5 >>>> apply(f, x, y, z) >>>> end >>>> >>>> >>>> On Sunday, February 2, 2014 5:47:36 PM UTC+2, Walking Sparrow wrote: >>>>> >>>>> Let me clarify a little bit. My question is actually the following: >>>>> >>>>> In R, one can do something like >>>>> >>>>> > f <- function(x1, x2, x3, x4, x5, x6) { some expressions that you >>>>> like to use } >>>>> > evaluate.at <- list(x1 = 2, x2 = 2.3, x3 = 2, x4 = 1.2, x5 = 3.4, >>>>> x6 = 5.6) >>>>> > do.call(f, evaluate.at) # get the value >>>>> >>>>> "do.call" can accept any valid function, and a list of variable >>>>> values. There is no restriction to the function or the number of >>>>> variables. >>>>> Sometimes this is very useful. >>>>> >>>>> How do we do similar things in Julia? Does Julia have a function or >>>>> macro similar to "do.call"? >>>>> >>>>> On Sunday, February 2, 2014 4:09:05 AM UTC-8, Mauro wrote: >>>>>> >>>>>> I don't quite comprehend your problem, so maybe this doesn't help. >>>>>> But >>>>>> as far as I can tell, there is no need for macros: >>>>>> >>>>>> Just define your function as a normal function, which can be >>>>>> evaluated >>>>>> for any (x,z): >>>>>> >>>>>> julia> f(x,z) = x + x*z + log(sin(x) + 2) * log(cos(z) + 2) >>>>>> f (generic function with 1 method) >>>>>> julia> x0 = 2.3; z0 = 1.4; >>>>>> julia> f(x0,z0) >>>>>> 6.302488546391614 >>>>>> >>>>>> For the first step: use automatic differentiation on the function in >>>>>> question. The package https://github.com/scidom/DualNumbers.jl can >>>>>> do >>>>>> this: >>>>>> >>>>>> julia> using DualNumbers >>>>>> julia> xdu = dual(x0,1) >>>>>> 2.3 + 1.0du >>>>>> >>>>>> # this gives (f(x0,z0), \partial f / \partial x at (x0,z0)) : >>>>>> julia> f(xdu,z) >>>>>> 6.302488546391614 + 2.2120074784516013du >>>>>> >>>>>> julia> zdu = dual(z,1) >>>>>> 1.4 + 1.0du >>>>>> # this gives (f(x0,z0), \partial f / \partial z at (x0,z0)) : >>>>>> julia> f(x,zdu) >>>>>> 6.302488546391614 + 1.8413102782559223du >>>>>> >>>>>> (double check that the derivatives are right but I think that is how >>>>>> it >>>>>> should work) >>>>>> >>>>>> On Sat, 2014-02-01 at 23:42, [email protected] wrote: >>>>>> > You are right about that I have an R background. What I am trying >>>>>> to do is >>>>>> > to evaluate a function given by the user. For example, >>>>>> > >>>>>> > I want to write a function that can compute the marginal effects of >>>>>> a >>>>>> > linear or logistic model. For simplicity, let's just use linear >>>>>> regression. >>>>>> > If the user did a linear regression using the following model (I am >>>>>> using >>>>>> > the formula syntax from R) >>>>>> > >>>>>> > y ~ x + z + sin(x) * sin(z) for the data set my_data, which has >>>>>> three >>>>>> > columns x, y, and z >>>>>> > >>>>>> > Then the marginal effects at the mean are computed like this: >>>>>> First, >>>>>> > compute the first derivative of 1+ x + z + sin(x) * sin(z). This >>>>>> can be >>>>>> > done in R using the function "deriv" to get the expression of the >>>>>> first >>>>>> > derivative. In the second step, I need to substitute the mean >>>>>> values of x >>>>>> > and z into the result of the first step. An example of this would >>>>>> be the >>>>>> > "margins" function in the R package "PivotalR" >>>>>> > (http://cran.r-project.org/web/packages/PivotalR/ and >>>>>> > https://github.com/gopivotal/PivotalR) >>>>>> > >>>>>> > Right now, I have no idea how to do the first step in Julia. But >>>>>> that is >>>>>> > OK, because I just started learning Julia. >>>>>> > >>>>>> > Now my question is in the second step. The user can use any complex >>>>>> > expressions in the linear regression like y ~ x + x*z + log(sin(x) >>>>>> + 2) * >>>>>> > log(cos(z) + 2), and the data set my_data and formula can have any >>>>>> number >>>>>> > of variables like x1, x2, ...., x1000. So when you write the code >>>>>> for the >>>>>> > value substitution in the second step, you cannot know which >>>>>> function and >>>>>> > what variables you will have. >>>>>> > >>>>>> > So in Julia or R, I need a function or macro F(f, [....]) that does >>>>>> this: >>>>>> > given a function f, whose format is the input from the user, and a >>>>>> set of >>>>>> > variable values [...], whose number and names are also the input >>>>>> from the >>>>>> > user, F(f, [...]) returns the value of f evaluated at the values >>>>>> [...]. For >>>>>> > example, the user inputs >>>>>> > >>>>>> > f = 1 + z + cos(x)*log(2+cos(z))/(2+sin(x)) >>>>>> > >>>>>> > and [x = 2.3, z = 1.4], >>>>>> > >>>>>> > F should return the value of f evaluated at x = 2.3 and z = 1.4. >>>>>> > >>>>>> > This can be done in R, see "margins" function in PivotalR, which >>>>>> actually >>>>>> > does big data computation in-database. The problem is how to do the >>>>>> same >>>>>> > thing in Julia? >>>>>> > >>>>>> > Hope my explanation makes my question clearer. >>>>>> > >>>>>> > On Saturday, February 1, 2014 2:35:38 PM UTC-8, Jameson wrote: >>>>>> >> >>>>>> >> You need to provide more detail on what you are trying to do with >>>>>> this. >>>>>> >> You seem >>>>>> >> to be confusing several concepts involving the usage of >>>>>> expressions, >>>>>> >> macros, and functions. I can't tell if you are trying to write >>>>>> special >>>>>> >> syntax, or are just unaware of anonymous functions: >>>>>> >> >>>>>> >> Mostly, why is :(sin(x) + cos(y) * sin(z)) an expression, and not >>>>>> a >>>>>> >> function? It seems like you perhaps have an R background? >>>>>> >> >>>>>> >> f(x,y,z) = (sin(x) + cos(y) * sin(z)) >>>>>> >> f(1,2,3) >>>>>> >> >>>>>> >> On Sat, Feb 1, 2014 at 12:04 PM, Walking Sparrow < >>>>>> [email protected]<javascript:>> >>>>>> >> wrote: >>>>>> >> > So the real question is how to generate a code block like this >>>>>> >> > >>>>>> >> > quote >>>>>> >> > x = 2 >>>>>> >> > y = 3 >>>>>> >> > ..... >>>>>> >> > x + y + .... >>>>>> >> > end >>>>>> >> > >>>>>> >> > Need to embed a for loop inside the macro definition? >>>>>> >> > >>>>>> >> > >>>>>> >> > >>>>>> >> > On Saturday, February 1, 2014 8:52:30 AM UTC-8, Walking Sparrow >>>>>> wrote: >>>>>> >> >> >>>>>> >> >> Please forgive me if this is a stupid question. Suppose I have >>>>>> an >>>>>> >> >> expression >>>>>> >> >> >>>>>> >> >> :(sin(x) + cos(y) * sin(z)) >>>>>> >> >> >>>>>> >> >> and the values of x, y, z. >>>>>> >> >> >>>>>> >> >> How can I write a macro that can substitute the values of x, y, >>>>>> z into >>>>>> >> the >>>>>> >> >> above expression? The number of values that I want to >>>>>> substitute >>>>>> >> depends on >>>>>> >> >> the actual use cases and thus is unknown. >>>>>> >> >> >>>>>> >> >> I wrote a function that can do this >>>>>> >> >> >>>>>> >> >> function substitute(expr::Expr, vals::Array{Expr,1}) >>>>>> >> >> for i = 1:length(vals) >>>>>> >> >> @eval $(vals[i]) >>>>>> >> >> end >>>>>> >> >> @eval $expr >>>>>> >> >> end >>>>>> >> >> >>>>>> >> >> x = 10 >>>>>> >> >> y = 23 >>>>>> >> >> >>>>>> >> >> substitute(:(x+y), [:(x = 2), :(y = 3)]) >>>>>> >> >> >>>>>> >> >> x >>>>>> >> >> y >>>>>> >> >> >>>>>> >> >> But if you run the above code, you will see that the values of >>>>>> global x >>>>>> >> >> and y are changed, which is not what I intend to do. This is >>>>>> because >>>>>> >> "eval" >>>>>> >> >> does the evaluation in the global scope. Besides, I think it is >>>>>> a bad >>>>>> >> coding >>>>>> >> >> pattern to use eval and it is slow. >>>>>> >> >> >>>>>> >> >> It would be better if this can be done using macro. But I have >>>>>> no idea >>>>>> >> >> about how to do this. >>>>>> >> >>>>>> >>>>>> -- >>>>>> Sent with my mu4e >>>>>> >>>>>> >>>
