Operating on multiple matrices in a for loop using R - r

I have 1000 matrices named A1, A2, A3,...A1000.
In a for loop I would like to simply take the colMeans() of each matrix:
for (i in 1:1000){
means[i,]<-colMeans(A1)
}
I would like to do this for each matrix Ax. Is there a way to put Ai instead of A1 in the for loop?

So, one way is:
for (i in 1:1000){
means[i,]<-colMeans(get(paste('A', i, sep = '')))
}
but I think that misses the point of some of the comments, i.e., you probably had to do something like this:
csvs = lapply(list.files('.', pattern = 'A*.csv'), function(fname) {
read.csv(fname)
})
Then the answer to your question is:
means = lapply(csvs, colMeans)

I don't completely understand, but maybe you have assigned each matrix to a different variable name? That is not the best structure, but you can recover from it:
# Simulate the awful data structure.
matrix.names<-paste0('A',1:1000)
for (name in matrix.names) assign(name,matrix(rnorm(9),ncol=3))
# Pull it into an appropriate list
list.of.matrices<-lapply(matrix.names,get)
# Calculate the column means
column.mean.by.matrix<-sapply(list.of.matrices,colMeans)

You initial question asks for a 'for loop' solution. However, there is an easy way to get the desired
result if we use an 'apply' function.
Perhaps putting the matrices into a list, and then applying a function would prove worthwhile.
### Create matrices
A1 <- matrix(1:4, nrow = 2, ncol = 2)
A2 <- matrix(5:9, nrow = 2, ncol = 2)
A3 <- matrix(11:14, nrow = 2, ncol = 2)
### Create a vector of names
names <- paste0('A', 1:3)
### Create a list of matrices, and assign names
list <- lapply(names, get)
names(list) <- names
### Apply the function 'colMeans' to every matrix in our list
sapply(list, colMeans)
I hope this was useful!

As others wrote already, using a list is perhaps your best option. First you'll need to place your 1000 matrices in a list, most easily accomplished using a for-loop (see several posts above). Your next step is more important: using another for-loop to calculate the summary statistics (colMeans).
To apply a for-loop through an R object, in general you can do one of the two options:
Loop over by indices: for example:
for(i in 1:10){head(mat[i])} #simplistic example
Loop "directly"
for(i in mat){print(i)} #simplistic example
In the case of looping through R lists, the FIRST option will be much easier to set up. Here is the idea adapted to your example:
column_means <- rep(NA,1000) #empty vector to store column means
for (i in 1:length(list_of_matrices)){
mat <- list_of_matrices[[i]] #temporarily store individual matrices
##be sure also to use double brackets!
column_means <- c(column_means, colMeans(mat))

Related

Iterative multiplication of the two lists in R

I am trying to multiply the values stored in a list containing 1,000 values with another list containing ages. Ultimately, I want to store 1,000 rows to a dataframe.
I wonder if it's better to use lapply fucntion or for loop function here.
list 1
lambdaSamples1 <- lapply(
floor(runif(numSamples, min = 1, max = nrow(mcmcMatrix))),
function(x) mcmcMatrix[x, lambdas[[1]]])
*the out put is 1,000 different values in a list. *
list 2
ager1= 14:29
What I want to do is
for (i in 1: numSamples) {
assign(paste0("newRow1_", i), 1-exp(-lambdaSample1[[i]]*ager1))
}
now I got 1,000 rows of values that I want to store in a predetermiend dataframe, outDf_1 (nrow=1000, ncol = ager1).
I tried
`
for (i in 1:numSamples) {
outDf_1[i,] <- newRow1_i
}
I want to store newRow1_1, ,,,,,, , newRow1_1000 to each of the 1,000 row of outDf_1 dataframe.
SHould I approach different way?
I think you're overcomplicating this a bit. Many operations in R are vectorized so you shoudln't need lapply or for loops for this. You didn't give us any data to work with but the code below should do what you want in a more straightforward and fast way.
lambdaSamples1 <- mcmcMatrix[sample(nrow(mcmcMatrix), numSamples, replace=T),
lambdas[[1]]]
outDF_1 <- 1 - exp(-lambdaSamples1 %*% t(ager1))
Just note that this makes outDF_1 a matrix, not a data frame.
To do this for multiple ages, you could use a loop to save your resulting matrices in a list:
outDF <- list()
x <- 5
for (i in seq_len(x)) {
lambdaSamples <- mcmcMatrix[sample(nrow(mcmcMatrix), numSamples, replace=T),
lambdas[[1]]]
outDF[[i]] <- 1 - exp(-lambdaSamples %*% t(ager[[i]]))
}
Here, ager1, ..., agerx are expected to be stored in a list (ager).

Compute 15 rows in parallel (through vectorization) and create df with them

I am creating 15 rows in a dataframe, like this. I cannot show my real code, but the create row function involves complex calculations that can be put in a function. Any ideas on how I can do this using lapply, apply, etc. to create all 15 in parallel and then concatenate all the rows into a dataframe? I think using lapply will work (i.e. put all rows in a list, then unlist and concatenate, but not exactly sure how to do it).
for( i in 1:15 ) {
row <- create_row()
# row is essentially a dataframe with 1 row
rbind(my_df,row)
}
Something like this should work for you,
create_row <- function(){
rnorm(10, 0,1)
}
my_list <- vector(100, mode = "list")
my_list_2 <- lapply(my_list, function(x) create_row())
data.frame(t(sapply(my_list_2,c)))
The create_row function is just make the example reproducible, then we predefine an empty list, then fill it with the result from the create_row() function, then convert the resulting list to a data frame.
Alternatively, predefine a matrix and use the apply functions, over the row margin, then use the t (transpose) function, to get the output correct,
df <- data.frame(matrix(ncol = 10, nrow = 100))
t(apply(df, 1, function(x) create_row(x)))

Saving rows into variables in R

I have a 18-by-48 matrix.
Is there a way to save each of the 18 rows automatically in a separate variable (e.g., from r1 to r18) ?
I'd definitely advise against splitting a data.frame or matrix into its constituent rows. If i absolutely had to split the rows up, I'd put them in a list then operate from there.
If you desperately had to split it up, you could do something like this:
toy <- matrix(1:(18*48),18,48)
variables <- list()
for(i in 1:nrow(toy)){
variables[[paste0("variable", i)]] <- toy[i,]
}
list2env(variables, envir = .GlobalEnv)
I'd be inclined to stop after the for loop and avoid the list2env. But I think this should give you your result.
I believe you can select a row r from your dataframe d by indexing without a column specified:
var <- d[r,]
Thus you can extract all of the rows into a variable by using
var <- d[1:length(d),]
Where var[1] is the first row, var[2] the second. Etc.. not sure if this is exactly what you are looking for. Why would you want 18 different variables for each row?
result <- data.frame(t(mat))
colnames(result) <- paste("r", 1:18, sep="")
attach(result)
your matrix is mat

Filling a list with a variety of matrices which are samples from a matrix

I'm wanting to fill a list with many different matrices which are created by selecting a variety of different samples from an original matrix. Then repeat this process 10 times. I managed to do it (after much fighting/painful learning process). I would be so grateful if someone could point me in the right direction to get rid of my redundant code and improve the functions I'm using (maybe even get rid of the loops which I gather are rather frowned upon).
My problem hinged on getting the different sized matrices out of the loop.
Here's the code I used, one day I aspire to write R code that is not ugly:
##defining a matrix called allmat
allmat <- matrix(rnorm(100), nrow=50, ncol=2)
##sampling different sizes of the allmat matrix from 0.1*allmat to 10*allmat
for(i in seq(0,9,by=1)) {
for(j in seq(0.1,10,by=0.05)) {
nam <- paste("powermatrix_",j,"_",i,sep="")
assign(nam, allmat[sample(nrow(allmat),replace=T,size=j*nrow(allmat)),])
}
}
##then using apropos to pick out the names of the matrices from file
##eventually converting matrix list into a list to then use lapply
matrixlist <- data.frame(apropos("powermatrix_"), stringsAsFactors = FALSE)
##then rather horribly trying somehow to get my dataframe into a
## list which eventually I do below (but although inelegant this bit is
## not crucial)
colnames(matrixlist) <- "col1"
matrixlist_split <- strsplit(matrixlist$col1, "_")
library("plyr")
df <- ldply(matrixlist_split)
colnames(df) <- c("V1", "V2", "V3")
vector_sample <- as.numeric(df$V2)
mynewdf <- cbind(vector_matrices,vector_sample)
##creating the list before lapply
mylist <- as.list(mget(mynewdf$col1))
##then with the list I can use lapply (but there has to be a much
## much better way!)
Many thanks for all your input. This is now working much better with the following two lines. I didn't know you could seq_along or seq with lapply. These two in combination are very helpful.
this vector changes the size and repititions of the matrix sampled
seq_vector <- c(rep(seq(0.1,1,by=0.1),each=10))
this samples the matrix for all of the sizes and repeats defined by the sequence vector
myotherlist <- lapply(seq(seq_vector), function(x) allmat[sample(1:nrow(allmat), replace=T, size=x*nrow(allmat)),])

turning list of matrixes into a vector

I have found many solutions the other way round but none this way. I have a list of matrixes and need to have them as a vector. I could take each element, name it, and than put it in a vector. But I'm sure there is a better way!
zerooklein <- lapply(1:10, function(x){genweb(10, 5, dens=2)})
zeroomittel <- lapply(1:10, function(x){genweb(10, 20, dens=2)})
zeroogroß <- lapply(1:10, function(x){genweb(10, 80, dens=2)})
these are my lists.
size <- c(this should contain all the singel matrices )
sizef <- sapply(size, function(x) nested(get(x), method="ALL"))
plot(capscale(formula = scale(sizef) ~ 1))
and this is what i want to do with them.
If you want to use the names of the your LISTS, note the 'zeroo...' objects are not vectors, you create that vector explicitly. The only vector in this entire process is the following one line:
size <- c("zerooklein", "zeroomittel", "zeroogroß")
Now the rest of this is all lists and matrices. Each of your 'zeroo...' objects is a list of matrices and therefore must be looped over to pass to nested. As such, you need to loop over not only each 'zeroo...' object but also each matrix within the 'zeroo...', hence a double loop. The following call does the job.
sizef <- lapply(size, function(x) sapply(get(x), function(y) nested(y, method="ALL")))
You cannot just use two sapply statements otherwise it will automatically 'rbind' your results together, which it appears is not your goal. Therefore, you have a list of three matrices at this point. You can merge these together with do.call.
size_merged <- do.call("cbind", sizef)
Now you can plot your final matrix
plot(capscale(scale(size_merged) ~ 1))

Resources