I'd like to create a function called g which in turn contains three other functions f1 and f2. Each of the two functions f1, f2 returns a data frame. I would like that the function g returns the two dataframe obtained from f1 and f2. Here is the code that I run:
g <- function(n,a,b,c,d,e) {
f1 <- function(n,a,b,c,d,e) {
X <- a*matrix(sample(0:1,n,replace = T),nrow=n,ncol=1)
Y <- (b*c-d)*matrix(sample(1:10,n,replace = T),nrow=n,ncol=1)
Z <- (a*e)*matrix(sample(0:12,n,replace = T),nrow=n,ncol=1)
data1 <- as.data.frame(cbind(X,Y,Z))
colnames(data1) <- c("X","Y","Z")
return(data1)
}
f1(n,a,b,c,d,e)
varpredict <- lm(Y ~ 0 + X + Z, data=f1(n,a,b,c,d,e))$fitted.values
h <- function(){
olsreg <- lm(Y ~ 0 + X + Z, data=f1(n,a,b,c,d,e))
P <- olsreg$residuals^2
return(P)
}
h()
G <- rep(0,n)
f2 <- function(n,a,b){
for (i in 1:n) {
G[i] <- varpredict[i]-a
}
X <- matrix(sample(0:1,n,replace = T),nrow=n,ncol=1)+h()
Y <- b*matrix(sample(1:10,n,replace = T),nrow=n,ncol=1)
Z <- (a*b)*matrix(sample(0:12,n,replace = T),nrow=n,ncol=1)-G
data2 <- as.data.frame(cbind(X,Y,Z))
colnames(data2) <- c("X","Y","Z")
return(data2)
}
f2(n,a,b)
return(list(data1,data2))
}
To run the function g I did this:
n=100
a=0.3
b=0.5
c=0.3
d=-1.32
e=c*d
my_function <- g(n,a,b,c,d,e)
But I received the following error message:
Error in g(n, a, b, c, d, e) : object 'data1' not found
Why am I getting this error?
First off, when you call your functions f1 and f2 you need to store their return value somewhere.
Secondly, it’s unclear why you want f1 inside g: it doesn’t seem to share any state with g, so it can be defined independently alongside g instead of inside it. That said, if it’s only ever used inside g then this is to some extent a matter of style.
Here’s how I’d write your code:
g <- function (n, a, b, c, d, e) {
f1 <- function (n, a, b, c, d, e) {
X <- a * matrix(sample(0 : 1, n, replace = TRUE), nrow = n)
Y <- (b * c - d) * matrix(sample(1 : 10, n, replace = TRUE),nrow = n)
Z <- (a * e) * matrix(sample(0 : 12, n, replace = TRUE), nrow = n)
data.frame(X, Y, Z))
}
f2 <- function(n, a, b) {
G <- varpredict - a
X <- matrix(sample(0 : 1, n, replace = TRUE), nrow = n) + square_res
Y <- b * matrix(sample(1 : 10, n, replace = TRUE), nrow = n)
Z <- (a * b) * matrix(sample(0 : 12, n, replace = TRUE), nrow = n) - G
data.frame(X, Y, Z)
}
model <- lm(Y ~ 0 + X + Z, data = f1(n, a, b, c, d, e))
varpredict <- model$fitted.values
square_res <- model$residuals ^ 2
list(f1(n, a, b, c, d, e), f2(n, a, b))
}
I’ve cleaned up the code a bit and I hope you’ll agree that it is more readable this way — it is also more efficient, since it avoids recomputing the initial model over and over again. Apart from that I’ve followed a few simple rules: use consistent spacing, don’t use gratuitous abbreviations (T instead of TRUE), use the appropriate functions to avoid redundant code (e.g. the creation of the data frames), no unnecessary use of returns.
But fundamentally I still have no good idea what it does since the variable names don’t provide any useful information. The most impactful improvement for readability is therefore the choice of better variable names.
Related
Using Octave's symbolic package, I define a symbolic function of t like this:
>> syms a b c d t real;
>> f = poly2sym([a b c], t) + d * exp(t)
f = (sym)
2 t
a⋅t + b⋅t + c + d⋅ℯ
I also have another function with known coefficients:
>> g = poly2sym([2 3 5], t) + 7 * exp(t)
g = (sym)
2 t
2⋅t + 3⋅t + 7⋅ℯ + 5
I would like to solve f == g for the coefficients a, b, c, d such that the equation holds for all values of t. That is, I simply want to equate the coefficients of t^2 in both equations, and the coefficients of exp(t), etc. I am looking for this solution:
a = 2
b = 3
c = 5
d = 7
When I try to solve the equation using solve, this is what I get:
>> solve(f == g, a, b, c, d)
ans = (sym)
t 2 t
-b⋅t - c - d⋅ℯ + 2⋅t + 3⋅t + 7⋅ℯ + 5
───────────────────────────────────────
2
t
It solves for a in terms of b, c, d, t. This is understandable since in essence there is no difference between the variables b, c and t. But I was wondering if there was a method to somehow separate the terms (using their symbolic form w. r. t. the variable t) and solve the resulting system of linear equations on a, b, c, d.
Note: The function I wrote here is a minimal example. What I am really trying to do is to solve a linear ordinary differential equation using the method of undetermined coefficients. For example, I define something like y = a*exp(-t) + b*t*exp(-t), and solve for diff(y, t, t) + diff(y,t) + y == t*exp(-t). But I believe solving the problem with simpler functions will lead me to the right direction.
I have found a terribly slow and dirty method to get the job done. The coefficients have to be linear in a, b, ... though.
The idea is to follow these steps:
Write the equation in f - g form (which equals zero)
Use expand() to separate the terms
Use children() to get the terms in the equation as a symbolic vector
Now that we have the terms in a vector, we can find those that are the same function of t and add their coefficients together. The way I checked this was by checking if the division of two terms had t as a symbolic variable
For each term, find other terms with the same function of t, add all these coefficients together, save the obtained equation in a vector
Pass the vector of created equations to solve()
This code solves the equation I wrote in the note at the end of my question:
pkg load symbolic
syms t a b real;
y = a * exp(-t) + b * t * exp(-t);
lhs = diff(y, t, t) + diff(y, t) + y;
rhs = t * exp(-t);
expr = expand(lhs - rhs);
chd = children(expr);
used = false(size(chd));
equations = [];
for z = 1:length(chd)
if used(z)
continue
endif
coefficients = 0;
for zz = z + 1:length(chd)
if used(zz)
continue
endif
division = chd(zz) / chd(z);
vars = findsymbols(division);
if sum(has(vars, t)) == 0 # division result has no t
used(zz) = true;
coefficients += division;
endif
endfor
coefficients += 1; # for chd(z)
vars = findsymbols(chd(z));
nott = vars(!has(vars, t));
if length(nott)
coefficients *= nott;
endif
equations = [equations, expand(coefficients)];
endfor
solution = solve(equations == 0);
let rec f (l: int list) : int * int =
begin match l with
| [] -> (0,0)
| [x] (x,x)
| x::y::tl -> let (a,b) = f tl in
(x + a, y + b)
end
let r = f [2;3;4;5;6]
I'm thinking that the answer would compute to r = (6,6) because if you keep calling the recursive function on the tail, you'll end up with the last item in the list, thus it will match to the second case but I have no idea if this is correct or why this is the case. Really, I don't understand the use of let (a,b) = f tl in (x + a, y + b).
I'll try to explain let (a, b) = f tl in (x + a, y + b). Maybe that will help.
The pattern for this case is x :: y :: tl. So this means that tl represents the tail of the tail of the list. I.e. it represents the list after you remove the two elements at the front.
Along these same lines, x represents the first element of the list and y represents the second element.
The recursive call to f is going to return whatever f returns for tl, which is what you're trying to figure out. This will be a pair of numbers, as you can tell from the pattern (a, b).
The result of the whole expression (which is the result of f except when the list is very short) is (x + a, y + b). In other words, it adds the first element of the list to the first number of the pair and the second element of the list to the second element of the pair.
I'm trying to put the last element of a list in the front of the list while keeping the rest of the elements in the same order N times. I can do it once with this function, but I want to add another parameter to the function so that the function in called N times.
Code:
fun multcshift(L, n) =
if null L then nil
else multcshift(hd(rev L)::(rev(tl(rev L))));
Thanks
To make the parameter n work, you need recursion. You need a base case at which point the function should no longer call itself, and a recursive case where it does. For this function, a good base case would be n = 0, meaning "shift the last letter in front 0 times", i.e., return L without modification.
fun multcshift(L, n) =
if n = 0
then L
else multcshift( hd(rev L)::rev(tl(rev L)) , n - 1 )
The running time of this function is terrible: For every n, reverse the list three times!
You could save at least one of those list reversals by not calling rev L twice. E.g.
fun multcshift (L, 0) = L
| multcshift (L, n) =
let val revL = rev L
in multcshift ( hd revL :: rev (tl revL) , n - 1 ) end
Those hd revL and rev (tl revL) seem like useful library functions. The process of applying a function to its own output n times seems like a good library function, too.
(* Return all the elements of a non-empty list except the last one. *)
fun init [] = raise Empty
| init ([_]) = []
| init (x::xs) = x::init xs
(* Return the last element of a non-empty list. *)
val last = List.last
(* Shift the last element of a non-empty list to the front of the list *)
fun cshift L = last L :: init L
(* Compose f with itself n times *)
fun iterate f 0 = (fn x => x)
| iterate f 1 = f
| iterate f n = f o iterate f (n-1)
fun multcshift (L, n) = iterate cshift n L
But the running time is just as terrible: For every n, call last and init once each. They're both O(|L|) just as rev.
You could overcome that complexity by carrying out multiple shifts at once. If you know you'll shift one element n times, you might as well shift n elements. Shifting n elements is equivalent to removing |L| - n elements from the front of the list and appending them at the back.
But what if you're asked to shift n elements where n > |L|? Then len - n is negative and both List.drop and List.take will fail. You could fix that by concluding that any full shift of |L| elements has no effect on the result and suffice with n (mod |L|). And what if n < 0?
fun multcshift ([], _) = raise Empty
| multcshift (L, 0) = L
| multcshift (L, n) =
let val len = List.length L
in List.drop (L, len - n mod len) #
List.take (L, len - n mod len) end
There are quite a few corner cases worth testing:
val test_zero = (multcshift ([1,2,3], 0) = [1,2,3])
val test_empty = (multcshift ([], 5); false) handle Empty => true | _ => false
val test_zero_empty = (multcshift ([], 0); false) handle Empty => true | _ => false
val test_negative = (multcshift ([1,2,3,4], ~1) = [2,3,4,1])
val test_nonempty = (multcshift ([1,2,3,4], 3) = [2,3,4,1])
val test_identity = (multcshift ([1,2,3,4], 4) = [1,2,3,4])
val test_large_n = (multcshift [1,2,3,4], 5) = [4,1,2,3])
val test_larger_n = (multcshift [1,2,3,4], 10) = [3,4,1,2])
I'm looking for a functional way to implement this:
list = [a b c d e f]
foo(list, 3) = [[a d] [b e] [c f]]
A potential solution is:
foo(list,spacing) = zip(goo(list,spacing))
Where, for example,
goo([a b c d e f],3) = [[a b c] [d e f]]
What is foo and goo usually called, so I can look for existing solutions rather than reinventing the wheel?
Notes: Rather than trying to explain with words, I've just shown examples that'll be hopefully much easier to get. Arbitrary syntax for broader understanding.
You can use partition:
(partition 3 '[a b c d e f])
=> ((a b c) (d e f))
(partition 2 '[a b c d e f])
=> ((a b) (c d) (e f))
Edit:
(apply map list (partition 3 '[a b c d e f]))
=> ((a d) (b e) (c f))
I do not think there is a built-in function for that. It's easy and nice to implement.
I know you do not want the implementation, but one of the tags was Haskell so maybe you want to see this
p :: Int -> [a] -> [[a]]
p n xs = [ [x | (x ,y) <- ys , y `mod` n == i] | i <- [0 .. n - 1] , let ys = zip xs [0 .. ]]
That is pretty functional.
Your goo function is drop with flipped arguments. Given that, you can implement foo almost like you say in your question:
let foo list spacing = zip list (drop spacing list)
This still doesn't exactly give the result you need though, but close:
Prelude> foo "abcdef" 3
[('a','d'),('b','e'),('c','f')]
EDIT:
Reading more carefully, your goo function is splitAt with flipped arguments. Given that, foo can be defined like this:
let foo list spacing = (uncurry zip) $ splitAt spacing list
Which is the same as:
let foo list spacing = let (left, right) = splitAt spacing list
in zip left right
Eventually what I want is what x represents:
let x = (something, (myfunc1 para1));;
so that when calling x, I get a tuple, but when calling (snd x) para, I will get a return value of myfunc1 para.
What I'm trying is like this:
let myfunc2 para1 para2 =
let myfunc1 para2 = ... in
( (fst para1), (myfunc1 para2) );;
And I want to call myfunc2 like this:
let x = myfunc2 para1 to get what I described above. However, what I get is just a function which when called with para1 will return a regular tuple, not a (something, function) tuple
You have a useless para2 parameter in your definition. The correct way is:
let myfunc2 para1 =
let x = ... in
let myfunc1 para2 = ... in
( x, myfunc1 );;
But it would help if we could speak about a concrete example. You are misunderstanding something obvious, but I do not know what.
Here is a concrete example. Suppose we want a function f which accepts a number n and returns a pair (m, g) where m is the square of n and g is a function which adds n to its argument:
let f n =
let m = n * n in
let g k = n + k in
(m, g)
Or shorter:
let f n = (n * n, fun k => n + k)
Now to use this, we can do:
let x = f 10 ;;
fst x ;; (* gives 100 *)
snd x ;; (* gives <fun> *)
snd x 5 ;; (* gives 15, and is the same thing as (snd x) 5 *)
Now let us consider the following bad solution in which we make the kind of mistake you have made:
let f_bad n k =
let m = n * n in
let g k = n + k in
(m, g k)
Now f_bad wants two arguments. If we give it just one, we will not get a pair but a function expecting the other argument. And when we give it that argument, it will return a pair of two integers because (m, g k) means "make a pair whose first component is the integer m and the second component is g applied to k, so that is an integer, too."
Another point worth making is that you are confusing yourself by calling two different things para2. In our definition of f_bad we also confuse ourselves by calling two different things k. The k appearing in the definition of g is not the same as the other k. It is better to call the two k's different things:
let f_bad n k1 =
let m = n * n in
let g k2 = n + k2 in
(m, g k1)
Now, does that help clear up the confusion?