Skip to content

Matrix indexing in a loop

4 messages · Mills, Jason, Gabor Grothendieck

#
For 2d here is a solution based on zoo.  It turns the matrix into
a time series and lags it forwards and backwards and does the
same for its transpose in order to avoid index machinations.
The function is called rook2 and it first defines three local
functions, one that converts NAs to zero, one that does
a lag using na.pad = TRUE and one to invoke Lag and
add up the lags:

library(zoo)
rook2 <- function(x, i = 1) {
   na2zero <- function(x) ifelse(is.na(x), 0, x)
   Lag <- function(x, i) na2zero(lag(zoo(x), i, na.pad = TRUE))
   Rook <- function(x, i) Lag(x, i) + Lag(x, -i) + t(Lag(t(x), i) +
Lag(t(x), -i))
   Rook(x, i) / Rook(1+0*x, i)
}

# test
m <- matrix(1:24, 6)
rook2(m)
On 2/17/06, Mills, Jason <Jason.Mills at afhe.ualberta.ca> wrote:
#
Thought about this some more and here is a solution that
works with 2d and 3d (and higher dimensions).

inner is a generalized inner product similar to a function
I have posted previously and f(x,y) is an inner product such
that f(x,y) is TRUE if abs(x - y) == order (after converting
both x and y to numeric) and FALSE otherwise.  Root then
uses as.data.frame.table to turn the array into data frames
with the last column having
the data and the other columns representing the indexes.
We then perform the inner product and use the resulting
matrix to multiply c(x) which is the input strung out
into a vector reshaping it back into the same shape as x.
Finally we divide each cell by the number of surrounding
cells.

root3 <- function(x, order = 1) {
	f <- function(x,y) sum(abs(as.numeric(x) - as.numeric(y))) == order
	inner <- function(a,b,f)
			apply(b,1,function(x)apply(a,1,function(y)f(x,y)))

	Root <- function(x) {
		n <- length(dim(x))
		dd <- sapply(as.data.frame.table(x)[,-n-1], as.numeric)
		structure(inner(dd, dd, f) %*% c(x), .Dim = dim(x))
	}
	Root(x) / Root(1+0*x)
}

# tests
m <- matrix(1:24, 6) # 2d
root3(m)
mm <- array(1:24, 2:4)  # 3d
root3(mm)
On 2/17/06, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
#
There was an error in the function f -- it only worked correctly if
order was 1.  Here it is with that fixed.  The function f is the
only thing changed from my last post.  It makes use of the
fact that sum(x) == n and sum(x*x) == n*n  only occur when
one element of x is n and the rest are 0.

root3 <- function(x, order = 1) {
	f <- function(x,y) {
		z <- abs(as.numeric(x) - as.numeric(y))
		(sum(z) == order) & (sum(z*z) == order * order)
	}
	inner <- function(a,b,f)
			apply(b,1,function(x)apply(a,1,function(y)f(x,y)))

	Root <- function(x) {
		n <- length(dim(x))
		dd <- sapply(as.data.frame.table(x)[,-n-1], as.numeric)
		structure(inner(dd, dd, f) %*% c(x), .Dim = dim(x))
	}
	Root(x) / Root(1+0*x)
}

# tests
m <- matrix(1:24, 6) # 2d
root3(m)
mm <- array(1:24, 2:4)  # 3d
root3(mm)
On 2/17/06, Gabor Grothendieck <ggrothendieck at gmail.com> wrote: