2016-06-22 8 views
1

Я хочу, чтобы применить функцию к входу матрицы a, эта функция будет изменить первый элемент c[a[1]] и следующие элементы к b[a[i],a[i+1]] начиная с i = 1 до i = ncol(a) - 1.mapply для лучшей производительности

Пример ввода:

a <- matrix(c(1,4,3,1),nrow=1) 
b <- matrix(1:25,ncol=5,nrow=5) 
c <- matrix(4:8,ncol=5,nrow=1) 

ожидается выход:

>a 
4 16 14 3 

#c[a[1]] gave us the first element: 4 
#b[a[1],a[2]] gave us the second element: 16 
#b[a[2],a[3]] gave us the third element: 14 
#b[a[3],a[4]] gave us the fourth element: 3 

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

ответ

8

Шаг 1: с помощью единого индекса для адресации матрицы

В матричных элементах R, хранится в столбцах порядка в вектор , поэтому A[i, j] - это то же самое, что и A[(j-1)*nrow(A) + i]. Рассмотрим пример случайной матрицы 3 на 3:

set.seed(1); A <- round(matrix(runif(9), 3, 3), 2) 

> A 
    [,1] [,2] [,3] 
[1,] 0.27 0.91 0.94 
[2,] 0.37 0.20 0.66 
[3,] 0.57 0.90 0.63 

Теперь эта матрица имеет 3 ряда (nrow(A) = 3). Сравните:

A[2,3] # 0.66 
A[(3-1) * 3 + 2] # 0.66 

Шаг 2: векторизации

Вы можете обратиться несколько элементов матрицы одновременно. Однако вы можете сделать это только с помощью одного режима индексирования (не слишком точно здесь, см. Примечание @ alexis_laz). Например, если вы хотите извлечь A[1,2] и A[3,1], но если вы делаете:

A[c(1,3), c(2,1)] 
#  [,1] [,2] 
# [1,] 0.91 0.27 
# [2,] 0.90 0.57 

Вы фактически получаете блок. Теперь, если вы используете единую индексацию, вы получите то, что вам нужно:

A[3 * (c(2,1) - 1) + c(1,3)] 
# [1] 0.91 0.57 

Шаг 3: получение одного индекса для вашей проблемы

Пусть n <- length(a) и вы хотите, чтобы решить эти элементы b:

a[1] a[2] 
a[2] a[3] 
.  . 
.  . 
a[n-1] a[n] 

Вы можете использовать единый указатель nrow(b) * (a[2:n] - 1) + a[1:(n-1)].

Шаг 4: полное решение

Поскольку у вас есть только один ряд для a и c, следует хранить их в качестве векторов, а не матрицы.

a <- c(1,4,3,1) 
c <- 4:8 

Если вы получили матрицу и не имеют никакого выбора (как в настоящее время они находятся в вашем вопросе), вы можете преобразовать их в векторы по:

a <- as.numeric(a) 
c <- as.numeric(c) 

Теперь, как обсуждалось, мы имеем индекс для адреса b матрицы:

n <- length(a) 
b_ind <- nrow(b) * (a[2:n] - 1) + a[1:(n-1)] 

Вы также адрес a[1] элемента c в качестве первого элемента вашего конечного результата, так что нам нужно concatena т.е: c[a[1]] и b[b_ind] по:

a <- c(c[a[1]], b[b_ind]) 
# > a 
# [1] 4 16 14 3 

Этот подход полностью векторизация, даже лучше, чем *apply семьи.


замечание alexis_laz в

alexis_laz напоминает мне, что мы можем использовать "матрица-индекс", а также, например, мы можем также рассмотреть матрицу b через:

b[cbind(a[1:(n-1)],a[2:n])] ## or b[cbind(a[-n], a[-1])] 

Тем не менее, я думаю, что использование единого индекса немного быстрее, потому что нам нужно получить доступ к индексной матрице по строке, чтобы обратиться к b, поэтому мы платим за задержку памяти, чем с помощью векторного индекса.

+0

Благодарим вас за быстрый ответ. Кажется, что b_ind = b [b_ind] ... Я не понимаю логики этого утверждения b_ind <- nrow (b) * (a [-1] - 1) + a [1: (length (a) -1)] Я проработаю его и посмотрю, лучше ли производительность, чем простой цикл, и вернемся к вам завтра. – Imlerith

+0

должен был дать ему еще одну попытку ... Я понял это сейчас (не знал о R-организационных матрицах таким образом что привело к этому своеобразному отношению) было бы также интересно увидеть применение реализации решения, так как я мало понимаю, как они работают в «сложных» проблемах – Imlerith

+0

Я отредактировал и удалил некоторые из текстов, которые не являются частью ответа (: -). Однако вы можете «откат», если вы считаете это необходимым. (Плюс один - по сути, вы набрали 8 очков). Кроме того, не принимайте всплески серьезно ... – akrun

 Смежные вопросы

  • Нет связанных вопросов^_^