Заменить значения вдоль первого из n измерений массива - PullRequest
0 голосов
/ 02 января 2019

РЕДАКТИРОВАТЬ: я упростил пример и функции после комментария @jdorbes.Надеюсь, это улучшит пост.

У меня есть серия N-мерных массивов, которые мне нужно «вращать» вдоль их первого измерения (например, в 2-мерной матрице, переключаясь между собой в первой и второй половинеколонны).Например, рассматривая трехмерный случай, я могу определить свой массив следующим образом:

field <- array(1:32, c(4, 4, 2))

Я разработал очень базовую и зависящую от размера функцию, которая достигает цели.Конечно, эту же операцию можно выполнить и с head и tail, но я обнаружил, что это более быстрый способ:

rotate.test <- function(field) {
  xxx <- field
  dims <- length(dim(xxx))
  if (dims == 2) { # for x,y data
      ll <- length(field[, 1])
      field[(ll * 0.5 + 1  ):ll, ] <- xxx[1:(ll * 0.5), ]
      field[1:(ll * 0.5), ] <- xxx[(ll * 0.5  + 1):ll, ]
  }
  if (dims == 3) { # for x,y,t data
      ll <- length(field[, 1, 1]) 
      field[(ll * 0.5 + 1 ):ll, , ] <- xxx[1:(ll * 0.5), , ]
      field[1:(ll * 0.5), , ] <- xxx[(ll * 0.5 + 1):ll, , ]
  } 
    return(field)
}

Результат читается как:

> rotate.test(field)
, , 1

     [,1] [,2] [,3] [,4]
[1,]    3    7   11   15
[2,]    4    8   12   16
[3,]    1    5    9   13
[4,]    2    6   10   14

, , 2

     [,1] [,2] [,3] [,4]
[1,]   19   23   27   31
[2,]   20   24   28   32
[3,]   17   21   25   29
[4,]   18   22   26   30

Это может быть дополнительно обобщено для N-мерных данных, но я думаю, вы видите, что это очень неуклюже.После этого поста Выберите по одному из n измерений в массиве Я обнаружил, что могу обобщить его, введя очень полезный вызов функции do.call:

array_indexing <- function(field, dim, value, drop = FALSE) {
  indices <- rep(list(bquote()), length(dim(field)))
  indices[[dim]] <- value
  out <- do.call("[",c(list(field), indices, list(drop = drop)))
  return(out)
}

Затем с помощью abind

rotate.evo <- function(field) {
 require("abind")
 xdim <- 1
 ll <- dim(field)[xdim]
 firstchunk <- array_indexing(field, xdim, (ll * 0.5 + 1):ll)
 secondchunk <- array_indexing(field, xdim, 1:(ll * 0.5))
 out <- abind(firstchunk, secondchunk, along = 1)
 return(out)
}

Однако сравнительный анализ (выполненный с rbenchmark) очень вероятен из-за вызова abind вместо более простой замены индекса.

                test replications elapsed relative user.self sys.self
2  rotate.evo(field)         1000   0.547     6.36     0.542    0.005
1 rotate.test(field)         1000   0.086     1.00     0.069    0.016
  user.child sys.child
2          0         0
1          0         0

Вот оновозникает мой вопрос: есть ли способ обобщить замену индекса, как это делается с помощью функции array_indexing?Другими словами, есть ли способ выполнить это переключение быстро и надежно без написания специальных случаев для каждого измерения?Я пытаюсь выяснить, существует ли в R метод для обобщения замены некоторого индекса массива по определенному измерению.

Я знаю, что это может звучать странно, но было бы здорово, если бы я могИзбегайте загрузки дополнительных пакетов.Этот код включен в онлайн-инструмент, который должен быть как можно легче (на самом деле, я тоже пытаюсь избавиться от abind!)

Спасибо за любую подсказку, и, пожалуйста, спросите, не является ли какая-либо часть моего объяснения неполной,Бест, Паоло

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...