javidcf
javidcf

Reputation: 59701

Subsetting a table using a matrix

I'm getting started with R and I'm having problems with a n-dimensional table my.table which I want to subset in various ways. I have a row matrix m that lets me pick a single cell of the table with my.table[m]. Now I want to use m to select a whole row of the table (not only one cell) by indicating one dimension i which I don't want to be sliced. This can be easily done with normal indexing by leaving the i-th position of the index empty, but in my case the value of i is only known at runtime.

I'll try to illustrate it with some code:

# let's assume n = 4
# I can pick a cell value with the literal indexing
a.value <- my.table[2, 1, 4, 2]
# And I can reproduce this with matrix indexing
m <- matrix(c(2, 1, 4, 2), nrow=1)
a.value <- my.table[m]

# Now let's assume i = 3
# I can subset the table with literal indexing to pick the whole row
a.row <- my.table[2, 1, , 2]
# But how can I do the same using the matrix m?

I have tried setting m[i] <- NA and m[i] <- NULL, but obviously it does not work.

Is there some "magical" value equivalent to the empty space in a literal index? Or there is no way of doing this straightforwardly?

UPDATE:

I'll post the code that I am using by now that gives the result I want. Still, it would be great to know if there is a better, more elegant or more general way to do it:

function(my.table, m, i) {
    i.dim <- dim(my.table)[i]
    return(apply(matrix(1:i.dim, nrow=1), 1, function(x) {
        # in my case, I don't need to preserve the original value of m[i]
        m[i] <- x
        return(my.table[m])
    }))
}

UPDATE 2: As requested by @javlacalle, I'm posting the output of dput of the table.

structure(c(0.830412306140461, 0.169587693859539, 0.944833625218914, 
0.0551663747810858, 0.993589743589744, 0.00641025641025641, 1, 
0, 0.992307692307692, 0.00769230769230769, 1, 0, 1, 0, NaN, NaN
), class = "table", .Dim = c(2L, 2L, 2L, 2L), .Dimnames = structure(list(
    V29.0 = c("0", "1"), `779.89` = c("0", "1"), `771.81` = c("0", 
    "1"), `771.89` = c("0", "1")), .Names = c("V29.0", "779.89", 
"771.81", "771.89")))

UPDATE 3:

I've found out that the "magical" value I was talking about actually exists, you can get it with bquote() - only that I don't think there is a way to use it along with other numbers in a matrix to form a proper index.

Upvotes: 2

Views: 89

Answers (1)

konvas
konvas

Reputation: 14346

How about writing e.g. my.table[1, 1, 1, 1:2] instead of my.table[1, 1, 1, ]? You could set the indices that you want to be expanded to 0 (in m) and then define

f <- function(my.table, m) {
    dims <- dim(my.table)
    a <- lapply(1:4, function(x) if (m[, x] == 0) 1:dims[x] else m[, x])
    my.table[a[[1]], a[[2]], a[[3]], a[[4]]]
}

For example

m <- matrix(c(0, 1, 1, 0), nrow = 1)
my.table[, 1, 1, ] # same as my.table[1:2, 1, 1, 1:2]
#      771.89
# V29.0         0           1
#     0 0.8304123 0.992307692
#     1 0.1695877 0.007692308

f(my.table, m)
#      771.89
# V29.0         0           1
#     0 0.8304123 0.992307692
#     1 0.1695877 0.007692308

Upvotes: 1

Related Questions