cune
cune

Reputation: 79

Sub-setting / Matching row and columns in R

Ok, so I need a very specific formula for subsetting. From matrix x, I only want to keep elements defined by rows and columns. The undesired elements should then be replaced by zeros. Example below:

> x <- matrix(c(65,46,52,76,34,345,65,87,12,53),nrow = 5,ncol = 2)
> x
     [,1] [,2]
[1,]   65  345
[2,]   46   65
[3,]   52   87
[4,]   76   12
[5,]   34   53

> rows <- c(1,1,2,3,3,4,5)
> cols <- c(1,2,2,1,2,1,2)

magic

> x
     [,1] [,2]
[1,]   65  345
[2,]    0   65
[3,]   52   87
[4,]   76    0
[5,]    0   53

Many thanks

Upvotes: 4

Views: 93

Answers (3)

Aaron - mostly inactive
Aaron - mostly inactive

Reputation: 37764

This kind of magic is called matrix indexing. If you had rows and cols be the ones you didn't want, or if matrix indexing allowed for negative values, it would be even easier.

y <- matrix(0, nrow=5, ncol=2)
y[cbind(rows,cols)] <- x[cbind(rows,cols)]
y
##      [,1] [,2]
## [1,]   65  345
## [2,]    0   65
## [3,]   52   87
## [4,]   76    0
## [5,]    0   53

Alternatively, you can do the same thing "by hand," and have the capability of using negative subscripting, by knowing that a matrix can be treated as a vector with indexing going down the columns.

k <- (cols-1)*nrow(x) + rows
x[-k] <- 0
x
##      [,1] [,2]
## [1,]   65  345
## [2,]    0   65
## [3,]   52   87
## [4,]   76    0
## [5,]    0   53

Upvotes: 6

BradP
BradP

Reputation: 501

kind of baroque:

    indicies <- NULL
    for (iter in 1:length(rows)) {
      indicies <- rbind(indicies, c(rows[iter], cols[iter]))
    }

    indicies
     [,1] [,2]
[1,]    1    1
[2,]    1    2
[3,]    2    2
[4,]    3    1
[5,]    3    2
[6,]    4    1
[7,]    5    2

    y <- matrix(rep(0, 10), nrow=5, ncol=2)
    for (k in 1:nrow(indicies)) {
      y[indicies[k,1], indicies[k,2]] <- x[indicies[k,1], indicies[k,2]]
    }
    y
         [,1] [,2]
    [1,]   65  345
    [2,]    0   65
    [3,]   52   87
    [4,]   76    0
    [5,]    0   53

Upvotes: 0

Andrew
Andrew

Reputation: 1

Here is a possible solution, not necessarily pretty or efficient. Loop through every cell, if it's not in your original set of coordinates then set it to 0.

x <- matrix(c(65,46,52,76,34,345,65,87,12,53),nrow = 5,ncol = 2)
rows <- c(1,1,2,3,3,4,5)
cols <- c(1,2,2,1,2,1,2)
coords <- paste(rows,cols)
numRows <- 5
numCols <- 2
for (i in 1:numRows){
  for (j in 1:numCols){
    if (!(paste(i,j) %in% coords)){
      x[i,j] <- 0
    }
  }
}

Upvotes: 0

Related Questions