Скользящая сумма матриц в списке - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть список матриц одинакового размера:

a <- matrix(data = c(1,2,3,4,5,6,7,8,9), ncol = 3, nrow = 3)

b <- matrix(data = c(9,8,7,6,5,4,3,2,1), ncol = 3, nrow = 3)

c <- matrix(data = c(1,2,3,4,5,6,7,8,9), ncol = 3, nrow = 3)

d <- matrix(data = seq(from = 1, to = 9, by = 1), ncol = 3, nrow = 3)

e <- matrix(data = seq(from = 10, to = 90, by = 10), ncol = 3, nrow = 3)

f <- matrix(data = seq(from = 9, to = 1, by = -1), ncol = 3, nrow = 3)


test_list <- list(a, b, c, d, e, f)

Как можно суммировать каждый набор из трех матриц, чтобы на выходе были две матрицы, первая из которых равна сумме a, b и c (output_1), а вторая - сумме d, e и f (output_2)? В идеале на выходе должен быть новый список из двух матриц, например,

output_1 <- structure(c(11, 12, 13, 14, 15, 16, 17, 18, 19), .Dim = c(3L, 
3L)) 

output_2 <- structure(c(3L, 6L, 9L, 12L, 15L, 18L, 21L, 24L, 27L), .Dim = c(3L, 
3L))

Ответы [ 5 ]

0 голосов
/ 06 ноября 2018

Просто каракули с data.table:

data.table::rbindlist(lapply(test_list, function(x) as.data.frame(x)))[, as.list(colSums(.SD)), 
                                     by = gl(ceiling(length(test_list)*nrow(test_list[[1]])/3), 
                                     3, length(test_list)*nrow(test_list[[1]]))]
0 голосов
/ 06 ноября 2018

43 секунды назад @iod прокомментировал ту же мысль, что и я. Я представляю это как базовый эквивалент логике map - reduce в ответе Зака:

lapply( split( test_list, cumsum( rep( c(T,F,F), 2))), function(x){ Reduce( "+", x)})
$`1`
     [,1] [,2] [,3]
[1,]   11   14   17
[2,]   12   15   18
[3,]   13   16   19

$`2`
     [,1] [,2] [,3]
[1,]    3   12   21
[2,]    6   15   24
[3,]    9   18   27

В моем приложении используется «Reduce», которое описано на странице справки с группой «funprog» -функций, озаглавленных «Общие функции высшего порядка в языках функционального программирования». Как и в случае с iod, у меня иногда возникали некоторые трудности с функциями Map и Reduce. В этом случае нужно использовать Reduce, а не do.call, потому что «+» является бинарным оператором и не может обрабатывать векторы с 3 элементами. Внутренне это не очень то, что отличается от ответа двойной петли r.user.05apr. И lapply-split, и Reduce действительно скрытые петли.

В настоящее время существует несколько примеров различных механизмов построения "групп из 3". Мой подход состоял в том, чтобы создать логический вектор и затем запустить cumsum, чтобы создать числовой вектор. Масуд использовал gl. zack использовал ceiling(seq_along(test_list)/3) и вежливо зачитал свое вдохновение.

0 голосов
/ 06 ноября 2018

Преобразовать в массив и apply rowSums:

test_array<-array(c(a,b,c,d,e,f),c(3,3,6))
apply(test_array[,1:3,1:3],2,rowSums)

     [,1] [,2] [,3]
[1,]   11   14   17
[2,]   12   15   18
[3,]   13   16   19

apply(test_array[,1:3,4:6],2,rowSums)

     [,1] [,2] [,3]
[1,]    3   12   21
[2,]    6   15   24
[3,]    9   18   27
0 голосов
/ 06 ноября 2018

Или:

Matrix_Number <- 6

res <- vector("list", Matrix_Number / 3)
for (i in (1:(Matrix_Number/3))) {
  res[[i]] <- test_list[[(i-1)*3 + 1]] + test_list[[(i-1)*3 + 2]] + test_list[[(i-1)*3 + 3]]
}
res
0 голосов
/ 06 ноября 2018
library(purrr)
map(split(test_list, ceiling(seq_along(test_list)/3)), ~reduce(.x , `+`))

$`1`
     [,1] [,2] [,3]
[1,]   11   14   17
[2,]   12   15   18
[3,]   13   16   19

$`2`
     [,1] [,2] [,3]
[1,]    3   12   21
[2,]    6   15   24
[3,]    9   18   27

Кредит на этот ответ за аккуратный код разделения.

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