turning list of matrixes into a vector - r

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))

Related

Assign names to sublists in a list

I have a list that contains three sublists, each of those sublists containing two objects.
Now I am looking for an efficent way to assign names to those objects in the sublists. In this case, the single objects of each sublist are supposed to have the same names (Matrix1 and Matrix2).
Here is a easy reproducible example:
# create random matrices
matrix1 <- matrix(rnorm(36),nrow=6)
matrix2 <- matrix(rnorm(36),nrow=6)
# combine the matrices to three lists
sublist1 <- list(matrix1, matrix2)
sublist2 <- list(matrix1, matrix2)
sublist3 <- list(matrix1, matrix2)
# combine the lists to one top list
Toplist <- list(sublist1, sublist2, sublist3)
I can do this by using a for loop:
# assign names via for loop
for (i in 1:length(Toplist)) {
names(Toplist[[i]]) <- c("Matrix1", "Matrix2")
}
I am sure there must be a more elegant way using a nested lapply command. But I struggled to implement the names() command inside it.
Anybody with a hint?
Try lapply(Toplist,setNames,c("a","b")).

List of lists with data frames [duplicate]

I know this topic appeared on SO a few times, but the examples were often more complicated and I would like to have an answer (or set of possible solutions) to this simple situation. I am still wrapping my head around R and programming in general. So here I want to use lapply function or a simple loop to data list which is a list of three lists of vectors.
data1 <- list(rnorm(100),rnorm(100),rnorm(100))
data2 <- list(rnorm(100),rnorm(100),rnorm(100))
data3 <- list(rnorm(100),rnorm(100),rnorm(100))
data <- list(data1,data2,data3)
Now, I want to obtain the list of means for each vector. The result would be a list of three elements (lists).
I only know how to obtain list of outcomes for a list of vectors and
for (i in 1:length(data1)){
means <- lapply(data1,mean)
}
or by:
lapply(data1,mean)
and I know how to get all the means using rapply:
rapply(data,mean)
The problem is that rapply does not maintain the list structure.
Help and possibly some tips/explanations would be much appreciated.
We can loop through the list of list with a nested lapply/sapply
lapply(data, sapply, mean)
It is otherwise written as
lapply(data, function(x) sapply(x, mean))
Or if you need the output with the list structure, a nested lapply can be used
lapply(data, lapply, mean)
Or with rapply, we can use the argument how to get what kind of output we want.
rapply(data, mean, how='list')
If we are using a for loop, we may need to create an object to store the results.
res <- vector('list', length(data))
for(i in seq_along(data)){
for(j in seq_along(data[[i]])){
res[[i]][[j]] <- mean(data[[i]][[j]])
}
}

R: Iterating Parameter Arguments from List for Random Generation For Loop

I'm new to the forum and to r, so please forgive the sloppy code.
In short, I am trying to get a normal distribution to iteratively use the parameters drawn from two lists for use in a For Loop that generates a 30x10000 matrix of random samples using these parameters.
The first list (List1) is a collection of numeric vectors. The second list (List2) has corresponding values I would like to use for the standard deviation argument in rnorm: i.e. vector 1 from List1's standard deviation is Value1 in List2.
set.seed(1500) #set up random gen
var1 = rnorm(1:1000, mean = #mean of vector(i) from list1, sd = #value(i) from List2)
sample(var1,size=1)
X = matrix(ncol = 30, nrow = 10000)
for(j in 1:length(var1)){ #simulates data using parameters set by rnorm var1 function
for(i in 1:10000){
X[i.j] = sample(var1,1)
}
}
Here's the original post where this code is inspired from.
Cheers!
It seems mapply() would help you:
# First let's turn the list1 into means.
dist.means = lapply(list1,mean)
Lapply is a way to execute a function for every element in a list. Mapply works in a very similar way but uses multiples lists.
samples = mapply(rnorm, 30*10000, dist.means, list2,SIMPLIFY=F)
A little bit more explanation: mapply() runs rnorm() multiple times. In the first attempt, it runs using the first element of first list as the first argument, the first element of second list as second argument, etc. So in our case it will run rnorm( 30*10000, dist.means[[1]], list2[[1]] ) then rnorm( 30*10000, dist.means[[2]], list2[[2]] ) and store the output in a list.
Note that I use a small trick here. The first list is a single number 30*10000. When you give list of different sizes to mapply it recycles the shorter one, i.e. it repeats the shorter lists until it has the same length of the longer lists.
Hope that helps

Operating on multiple matrices in a for loop using 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))

R: apply() type function for two 2-d arrays

I'm trying to find an apply() type function that can run a function that operates on two arrays instead of one.
Sort of like:
apply(X1 = doy_stack, X2 = snow_stack, MARGIN = 2, FUN = r_part(a, b))
The data is a stack of band arrays from Landsat tiles that are stacked together using rbind. Each row contains the data from a single tile, and in the end, I need to apply a function on each column (pixel) of data in this stack. One such stack contains whether each pixel has snow on it or not, and the other stack contains the day of year for that row. I want to run a classifier (rpart) on each pixel and have it identify the snow free day of year for each pixel.
What I'm doing now is pretty silly: mapply(paste, doy, snow_free) concatenates the day of year and the snow status together for each pixel as a string, apply(strstack, 2, FUN) runs the classifer on each pixel, and inside the apply function, I'm exploding each string using strsplit. As you might imagine, this is pretty inefficient, especially on 1 million pixels x 300 tiles.
Thanks!
I wouldn't try to get too fancy. A for loop might be all you need.
out <- numeric(n)
for(i in 1:n) {
out[i] <- snow_free(doy_stack[,i], snow_stack[,i])
}
Or, if you don't want to do the bookkeeping yourself,
sapply(1:n, function(i) snow_free(doy_stack[,i], snow_stack[,i]))
I've just encountered the same problem and, if I clearly understood the question, I may have solved it using mapply.
We'll use two 10x10 matrices populated with uniform random values.
set.seed(1)
X <- matrix(runif(100), 10, 10)
set.seed(2)
Y <- matrix(runif(100), 10, 10)
Next, determine how operations between the matrices will be performed. If it is row-wise, you need to transpose X and Y then cast to data.frame. This is because a data.frame is a list with columns as list elements. mapply() assumes that you are passing a list. In this example I'll perform correlation row-wise.
res.row <- mapply(function(x, y){cor(x, y)}, as.data.frame(t(X)), as.data.frame(t(Y)))
res.row[1]
V1
0.36788
should be the same as
cor(X[1,], Y[1,])
[1] 0.36788
For column-wise operations exclude the t():
res.col <- mapply(function(x, y){cor(x, y)}, as.data.frame(X), as.data.frame(Y))
This obviously assumes that X and Y have dimensions consistent with the operation of interest (i.e. they don't have to be exactly the same dimensions). For instance, one could require a statistical test row-wise but having differing numbers of columns in each matrix.
Wouldn't it be more natural to implement this as a raster stack? With the raster package you can use entire rasters in functions (eg ras3 <- ras1^2 + ras2), as well as extract a single cell value from XY coordinates, or many cell values using a block or polygon mask.
apply can work on higher dimensions (i.e. list elements). Not sure how your data is set up, but something like this might be what you are looking for:
apply(list(doy_stack, snow_stack), c(1,2), function(x) r_part(x[1], x[2]))

Resources