Iterate over list in list - r

I am currently trying to create a list of matrices from a list of lists. The ingredient of the list of list are polygons i.e. vertice coordinates of each o the five vertices:
$HEW18
[,1] [,2]
[1,] 595165.9 5688133
[2,] 595065.9 5688133
[3,] 595065.9 5688233
[4,] 595165.9 5688233
[5,] 595165.9 5688133
$HEW19
[,1] [,2]
[1,] 593512.7 5672780
[2,] 593412.7 5672781
[3,] 593414.0 5672881
[4,] 593514.0 5672880
[5,] 593512.7 5672780
There is a total of 150 polygons in this file
Now in order to create a spatialpolygonsdataframe, I have to create matrices from the "inside" lists, or a list of matrices...
I managed to do that for one single polygon like this:
#turn list to matrix
matrixHEW39 = matrix(c(forest$HEW39[1:5,]), nc=2, byrow = FALSE)
What I would like to do now is, to save some time and NOT write this for all 150 polys individually but rather create a for-loop for it.
The following code represents my unrefined "idea" of how it should work:
forest_list <-list()
for (i in forest) {
matrix[i] = matrix(c(forest$i[1:5], nc =2, byrow = FALSE)
forest_list[i]<-matrix[i]
}
You see, the problem here, or at least one of them is the "forest$i[1:5]"
How can I select ONE of the polygons and within each row 1 -5 , as in the single polygon code? Also, I need to maintain the names of each polygon?

I think you are a little confused here (happens easily when learning R!). This is based on seeing you using forest_list[i]<-matrix[i]. Lists can be accessed using either single-brackets [i], double-brackets [[i]], or the dollar-name convention as you have used: forest$HEW39. The single-bracket takes a 'slice', which returns the data, but it is still a list. The double brackets return the object at position 'i' of the list, same as dollar-name returns the list item with that name. NB you can also use [["HEW39"]].
I think this is from where the confusion stems. I don't think you have a list of lists, just a plain list, but trying to access this list using the single-bracket returns a list (of length 1) of your matrix. So it looks like a list of lists. And naturally, you try to create a matrix from that. But the matrix is there, you just need to access it using double-brackets.
To answer your question, I have made a list of 5 matrices similar to yours and named them:
forest <- lapply(c(1,2,3,4,5), function(f){replicate(2, rnorm(5))})
names(forest) <- paste0("HEW", 1:5)
NB:
class(forest[1])
[1] "list"
class(forest[[1]])
[1] "matrix"
class(forest$HEW1)
[1] "matrix"
To index over those, we can use a for-loop, and capture in a new list
forest_list <- as.list(names(forest))
for (i in 1:length(forest)) {
matrixi <- forest[[i]]
forest_list[[i]] <- matrixi
}
If you do have a list of lists, e.g.:
forest_lol <- list(1)
forest_lol[[1]] <- forest_list
you can iterate over the primary list you want (e.g. [[1]] in this case):
forest_list <- as.list(names(forest))
for (i in 1:length(forest_lol[[1]])) {
matrixi <- forest_lol[[1]][[i]]
forest_list[[i]] <- matrixi
}
Retaining names in new lists just means either capturing them in a vector during the for-loop, or more simply naming based on the previous list:
name_vector <- c()
for (i in 1:length(forest)) {
name_vector <- c(name_vector, names(forest)[i])
}

Related

change specific component of list in R

I try to change a specific component L[[2]] in a list L in R. Unfortunately, the other component L[[1]] in the list changes as well. Below is a minimal working example:
# initialize list L:
L <- matrix(list( matrix(0,1,2) ), 2, 1)
# show that L[[1]] = c(0,0):
print(L[[1]][1,])
#>[1] 0 0
# only change L[[2]] into c(1,1):
L[[2]][1,] <- 1
# however L[[1]] has changed too to c(1,1):
print(L[[1]][1,])
#>[1] 1 1
(Maybe this is a basic question as I am not an expert in R.)
In response to Akrun's comment:
The change in L[[1]] occurs when I run the complete code in one go in the editor of R-studio. Somehow the change in L[1] does not occur when I run the four commands at the command line one at a time. Seems very strange to me.
There are multiple ways to tackle this. The structure is a bit convoluted to make the changes as we do in regular list. It is a list with dimension attributes given by matrix and is complicated by having a list of matrices
1) The list object is created within a matrix and it is a list of matrices. So, we could assign the values based on subsetting the elements of the matrix first and then extract the list component to assign it to 1
L[2][[1]][] <- 1
print(L[[1]][1,])
#[1] 0 0
2) Another option is to create a temporary list object and assign the values on the list, update the matrix/list later with the changed list
l1 <- lapply(L, I) # I stands for identity.
l1[[2]][] <- 1
L[] <- l1
print(L[[1]][1,])
#[1] 0 0

for loop to print dimensions of files in a list

temp <- list.files(pattern = '*.xlsx')
list <- lapply(temp,read_excel)
The above list has 12 files. I want to check the dimensions of each of those 12 files, i.e. number of rows and columns in each file.
for(i in length(list)){
print(dim(list[[i]]))
}
[1] 12533 49
The above for loop only gives me output of the last file, whereas I need the for loop to give me dimension of each 12 files.
Could someone please let me know what needs to be done.
You need to change your for loop to
for(i in 1:length(list)){
print(dim(list[[i]]))
}
since 1:length(list) would create a sequence of numbers to loop over whereas length(list) would only give the length of the list (which is 12 in your case) and it would not generate the sequence.
Moreover, you don't even need a loop to do this. You could just use lapply and it would give you dimensions of the list.
lapply(list, dim)
For example,
list_df <- list(mtcars, iris)
lapply(list_df, dim)
#[[1]]
#[1] 32 11
#[[2]]
#[1] 150 5
On a side note, it is not a good practice to name your list as list since it is an internal R function.

How to iterate/loop through multiple numbered variables in R

So, I'm new to programming in R, so I don't even know if this is feasible to even do. I have 50 matrices (50,000 rows by 10 columns) I'm trying to populate for a Monte Carlo simulation. I created all matrices in a loop and they're called mCMatrix1, mCMatrix2 etc.
I want to populate the matrices in a loop, something to this effect:
for (i in 50){
for (j in 50000){
num <- mu + tR %*% rnorm(10) # returns a 10 row, 1 column matrix
mCMatrixC"i"[]= num[,1] # basically rotates the matrix to fill in the first row
}
}
where I can somehow code the program to know that it needs to populate mCMatrix1, then mCMatrix2, all the way to the 50th matrix. For STATA users, I remember you could loop through variables with with v = forval(range of values), mCMatrix`v' . (It's been a while since I've used STATA, so the syntax probably isn't right, but it was something to that effect.
You can build a list of matrices for easier access and access it using the following. I am not sure about the matrix operation you do in the loop so I have chosen a random matrix as an example.
> list_matrices = c()
> for (i in 1:10) { list_matrices[[i]] = matrix(rnorm(9), nrow=3)}
> list_matrices[[1]]
[,1] [,2] [,3]
[1,] -0.09855292 0.2665513 0.72873888
[2,] -0.03005994 -0.4834303 -1.12356622
[3,] 0.98443875 0.5895932 0.07072777
If the core issue is to generate new (numbered) variable names and assign values to them, then I think you can use this approach:
for(i in 1:3)
{
n<- sprintf("matr%d",i)
print(n)
assign(x=n,value = i)
}
matr1
matr2
matr3
R runs on lists and data.frames which is a little bit different from other methods. Your easiest method is to create a list of of matrix names and iterate through the list.
Rawr's approach is the simplest and probably most effective.
Then you simply access it by mlist[n], n being the matrix you want.
If you want a complete data frame approach its a little more complicated but it gives a data table with indices rather than a list of matrices
library(dplyr)
yourData <- data.frame()
for (k in 1:50) {
yourData <- yourData %>%
rbind((as.data.frame(matrix(rnorm(50000 * 10), nrow=50000, ncol=10))) %>%
mutate(Run = k))
}
That way you could access it as
yourData %>% filter(Run = n)

Creating an array or lists of lists in R

I have a list of matrices such that my_list[[1]] consists of a matrix and my_list[[2]] contains another matrix and so on. I want to embed this list inside a loop such that for every iteration of the loop I have a different my_list with different matrices, and want to be able to access them later. Is there any way I could do this in R? For example like creating an array (of size = number of iterations of the loop), and each index of the array would have a different list of matrices. Or something similar. And how can I access it. Could anyone please help me with this? I would greatly appreciate the help. I have looked around but cannot find a way to do this. Lists of lists seem to be an option, and I have tried to experiment with it for one iteration but it gives this error:
> nes <- list()
> nes[[1]] <- append(nes[[1]], my_list[[1]])
Error in nes[[1]] : subscript out of bounds
Would be great if anyone could help me with this.
EDIT:
Basically what I have is an initial list known as particles. Something like this:
for (k in 1:10)
{
# three centroids; k = 3
particle[[k]] <- rbind(features.dataf[sample(1:10, 1),2:4],
features.dataf[sample(1:10, 1),2:4],
features.dataf[sample(1:10, 1),2:4])
row.names(particle[[k]]) <- c(1,2,3)
}
Then I run this loop again. With an extra outer loop.
for (n in 1:30) {
for (k in 1:10) {
###some calculations
### create a vector f[k] with an f value for each k (calculated according to some formula)
pbestFitness[n,k] <- f[k] ##create a nXk dataframe that stores the f[k] value for every iteration of n
### over here I want to create a list of lists
}
}
In the above code where I create the list of lists, such that for every iteration of the outer loop I have a particle[[k]]th matrix stored.
Any particle[[k]] is of the form:
[,1] [,2] [,3]
[1,] 0.96436532 0.8958297 0.6089338
[2,] 0.08555853 0.7762849 0.6647247
[3,] 0.30792817 0.8061227 0.5099790
The desired output would be something like that if I try to access this new lists of lists (nes), its nes[[n]] value should have a list with k number of matrices.

Applying a function to a specific element of a list of a list

I have a function that returns a list of vectors and matrices. I then create a variable that is a list of several of the resulting lists from calls to the function. So I have a list of lists. My question is how do I apply a function over the elements of these lists (note this is not the same as applying a function over the lists themselves). Here is a simple example that retains all the essential features of what I am doing
numtrials = 5
x = rep(list(NULL),numtrials)
testfunction = function(){return( list( c(1,2,3,4,5), matrix(runif(10), 2,5),
matrix(0,2,2) ) )}
for(index in 1:numtrials){
x[[index]] = testfunction()
}
I want to now calculate the mean of say the (2,3) element of x[[index]][[2]] across all "index" lists. Or even better get a matrix of means, xbar, such that xbar[i,j] = mean(x[[]][[2]][i,j]). I tried to play around with (and of course read the help file for) lapply, and apply, but couldn't get it to work. One of the reasons is that x[[]][[2]][i,j] appears to be invalid notation
Error in x[[]] : invalid subscript type 'symbol'
I think R doesn't know what to make of the "[[]]". I know some people are going to suggest vectorizing but note that my function returns matrices and vectors of different, unrelated dimensions (although I am not opposed to vectorizing if you have a clever way of doing this).
Using abind you can create a list which contains arrays for the relevent components of the internal lists..
eg
library(abind)
xl <- do.call(mapply, c('abind', x, rev.along = 0))
# the second element from each inner list is now within a 3-d array
# which is the 2nd element of xl
# you can now construct your matrix of mean values by using `apply`
means <- apply(xl[[2]], 1:2, mean)
means
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.4576039 0.5185270 0.7099742 0.3812656 0.4529965
## [2,] 0.6528345 0.2304651 0.5534443 0.4404609 0.7361132
If you know which elements you want to pull out, then it's pretty straightforward to grab them with sapply/lapply, and get the mean:
# Mean of [[2]][2, 3] elements
values = sapply(x, function(elem) {
return(elem[[2]][2, 3])
})
mean(values)
sapply applies a function to each element of the outer list, which is passed in as the elem argument to the little anonymous function I've written. Then you just get the 2nd element of each of those: elem[[2]], and index into it to get the [2, 3] value.
here is the code, it may help you, first unlist and then apply on top of it
ulist=function(x)
{
l=length(x)
for(i in 1:l) lst[[i]]=x[[i]][[2]]
return(lst)
}
#apply mean of each column of the x[[i]][[2]] matrix
sapply(ulist(x),function(y) apply(y,2,mean))
#apply mean of each row of the x[[i]][[2]] matrix
sapply(ulist(x),function(y) apply(y,1,mean))

Resources