Using two for loops to fill one empty matrix by rows - r

I'm trying to do a forecast analysis with some error measures. My question relates more to a technical Problem.
Here is a short example:
Im studying error measures regarding to the forecast length (h) and the k-step-forecast. I want to compare forecast lengths of 12, 18 and 24 months.
h<-c(12,18,24)
And for that lengths I'm comparing the 1-12 step ahead forecasts.
k <- c(1:12)
I've written two functions:
The first one (foo) is computing the hole code and the second one (forecast_analysis) is doing my forecast Analysis.
foo <- function(series, k, h){
Outfinal <- matrix(nrow = length(h)*length(k), ncol = 5)
for(i in 1:length(h)){
for(j in 1:length(k)){
Outfinal[j,] <- forecast_analysis(series,k[j],h[i])
}
}
return(Outfinal)
}
my Problem is, that I couldnt find a way to fill the Matrix by rows like this:
h k measure 1 measure 2 measure3 measure 4 measure 5
12 1
12 2
12 3
. .
. .
. .
24 10
24 11
24 12
So, first I want to fill the Matrix for a fixed value of h for all values of k. And then repeating this for all values of h. I hope ure understanding my Problem.
I know that apply functions would be more efficient here. But I'm not yet able to do so.

You can build a table of all h x k combinations plus a result using expand.grid.
This code should get you started
dummy_forecast <- function(h, k) 42
h<-c(12,18,24)
k <- 1:12 # no need for the c function here
combinations <- expand.grid(h = h, k = k, forecast = NA)
for (row in seq_along(combinations$h)) {
combinations[row, "forecast"] <-
with(combinations[row,], dummy_forecast(h, k))
}
If you return more than one value from your function, you need to assign to more than one column in combinations[row,...], but otherwise it should work.
Update
To handle a function that returns more than one value, do something like this:
dummy_forecast <- function(h, k) rep(42, 5)
result <- matrix(nrow = length(h) * length(k), ncol = 7)
combinations <- expand.grid(h = h, k = k)
for (row in seq_along(combinations$h)) {
result[row,] <- with(combinations[row,], c(h, k, dummy_forecast(h, k)))
}

Related

Using for loops to run through two different sequences of values in an equation

New to R! My goal is to simultaneously change the values of two variables (i and j) in an equation, using two different sequences of numbers (x and y). I want to move through the for loops at the same time in order to go through each sequence of numbers once. Here's the code I've written so far:
A <- -13
B <- -21
x <- seq(from = 0, to = 10)/10
y <- seq(from = 10, to = 0)/10
for(i in x){
for(j in y){
SOM <- (A*i) + (B*j)
print (SOM)
}
}
I want i to go from 0 to 1 while j goes from 1 to 0, resulting in a list of 11 numbers that are the product of (A * i) + (B * j). For example, when i = .2 and j is .8, SOM = -19.4. Right now, I think the code goes through each for loop separately or only for a part of the equation, which isn't what I want. Sorry in advance if there is an easy/obvious solution or if this isn't clear, I've never used R/programming for more than graphing data and would greatly appreciate any and all comments!
These are arithmetic operations that are vectorized. There is no need for a loop if the intention is to get the output with length equal to that of the length of 'x' or 'y' (both considered to be of same length)
A * x + B * y
Take advantage of the fact that y = 1-x:
B <- -21
x <- seq(from = 0, to = 10)/10
for(i in x){
SOM <- (A*i) + (B*(1-i))
print (SOM)
}

What argument to give to the function to return results for more than one value?

I need to simulate the probabilities that are computed using the function transitionProbability1D from isingLenzMC package. I want to simulate them for 10 values of bF at once and receive a vector of results but still receive only one number and I dont know why. Here is my code
N <- 100
conf0 <- genConfig1D(N)
conf1 <- flipConfig1D(conf0)
# transition probability at J=H=1/kBT=1.0, 1= p-ty metropolis 2=glauber
bF <- 1:10
J <- h <- rep(1,10)
# HERE IT DOESNT WORK EVEN THOUGHT bF IS A VECTOR
transitionProbability1D(bF, conf0, conf1, J, h, 1)
>> 0.298615
You might want to look at how to vectorize a function.
On your example, the following would probably give you what you expect:
library(isingLenzMC)
N <- 100
conf0 <- genConfig1D(N)
conf1 <- flipConfig1D(conf0)
# transition probability at J=H=1/kBT=1.0, 1= p-ty metropolis 2=glauber
bF <- 1:10
# Here I changed these inputs to single values
J <- h <- 1
# HERE IT DOESNT WORK EVEN THOUGHT bF IS A VECTOR
transitionProbability1D(bF, conf0, conf1, J, h, 1)
# Vectorize on the first argument
transitionProbability1D_vectorized <- Vectorize(transitionProbability1D, vectorize.args = "ikBT")
# Now there are as many results as input values
transitionProbability1D_vectorized(ikBT = bF, x = conf0, xflip = conf1, J = J, H = h, probSel = 1)
You could also use a (for) loop!

Trying to understand how some function works

I was given a task to write a function, which I name: my_mode_k.
The input is consisted of two variables:
(x, k)
as x, is a vector of natural numbers with the length of n. the greatest object of x can be k, given that k < n.
my_mode_k output is the highest frequency object of x. if there's more then one object in the vector that are common in x the same number of times - then the function will output the minimum object between them.
for example:
my_mode_k(x = c(1, 1, 2, 3, 3) , k =3)
1
This is code I wrote:
my_mode_k <- function(x, k){
n <- length(x)
x_lemma <- rep(0, k)
for(i in 1:n){
x_lemma[i] < x_lemma[i] +1
}
x_lem2 <- 1
for( j in 2:k){
if(x_lemma[x_lem2] < x_lemma[j]){
x_lem2 <- j
}
}
x_lem2
}
which isn't working properly.
for example:
my_mode_k(x = c(2,3,4,3,2,2,5,5,5,5,5,5,5,5), k=5)
[1] 1
as the function is supposed to return 5.
I don't understand why and what is the intuition to have in order to even know if a function is working properly (It took me some time to realize that it's not executing the needed task) - so I could fix the mistake in it.
Here are a few steps on how you can achieve this.
k <- 5
input <- c(2,3,4,3,3,3,3,3,3,3,2,2,5,5,5,5,5,5,5,5)
# Calculate frequencies of elements.
tbl <- table(input[input <= k])
# Find which is max. Notice that it returns the minimum of there is a tie.
tbl.max <- which.max(tbl)
# Find which value is your result.
names(tbl.max)
input <- c(2,2,3,3,3,5,5,5)
names(which.max(table(input[input <= k])))
# 3
input <- c(2,2,5,5,5,3,3,3)
names(which.max(table(input[input <= k])))
# 3

Without calling polym(), how can I count the number of interactions it will return?

How can I count number of interactions poly will return?
If I have two variables, then the number of interactions poly will return in function of degree is given by:
degree <- 2
dim(poly(rnorm(10), rnorm(10), degree = degree))[2]
That is the same as:
(degree^2+3*degree)/2
Is there anyway to count the number of interactions depending on the number of degree and variables (in case I use more than two)?
Math result from combinations
Suppose you have p variables, the number of interactions associated with degree d is computed by:
fd <- function (p, d) {
k <- choose(p, d)
if (d > 1) k <- k + p * sum(choose(p-1, 0:(d-2)))
return(k)
}
The function poly (actually polym in this case), with p input variables and a degree = D, will construct interactions from degree = 1 up to degree = D. So the following function counts it:
fD <- function (p, D) {
if (D < 1) return(0)
component <- sapply(1:D, fd, p = p)
list(component = component, ncol = sum(component))
}
The entry component gives the number of interaction for each degree from 1 to D, and ncol component gives total number of interactions.
A quick test:
a <- runif(50)
b <- runif(50)
c <- runif(50)
d <- runif(50)
X <- poly(a, b, c, d, degree = 3)
ncol(X)
# 34
fD(4, 3)
# component
# [1] 4 10 20
#
# ncol
# [1] 34
How R does this?
The first few lines of the source code for polym explains how R addresses this problem. An expand.grid is first called to get all possible interactions, then a rowSums is called to compute the degree of all available interactions. Finally, a filter is applied to retain only interactions terms with degree between 1 and D.
More than three years later I had to work with degree >=3 polynomials. Unfortunately #李哲源 solution fails for degrees larger than 3. I could, however, build two solutions:
Expand Grid Solution
This method emulates polym original behavior, which is not very elegant for our purposes but is a natural benchmark.
expand_grid_solution <- function(nd, degree){
z <- do.call(expand.grid, c(rep.int(list(0:degree), nd),
KEEP.OUT.ATTRS = FALSE))
s <- rowSums(z)
ind <- 0 < s & s <= degree
z <- z[ind, , drop = FALSE]
s <- s[ind]
return(length(s))
}
Combination with repetion solution
combination_with_repetition <- function(n, r){
factorial(r+n-1)/(factorial(n-1)*factorial(r))
}
poly_elements <- function(n, d) {
x <- sapply(1:d, combination_with_repetition, n = n)
return(sum(x))
}
A quick test:
mapply(expand_grid_solution, c(2,2,2,3,3,3,4), c(2,3,4,2,3,4,4))
#[1] 5 9 14 9 19 34 69
mapply(poly_elements, c(2,2,2,3,3,3,4), c(2,3,4,2,3,4,4))
#[1] 5 9 14 9 19 34 69

creating a loop with combinatorics in r

I'm trying to create a combinatoric function in R and it is dependent on what number I set a variable to. This tells me I would have to use a loop. Here is an example of the equation that I am trying to create and I filled in the numbers given in the example:
The equation changes depending on what number if put in for b. I'm guessing I would need a sum and a loop.
comb = function(n, x) {return(factorial(n) / (factorial(x) * factorial(n-x)))}
a <- 8
b <- 4
c <- 0:b
p <- 0.05
total = function(n) {
return(((comb(a,b + c)*comb((n-a), (c - b)*(-1))/comb(n,a) - 0.05)
}
I will then find out what n is equal too by setting it equal to 0.
You don't need to define comb -- this is provided by the function choose in base R. I think all you need is to combine choose and sum to compute your numerator:
total <- function(n) {
sum(choose(a, b:(2*b)) * choose(n-a, b:0)) / choose(n, a) - p
}
# Plot total(n) for various n values:
a <- 8
b <- 4
p <- 0.05
n <- 20:100
plot(n, sapply(n, total))
For these parameters, total(n) crossed 0 between n=36 and n=37.

Resources