Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving vectors of different lengths in a matrix/data frame

Tags:

r

I have a numeric called area of length 166860. This consists of 412 different elements, most of length 405 and some of length 809. I have their start and end ids.

My goal is to extract them and put them in a matrix/data frame with 412 columns

Right now, I'm trying this code:

m = matrix(NA,ncol=412, nrow=809)
for (j in 1:412){
temp.start = start.ids[j]
temp.end = end.ids[j]
m[,j] = area[temp.start:temp.end]
}

But I just end up with this error message:

"Error in m[, j] = area[temp.start:temp.end] : number of items to replace is not a multiple of replacement length"

like image 572
user2846211 Avatar asked Jan 21 '14 12:01

user2846211


2 Answers

Here's a quite easy approach:

Example data:

area <- c(1:4, 1:5, 1:6, 1:3)
# [1] 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 1 2 3

start.ids <- which(area == 1)
# [1]  1  5 10 16

end.ids <- c(which(area == 1)[-1] - 1, length(area))
# [1]  4  9 15 18

Create a list with one-row matrices:

mats <- mapply(function(x, y) t(area[seq(x, y)]), start.ids, end.ids)
# [[1]]
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# 
# [[2]]
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    2    3    4    5
#
# [[3]]
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    1    2    3    4    5    6
# 
# [[4]]
#      [,1] [,2] [,3]
# [1,]    1    2    3

Use the function rbind.fill.matrix from the plyr package to create the matrix and transpose it (t):

library(plyr)
m <- t(rbind.fill.matrix(mats))
#    [,1] [,2] [,3] [,4]
# 1    1    1    1    1
# 2    2    2    2    2
# 3    3    3    3    3
# 4    4    4    4   NA
# 5   NA    5    5   NA
# 6   NA   NA    6   NA
like image 69
Sven Hohenstein Avatar answered Oct 02 '22 13:10

Sven Hohenstein


You are setting the column length to be 412, and matrices cannot be flexible/variable in their length. This means the value you assign to the columns must either have a length of 412 or something less that can fill into a length of 412. From the manual on ?matrix:

If there are too few elements in data to fill the matrix, then the elements in data are recycled. If data has length zero, NA of an appropriate type is used for atomic vectors (0 for raw vectors) and NULL for lists.

As another commenter said, you may have intended to assign to the rows in which case m[j, ] is the way to do that, but you have to then pad the value you are assigning with NA or allow NA's to be filled so the value being assigned is always of length 809.

m = matrix(NA,ncol=412, nrow=809)
for (j in 1:412){
  temp.start = start.ids[j]
  temp.end = end.ids[j]
  val <- area[temp.start:temp.end]
  m[j, ] = c(val, rep(NA, 809 - length(val)))
}
like image 23
jjacobs Avatar answered Oct 02 '22 13:10

jjacobs