How to repeat a loop? - r

this is my first loop:
e13 = rnorm(122)
y = 0*e13
y[1]=2
y[2]=5
for(k in 3:length(e13)) {
y[k]= 0.6 * y[k-1] + e13[k]
}
Now I want to repeat it 10 times to find another 10 values for the same y[k], like, 10 different y[1], 10 different y[2] and so on.
And then I need ot use these numbers for another functions.
I tried it but didn't work
for (i in 1:20) {
for(k in 3:length(e13)) {
y[k,i] = 0.6 * y[k-1,i] + e13[k,i]
}
}
it says "wrong number of dimensions"
Now my code is like that:
e13 = rnorm(122)
y <- array(0, c(length(e13), 20))
y[1, ] <- 2
y[2, ] <- 5
i<-c(1:20)
y[1]=2
y[2]=5
for (i in 1:20) {
for(k in 3:length(e13)) {
y[k,i] = 0.6 * y[k-1,i] + e13[k,i]
}
}
but the problem now is the dimension of e13 (a normal distribution), im going to try to set the correct dimension

You should take a good look at some introductory R texts (e.g., this, this, this, and others). The comments on your question were guiding you to solve this yourself. You're almost there, but here is how I would do what you're attempting.
e13 <- matrix(rnorm(122*20), ncol=20)
y <- array(0, dim(e13))
y[1, ] <- 2
y[2, ] <- 5
for (i in 1:ncol(y)) {
for(k in 3:nrow(y)) {
y[k, i] <- 0.6 * y[k-1, i] + e13[k, i]
}
}

Here is a simple solution although cbind will slow you down with larger datasets. If need more speed you don't need to specify 2 dimensions you can specify datamatrix as a vector of length length(e13)*(how many times you want to repeat) In this case length(e13)*20. Then in your second loop you would have y placed further along the length of datamatrix each repetition of the loop. Its sometimes simpler to do this and you turn it into a matrix at the end if you want using matrix.
datamatrix=NULL
for(n in 1:20) {
e13 = rnorm(122)
y = 0*e13
y[1]=2
y[2]=5
for(k in 3:length(e13)) {
y[k]= 0.6 * y[k-1] + e13[k]
}
datamatrix=cbind(datamatrix,y)}

Related

Understanding Breakpoint function: how for loops work inside functions

I have the following exercise to be solved in R. Under the exercise, there is a hint towards the solution.
Exercise: If there are no ties in the data set, the function above will produce breakpoints with h observations in the interval between two consecutive breakpoints (except the last two perhaps). If there are ties, the function will by construction return unique breakpoints, but there may be more than h observations in some intervals.
Hint:
my_breaks <-function(x, h = 5) {
x <-sort(x)
breaks <- xb <- x[1]
k <- 1
for(i in seq_along(x)[-1])
{if(k<h)
{k <- k+1}
else{
if(xb<x[i-1]&&x[i-1]<x[i])
{xb <- x[i-1]
breaks <-c(breaks, xb)
k <- 1
}
}
}
However, I am having a hard time understanding the above function particularly the following lines
for(i in seq_along(x)[-1])
{if(k<h)
{k <- k+1}
Question:
How is the for loop supposed to act in k if k is previously defined as 1 and i is different than k? How are the breakpoints chosen according to the h=5 gap if the for loop is not acting on x? Can someone explain to me how this function works?
Thanks in advance!
First, note that your example is incomplete. The return value and the final brace are missing there. Here is the correct version.
my_breaks <-function(x, h = 5) {
x <- sort(x)
breaks <- xb <- x[1]
k <- 1
for(i in seq_along(x)[-1]){
if(k<h) {
k <- k+1
} else {
if(xb<x[i-1]&&x[i-1]<x[i]){
xb <- x[i-1]
breaks <-c(breaks, xb)
k <- 1
}
}
}
breaks
}
Let's check if it works.
my_breaks(c(1,1,1:5,8:10), 2)
#[1] 1 2 4 8
my_breaks(c(1,1,1:5,8:10), 5)
#[1] 1 3
As you can see, everything is fine. And what is seq_along(x)[-1]? We could write this equation as 2:length(x). So the for loop goes through each element of the vector x in sequence, skipping the first element.
What is the k variable for? It counts the distance to take into account the h parameter.

User defined function within for-loops

I am working on a project in which I am simulating 8 classroom social networks over 6 weeks, so 30 iterations. Students will nominate each other based on a number of factors, and I plan to simulate a number of conditions in which I remove or add some of these factors to the simulation. In other words, I'm going to be repeating a lot of code, so I'd rather use functions rather than cutting and pasting where ever possible.
Right now, I'm trying to create a function that adjusts the probability of one student selecting another based on the similarity of their emotions. When I include it in a set of nested for for loops, this works just fine:
num_students <- 5
names_students <- letters[1:num_students]
student_emotion <- sample(round(runif(5, min = -5, max = 5), digits = 1))
student_emotion_df <- cbind.data.frame(names_students, student_emotion)
probs <- rep(1/num_students, 5)
row_prob <- vector(length = 5)
for(i in 1:num_students){
for(q in 1:num_students){
if(abs(student_emotion[i]-student_emotion[q]) >= 0 &
abs(student_emotion[i]-student_emotion[q]) <= .5){
row_prob[q] <- 1*probs[q]
} else if(abs(student_emotion[i]-student_emotion[q]) > .5 &
abs(student_emotion[i]-student_emotion[q]) <= 1) {
row_prob[q] <- .75 * probs[q]
}
else {
row_prob[q] <- .5 * probs[q]
}
}
}
The row_prob object is a vector of probabilities a student i, in the column, will select student q, in the rows.
I've created a user-defined function based on the same code, and that works:
emotion_difference_fun <- function(probs){
for(q in 1:num_students){
if(abs(student_emotion[i]-student_emotion[q]) >= 0 &
abs(student_emotion[i]-student_emotion[q]) <= .5){
row_prob[q] <- 1*probs[q]
} else if(abs(student_emotion[i]-student_emotion[q]) > .5 &
abs(student_emotion[i]-student_emotion[q]) <= 1) {
row_prob[q] <- .75 * probs[q]
}
else {
row_prob[q] <- .5 * probs[q]
}
}
return(row_prob)
}
emotion_difference_fun(probs)
But when I try to embed that function within the for loop iterating through the columns, row_prob returns as an empty vector:
for(i in 1:num_students){
emotion_difference_fun(probs)
}
Any thoughts on how I can get this to work?
Thanks for any help you're able to offer.
If I understood your question properly, then you need to assign the results in your last 'for' loop:
for(i in 1:num_students){
if(i == 1) out <- NULL
out <- c(out, emotion_difference_fun(probs))
}
out
Is that what you are looking for?
What I am unclear about though, is why in your second code section you are not looking for a 5*5 matrix. Eventually, when running that code, it doesn't matter that you did it for i = 5 students, because it will only save in row_prob your last iteration (student = 5).
You can use replicate to repeat the function emotion_difference_fun for num_students.
result <- replicate(num_students, emotion_difference_fun(probs))
You can also set simplify = FALSE to get output as list.
result <- replicate(num_students, emotion_difference_fun(probs),simplify = FALSE)

why my sum() function don't work for the matrix operations in R

The following is my R code, I want the tx[1, 1] = 1*2^1 + 4*5^2 + 7*8^3, tx[1, 2] = 4*5 + 7*8^2, tx[1, 3] = 7*8,but it only including 7*8^3 for tx[1, 1] and 7*8^2 for tx[1, 2]. The other elements in the tx matrix only include the last term in the sum operation too. So,could anyone tell me how to rectify my code to have a correct output? Thanks in advance!
A <- matrix(c(1:9),ncol=3)
B <- matrix(c(2:10),ncol=3)
tx<-matrix(rep(NA,3*3),3,3)
for(j in 1:3)
{
for(i in 1:3)
{
for(k in 1:3-i+1)
{
tx[j,i]<-sum(A[j,k+i-1]*(B[j,k+i-1])^k)
}
}
}
Right now it's not summing the results of each loop, just saving out whatever the last loop result happens to be. Try this instead:
A <- matrix(c(1:9),ncol=3)
B <- matrix(c(2:10),ncol=3)
tx<-matrix(rep(0,3*3),3,3)
for(j in 1:3)
{
for(i in 1:3)
{
for(k in 1:3-i+1)
{
tx[j,i]<-tx[j,i] + (A[j,k+i-1]*(B[j,k+i-1])^k)
}
}
}
I initialized the tx matrix to start at 0 and added the result of each loop to the existing total, so that it increments over each loop.

Bubble sort using R language?

I am new in programming, and I just start learning R language. I am trying to do a bubble sort, but it shows the following error message. Can anyone help me solve the problem?
x <-sample(1:100,10)
n <- length(x)
example <- function(x)
{
for (i in 1:n-1)
{
while (x[i] > x[i+1])
{
temp <- x[i+1]
x[i+1] <- x[i]
x[i] <- temp
}
i <- i+1
}
}
example(x)
Error in while (x[i] > x[i + 1]) { : argument is of length zero
x<-sample(1:100,10)
example <- function(x){
n<-length(x)
for(j in 1:(n-1)){
for(i in 1:(n-j)){
if(x[i]>x[i+1]){
temp<-x[i]
x[i]<-x[i+1]
x[i+1]<-temp
}
}
}
return(x)
}
res<-example(x)
#input
x
#output
res
It is working fine with little modification of your code. In 'R' it is better to use sort() function.
x <-sample(1:100,10)
x
res<-sort(x)
res
You have some inaccuracies in your algorithm of sorting. I've made changes to make it work.
set.seed(1)
x <-sample(1:100,10)
x
# [1] 27 37 57 89 20 86 97 62 58 6
example <- function(x)
{
n <- length(x) # better insert this line inside the sorting function
for (k in n:2) # every iteration of the outer loop bubbles the maximum element
# of the array to the end
{
i <- 1
while (i < k) # i is the index for nested loop, no need to do i < n
# because passing j iterations of the for loop already
# places j maximum elements to the last j positions
{
if (x[i] > x[i+1]) # if the element is greater than the next one we change them
{
temp <- x[i+1]
x[i+1] <- x[i]
x[i] <- temp
}
i <- i+1 # moving to the next element
}
}
x # returning sorted x (the last evaluated value inside the body
# of the function is returned), we can also write return(x)
}
example(x)
# [1] 6 20 27 37 57 58 62 86 89 97
BTW, R language has a lot of functions and methods for doing things. This example function can be a learning example, but I advice to use existing function sort for solving real problems.
In R language you should try to avoid loops and make usage of vectorized functions to make the code faster.
It gives you that error message because he cannot compare a value that is out of his bounds which is the case for you at (x[i] > x[i + 1]). Try this if you want to sort your array in a decreasing order:
for (i in 1:n){
j = i
while((j>1)){
if ((X[j]> X[j-1])){
temp = X[j]
X[j] = X[j-1]
X[j-1] = temp
}
j = j-1
}
}
For an increasing order you just have to switch around the > sign in the while loop.

R: creating a matrix with unknown number of rows

I have written the code below to generate a matrix containing what is, to me, a fairly complex pattern. In this case I determined that there are 136 rows in the finished matrix by trial and error.
I could write a function to calculate the number of matrix rows in advance, but the function would be a little complex. In this example the number of rows in the matrix = ((4 * 3 + 1) + (3 * 3 + 1) + (2 * 3 + 1) + (1 * 3 + 1)) * 4.
Is there an easy and efficient way to create matrices in R without hard-wiring the number of rows in the matrix statement? In other words, is there an easy way to let R simply add a row to a matrix as needed when using for-loops?
I have presented one solution that employs rbind at each pass through the loops, but that seems a little convoluted and I was wondering if there might be a much easier solution.
Sorry if this question is redundant with an earlier question. I could not locate a similar question using the search feature on this site or using an internet search engine today, although I think I have found a similar question somewhere in the past.
Below are 2 sets of example code, one using rbind and the other where I used trial and error to set nrow=136 in advance.
Thanks for any suggestions.
v1 <- 5
v2 <- 2
v3 <- 2
v4 <- (v1-1)
my.matrix <- matrix(0, nrow=136, ncol=(v1+4) )
i = 1
for(a in 1:v2) {
for(b in 1:v3) {
for(c in 1:v4) {
for(d in (c+1):v1) {
if(d == (c+1)) l.s = 4
else l.s = 3
for(e in 1:l.s) {
my.matrix[i,c] = 1
if(d == (c+1)) my.matrix[i,d] = (e-1)
else my.matrix[i,d] = e
my.matrix[i,(v1+1)] = a
my.matrix[i,(v1+2)] = b
my.matrix[i,(v1+3)] = c
my.matrix[i,(v1+4)] = d
i <- i + 1
}
}
}
}
}
my.matrix2 <- matrix(0, nrow=1, ncol=(v1+4) )
my.matrix3 <- matrix(0, nrow=1, ncol=(v1+4) )
i = 1
for(a in 1:v2) {
for(b in 1:v3) {
for(c in 1:v4) {
for(d in (c+1):v1) {
if(d == (c+1)) l.s = 4
else l.s = 3
for(e in 1:l.s) {
my.matrix2[1,c] = 1
if(d == (c+1)) my.matrix2[1,d] = (e-1)
else my.matrix2[1,d] = e
my.matrix2[1,(v1+1)] = a
my.matrix2[1,(v1+2)] = b
my.matrix2[1,(v1+3)] = c
my.matrix2[1,(v1+4)] = d
i <- i+1
if(i == 2) my.matrix3 <- my.matrix2
else my.matrix3 <- rbind(my.matrix3, my.matrix2)
my.matrix2 <- matrix(0, nrow=1, ncol=(v1+4) )
}
}
}
}
}
all.equal(my.matrix, my.matrix3)
If you have some upper bound on the size of the matrix,
you can create a matrix
large enough to hold all the data
my.matrix <- matrix(0, nrow=v1*v2*v3*v4*4, ncol=(v1+4) )
and truncate it at the end.
my.matrix <- my.matrix[1:(i-1),]
This is the generic form to do it. You can adapt it to your problem
matrix <- NULL
for(...){
...
matrix <- rbind(matriz,vector)
}
where vector contains the row elements
I stumbled upon this solution today: convert the matrix to a data.frame. As new rows are needed by the for-loop those rows are automatically added to the data.frame. Then you can convert the data.frame back to a matrix at the end if you want. I am not sure whether this constitutes something similar to iterative use of rbind. Perhaps it becomes very slow with large data.frames. I do not know.
my.data <- matrix(0, ncol = 3, nrow = 2)
my.data <- as.data.frame(my.data)
j <- 1
for(i1 in 0:2) {
for(i2 in 0:2) {
for(i3 in 0:2) {
my.data[j,1] <- i1
my.data[j,2] <- i2
my.data[j,3] <- i3
j <- j + 1
}
}
}
my.data
my.data <- as.matrix(my.data)
dim(my.data)
class(my.data)
EDIT: July 27, 2015
You can also delete the first matrix statement, create an empty data.frame then convert the data.frame to a matrix at the end:
my.data <- data.frame(NULL,NULL,NULL)
j <- 1
for(i1 in 0:2) {
for(i2 in 0:2) {
for(i3 in 0:2) {
my.data[j,1] <- i1
my.data[j,2] <- i2
my.data[j,3] <- i3
j <- j + 1
}
}
}
my.data
my.data <- as.matrix(my.data)
dim(my.data)
class(my.data)

Resources