I feel dumb asking such a simple question, but I can't seem to find a way, although I'm sure there are plenty of ways. The easiest way to explain my problem might be to show an example, I've got some program I want applied.
FUN<- function(v1, v2, v3){
n=length(v1)
res <- vector()
for (i in 1:n){
if(v1[i]>v2[i]) (res[i] <- v3[i+2])
else(res[i] <- v1[i+2])}
return(res)}
The input is two vectors and a matrix, all being the same length
matrix <- matrix(runif(30),ncol=3)
v2 <- runif(10)
v3 <- rnorm(10)
So that when I run the a for loop including the function I can do the program i times and each time the output goes to a different column in a matrix. I've tried something like and several similar "versions", but with no luck.
for (i in 1:3)(
r <- matrix()
r[re,i] <- re <- FUN(matrix[,i], v2, v3))
Can anyone please help me?
r <- matrix(ncol=3, nrow=10)
for (i in 1:3) {
r[,i] <- FUN(matrix[,i], v2, v3)
}
Declare your matrix outside the loop, and just fill in one column per loop iteration.
(This assumes that FUN is correct; even if it is, there are better ways to do what it does. And other ways to do what you want other than a loop.)
Related
I have never used for loops before and I would like to use it for my data. However, I still don't know how to use it properly. Could anyone tell me how to use for loops correctly?
For item 1 to 9
the results I wanted to get
real<lower=0>l1_0+l1_11
real<lower=0>l2_0+l2_11
real<lower=0>l3_0+l3_11
..
real<lower=0>l9_0+l9_11
For item 10 to 18
real<lower=0>l10_0+l10_12
real<lower=0>l11_0+l11_12
real<lower=0>l12_0+l12_12
..
real<lower=18>l18_0+l18_12
What I tried to do..
for(i in 1:9){
i=l[i]"_0"+l[i]"_11"
print(paste("real<lower=0>",i))
}
for (i in 1:9){
i<-paste('l',i,'_0',sep='')
print(paste("real<lower=0>",i)
}
Assuming you have no background in programming and just want to know how to use the for loop. I have created a very simple data-frame and will do something easy.
I want to have the sum of each row in the data-frame (luckily we also have the apply family to do this simply).
df <- data.frame(x=c(1,4,2,6,7,1,8,9,1),
y=c(4,7,2,8,9,1,9,2,8))
This is the example shown everywhere, which is highly unsatisfactory.
for(i in 1:10){
print(i)
}
Only print the example of the sum of each row.
for(i in 1:nrow(df)){
print(df$x[i]+df$y[i])
}
This is the part often horrible explained everywhere (I do not get why? Perhaps I just used the wrong searching terms/keywords?). Fortunately, there was a good example here on Stack Exchange that showed me how. So, the credits go to someone else. Yet, this part is fairly easy, but for someone with no background in modeling, R, or any programming what so ever, it can be an pain in the ass to figure out. To make a for loop and store the results, you NEED to create an object that can store the data of the loop.
Here a simple for loop storing the results in a data frame.
loopdf <- as.data.frame(matrix(ncol = 1, nrow = 0))
for(i in 1:nrow(df)){
loopdf[i,] <- df$x[i]+df$y[i]
}
loopdf
Here a simple for loop storing the results in a list.
looplist <- list()
for(i in 1:nrow(df)){
looplist[[i]] <- df$x[i]+df$y[i]
}
do.call(rbind, looplist)
Here a loop concatenating the results in an atomic vector.
loopvec <- NULL
for(i in 1:nrow(df)){
loopvec <- c(loopvec, df$x[i]+df$y[i])
}
loopvec
Here the apply loop (two versions).
apply(df, 1, sum)
apply(df, 1, function(x), sum(x))
I am trying to figure out how to use a for loop to create a matrix of expected values. it should be able to handle a matrix of any size. This is all I've been able to come up with so far.
for(i in 1:obsv){
for(j in 1:obsv){
obsv[i,j]<-(sum(obsv[i,])*sum(obsv[,j]))/sum(obsv)
}
}
##obsv is the name of the matrix of observed values
Your loop is obviously wrong, see below. The main error was that you need to loop through 1:nrow(obsv) and 1:ncol(obsv), not like you are doing it.
I will use a fake matrix, since you haven't posted an example dataset.
obsv <- matrix(1:25, ncol = 5)
obsv2 <- obsv # modify a copy
for(i in 1:nrow(obsv)){
for(j in 1:ncol(obsv)){
obsv2[i, j] <- sum(obsv[i, ])*sum(obsv[, j])/sum(obsv)
}
}
Now, the above code can be greatly simplified. A one-liner will do it.
obsv3 <- rowSums(obsv) %*% t(colSums(obsv))/sum(obsv)
identical(obsv2, obsv3)
#[1] TRUE
I have some array named P_Array with 100,000 data points and need to calculate the first order autocorrelation for subintervalls of length 100, i.e. from 1:100 and 2:101 etc. I've written a loop which works just fine, but is very slow.
Tf <- 100000
acf_Array <- rep(0, length.out = Tf-100)
for (t in 1:(Tf-100)){
acf_Array[t] <- acf(P_Array[t:(t+100)])$acf[2]
}
My idea was to use something like
acf_Array[1:(Tf-100)] <- acf(P_Array[(1:(Tf-100)):(101:Tf)])$acf[2]
which, however, does not work. Any suggestions?
Edit
I think this will do the trick
for (t in 1:(Tf-100)){
acf_Array[t] <- cor(P_Array[t:(t+98)], P_Array[(t+1):(t+99)])
}
To answer the specific question on vectorising the for loop, this is my answer:
acf_Array <- sapply(1:Tf-100, function(x) acf(P_Array[x:x+100])$acf[2])
But as mentioned in the comments the speed limiting bit is probably the acf function.
I can't get this for loop to run.
loopLength <- length(vector_X)
i <- 1
for (x in 1:loopLength)
vector_Y <- Frame_X$column_a == vector_X[i]
Frame_Y <- Frame_X[Vector_Y,]
Frame_A <- Frame_Y$column_b == vector_X[i]
Frame_Z <- Frame_Y[Frame_A,]
Vector_T <- Frame_Y$column_c == Frame_Z[1,2]
Frame_Z2 <- Frame_Y[Vector_T,]
returnSum1[i] <- sum(Frame_Z2$column_d)
Frame_Z3 <- Frame_Y[!(Frame_Z1),]
returnSum2[i] <- sum(Frame_X3$column_d)`
I can run the stand_alone code block by replacing the i with an integer (it is only running from 1 to 20) and crosscheck the db and the results are correct. However, I can't seem to iterate it.
I think I'm missing something glaring about integrating a loop but I've looked and can't seem to find it.
It doesn't work when I try to run it as for (i in 1:20) either.
Nor do the inclusion or exclusion around brackets around the code block work either.
The variable you defined in your for loop is named x, not i. If that isn't it, then the error might come from the fact that if Frame_Z happens to have 0 rows, then Frame_Z[1,2] doesn't exist! I think that step in particular is not very clear. I could help more if you posted an example data.frame and said what you want to do. Also, it would make your code easier to read if you used less steps and didn't name indices Frames (as in Frame_A and Frame_Z1). Also, I think using dplyr would be easier. Something like:
library(dplyr)
loopLength <- length(vector_X)
for(i in 1:loopLength){
xval <- vector_X[i]
Frame_Z <- Frame_X %>%
filter(column_a == xval, column_b == xval)
...
}
I can't post more because I don't quite get what you are trying to do though.
I have a large data set and I want to perform several functions at once and extract for each a parameter.
The test dataset:
testdf <- data.frame(vy = rnorm(60), vx = rnorm(60) , gvar = rep(c("a","b"), each=30))
I first definded a list of functions:
require(fBasics)
normfuns <- list(jarqueberaTest=jarqueberaTest, shapiroTest=shapiroTest, lillieTest=lillieTest)
Then a function to perform the tests by the grouping variable
mynormtest <- function(d) {
norm_test <- res_reg <- list()
for (i in c("a","b")){
res_reg[[i]] <- residuals(lm(vy~vx, data=d[d$gvar==i,]))
norm_test[[i]] <- lapply(normfuns, function(f) f(res_reg[[i]]))
}
return(norm_test)
}
mynormtest(testdf)
I obtain a list of test summaries for each grouping variable.
However, I am interested in getting only the parameter "STATISTIC" and I did not manage to find out how to extract it.
You can obtain the value stored as "STATISTIC" in the output of the various tests with
res_list <- mynormtest(testdf)
res_list$a$shapiroTest#test#statistic
res_list$a$jarqueberaTest#test#statistic
res_list$a$lillieTest#test#statistic
And correspondingly for set b:
res_list$b$shapiroTest#test$statistic
res_list$b$jarqueberaTest#test$statistic
res_listb$lillieTest#test$statistic
Hope this helps.
Concerning your function fgetparam I think that it is a nice starting point. Here's my suggestion with a few minor modifications:
getparams2 <- function(myp) {
m <- matrix(NA, nrow=length(myp), ncol=3)
for (i in (1:length(myp))){
m[i,] <- sapply(1:3,function(x) myp[[i]][[x]]#test$statistic)}
return(m)
}
This function represents a minor generalization in the sense that it allows for an arbitrary number of observations, while in your case this was fixed to two cases, a and b. The code can certainly be further shortened, but it might then also become somewhat more cryptic. I believe that in developing a code it is helpful to preserve a certain compromise between efficacy and compactness on one hand and readability or easiness to understand on the other.
Edit
As pointed out by #akrun and #Roland the function getparams2() can be written in a much more elegant and shorter form. One possibility is
getparams2 <- function(myp) {
matrix(unname(rapply(myp, function(x) x#test$statistic)),ncol=3)}
Another great alternative is
getparams2 <- function(myp){t(sapply(myp, sapply, function(x) x#test$statistic))}