Search code examples
rmatrixfill

Fill matrix in R


I have a preallocated matrix in R and need to fill it with data from a dataframe generated from a file having following format:

1-1-7  
1-3-2  
2-2-6  
1-4-8  
....

where the first column contains a row index, the second a column index, and the 3rd contains the values.

Is there a faster/better way then the following loop?

    for(i in 1:nrow(file)){  
    matrix[file[i,1],file[i,2]]=file[i,3]
    }

Solution

  • Use row/col index as the first and second columns of file and assign the file[,3] to m1 using those index.

    m1[as.matrix(file[1:2])] <- file[,3]
    m1
    #     [,1] [,2] [,3] [,4]
    #[1,]    7    0    2    8
    #[2,]    0    6    0    0
    

    As I mentioned above, we assign the values based on the row/column index. If we take the first two columns and convert to matrix, the first column acts as the row index and second as the column index

     as.matrix(file[1:2])
     #     v1 v2
     #[1,]  1  1
     #[2,]  1  3
     #[3,]  2  2
     #[4,]  1  4
    

    If we subset the m1 based on the first row i.e. 1 1, we are getting the element of m1 at row=1 and column=1, similarly for the 2nd row, it would be the element at row=1 and column=3, and so on.. Here, we created a matrix of 0 with the specified dimensions. So, the 4 values based on the row/columns positions will be 0

    m1[as.matrix(file[1:2])]
    #[1] 0 0 0 0
    

    Now, we are changing/replacing the values in 'm1' at the specified row/column positions by assigning the value to the 3rd column of 'file'

     m1[as.matrix(file[1:2])] <- file[,3]
    

    If we check the values at the specified position, it will be replaced

     m1[as.matrix(file[1:2])] 
     #[1] 7 2 6 8
    

    Or we can use another approach using sparseMatrix from library(Matrix)

    library(Matrix)
    sM <- sparseMatrix(file[,1], file[,2], x=file[,3])
    as.matrix(sM)
    #      [,1] [,2] [,3] [,4]
    #[1,]    7    0    2    8
    #[2,]    0    6    0    0
    

    data

    file <- structure(list(v1 = c(1L, 1L, 2L, 1L), v2 = c(1L, 3L, 2L, 4L), 
    v3 = c(7, 2, 6, 8)), .Names = c("v1", "v2", "v3"), 
     class = "data.frame", row.names = c(NA, -4L))
    
    m1 <- matrix(0, nrow=max(file[,1]), ncol=max(file[,2]))