R: разбить матрицу на произвольное количество блоков - PullRequest
2 голосов
/ 24 февраля 2012

Скажите, у меня есть матрица значений

    set.seed(1)
    A <- matrix(runif(25),ncol=5)

Я хотел бы рассчитать некоторую статистику для приблизительно квадратных окрестностей в этой матрице приблизительно равного размера. Любой из этих видов вывода будет делать:

    N1 <-  matrix(c(rep(c("A","A","B","B","B"),2),rep(c("C","C","D","D","D"),3)),ncol=5)
    N2 <-  matrix(c(rep(c("A","A","A","B","B"),3),rep(c("C","C","D","D","D"),2)),ncol=5)
    N1
         [,1] [,2] [,3] [,4] [,5]
    [1,] "A"  "A"  "C"  "C"  "C" 
    [2,] "A"  "A"  "C"  "C"  "C" 
    [3,] "B"  "B"  "D"  "D"  "D" 
    [4,] "B"  "B"  "D"  "D"  "D" 
    [5,] "B"  "B"  "D"  "D"  "D" 

    N2
         [,1] [,2] [,3] [,4] [,5]
    [1,] "A"  "A"  "A"  "C"  "C" 
    [2,] "A"  "A"  "A"  "C"  "C" 
    [3,] "A"  "A"  "A"  "D"  "D" 
    [4,] "B"  "B"  "B"  "D"  "D" 
    [5,] "B"  "B"  "B"  "D"  "D" 

другие приближения тоже в порядке, так как я всегда могу вращать матрицу. Затем я могу использовать эти матрицы окрестностей для вычисления статистики, используя tapply(), например:

    tapply(A,N1,mean)
            A         B         C         D 
    0.6201744 0.5057402 0.4574495 0.5594227

То, что я хочу, - это функция, которая может сделать меня матрицей произвольных измерений с произвольным числом блочных окрестностей, таких как N1 или N2. Я с трудом пытаюсь понять, как такая функция будет справляться с ситуациями, когда желаемое количество блоков даже не является квадратом. N1 и N2 имеют 4 окрестности, но говорят, что я хотел 5 для некоторого вывода что-то вроде этого:

    N3 <-  matrix(c("A","A","B","B","B","A","A","C","C","C","D","D","C","C","C",
            "D","D","E","E","E","D","D","E","E","E"),ncol=5)
         [,1] [,2] [,3] [,4] [,5]
    [1,] "A"  "A"  "D"  "D"  "D" 
    [2,] "A"  "A"  "D"  "D"  "D" 
    [3,] "B"  "C"  "C"  "E"  "E" 
    [4,] "B"  "C"  "C"  "E"  "E" 
    [5,] "B"  "C"  "C"  "E"  "E" 

Кто-нибудь знает о существующей функции, которая может делать такое разделение, или есть какие-либо идеи о том, как ее создать? Спасибо!

[[Изменить]] Моя последняя функция, учитывая советы Винсента:

    DecideBLocks <- function(A,nhoods){
        nc <- ncol(A)
        nr <- nrow(A)
        nhood_side <- floor(sqrt((nc*nr)/nhoods))
        Neighborhoods <- matrix(paste(ceiling(col(A)/nhood_side), ceiling(row(A)/nhood_side), sep="-"), nc=ncol(A)) 
        nhoods.out <- length(unique(c(Neighborhoods)))
        if (nhoods.out != nhoods){
            cat(nhoods.out,"neighborhoods created.\nThese were on average",nhood_side,"by",nhood_side,"cells\nit's a different number than that stated the function tries to round things to square neighborhoods\n")
        }
        return(Neighborhoods)
    }
    A <- matrix(rnorm(120),12)
    B <- DecideBLocks(A,13)

Ответы [ 2 ]

2 голосов
/ 24 февраля 2012

Вы можете попробовать поиграть с функциями row и col: они уменьшают проблему до одномерной.Следующее определяет блоки размером не более 2 * 2.

matrix( 
  paste(
    ceiling(col(A)/2), 
    ceiling(row(A)/2), 
    sep="-"), 
  nc=ncol(A) 
)
1 голос
/ 24 февраля 2012

Вы можете выбрать параметры bdeep (row-spec) и bwide (co-spec) рядом с центром ваших размеров матрицы любым удобным вам способом и использовать эту простую функцию для построения вашей матрицы. Пока bwide и bdeep равны, а nrow == ncol, вы должны получить квадратные подматрицы.

 mkblk <- function(bwide, bdeep, nrow, ncol){
   bstr1 <- c(rep("A", bdeep), rep("B", nrow-bdeep))
   bstr2 <- c(rep("C", bdeep), rep("D", nrow-bdeep))
   matrix(c( rep(bstr1, bwide), rep(bstr2, ncol-bwide)), ncol=ncol, nrow=nrow)}
 mkblk(2,2,5,5)

     [,1] [,2] [,3] [,4] [,5]
[1,] "A"  "A"  "C"  "C"  "C" 
[2,] "A"  "A"  "C"  "C"  "C" 
[3,] "B"  "B"  "D"  "D"  "D" 
[4,] "B"  "B"  "D"  "D"  "D" 
[5,] "B"  "B"  "D"  "D"  "D" 

#Test of your strategy
 tapply(A, mkblk(2,2,5,5), mean)
        A         B         C         D 
0.6201744 0.5057402 0.4574495 0.5594227 
...