k1000x
k1000x

Reputation: 65

Loop over elements in vector, and elements are matrices

I started using R today, so I apologize if this is too basic.

First I construct 2 matrices, and construct a vector, whose entries are these matrices. Then, I try to loop over the elements of the vector, i.e. the matrices. However, when I do, I get a "argument of length zero" error.

cam <- 1:12
ped <- 13:24

dim(cam) <- c(3,4)
dim(ped) <- c(4,3)

mats <- c('cam','ped')

for (i in  1:2) {
  rownames(mats[i]) <- LETTERS[1:dim(mats[i])[1]]
  colnames(mats[i]) <- LETTERS[1:dim(mats[i])[2]]
}

The error text is as follows:

Error in 1:dim(mats[i])[1] : argument of length 0

The question: how to loop over elements of a vector, these elements being matrices? (I'm guessing I'm not calling the elements correctly). Thank you for patience.

Upvotes: 0

Views: 77

Answers (2)

Evan Friedland
Evan Friedland

Reputation: 3194

The go-to option in R is to use lists:

cam <- 1:12 ; dim(cam) <- c(3,4)
# same as matrix(1:12, nrow = 3, ncol = 4)
ped <- 13:24 ; dim(ped) <- c(4,3)

# save the list ( '=' sign for naming purposes only here)
mats <- list(cam = cam, ped = ped)

# notice the double brackets '[[' which is used for picking the list
for (i in  1:length(mats) {
  rownames(mats[[i]]) <- LETTERS[1:dim(mats[[i]])[1]]
  colnames(mats[[i]]) <- LETTERS[1:dim(mats[[i]])[2]]
}

# finally you can call the whole list at once as follows:
mats
# or seperately using $ or [[
mats$cam # mats[['cam']]
mats$ped # mats[['ped']]

ALTERNATIVELY

If you really want to get crazy you can take advantage of the get() and assign() functions. get() calls an object by character, and assign() can create one.

mats <- c('cam','ped')
mats.new <- NULL # initialize a matrix placeholder
for (i in  1:length(mats)) {
  mats.new <- get(mats[i]) # save as a new matrix each loop
  # use dimnames with a list input to do both the row and column at once
  dimnames(mats.new) <- list(LETTERS[1:dim(mats.new)[1]],
                             LETTERS[1:dim(mats.new)[2]]) 
  assign(mats[i],mats.new) # create (re-write) the matrix
}

Upvotes: 2

akrun
akrun

Reputation: 887128

If the datasets are placed in a list we can use lapply

lst <- lapply(mget(mats), function(x) {
         dimnames(x) <-  list(LETTERS[seq_len(nrow(x))], LETTERS[seq_len(ncol(x))])
    x})

It is better to keep it in a list. In case the original objects needs to be changed

list2env(lst, envir = .GlobalEnv)

Upvotes: 1

Related Questions