Матрица подмножества в функции mutate() в R

#r #dataframe #matrix #dplyr

#r #фрейм данных #матрица #dplyr

Вопрос:

Проблема

У меня есть простая матрица:

 library(tidyverse)

m <- matrix(seq(1,25), nrow = 5, ncol =5)
m
#>      [,1] [,2] [,3] [,4] [,5]
#> [1,]    1    6   11   16   21
#> [2,]    2    7   12   17   22
#> [3,]    3    8   13   18   23
#> [4,]    4    9   14   19   24
#> [5,]    5   10   15   20   25
 

Эта матрица содержит значения, которые я хотел бы сохранить в качестве третьего столбца в dataframe, который содержит все комбинации индексов:

 library(tidyverse)
df <- expand_grid(V1 = 1:5, V2 = 1:5)
 

Попытка

 df <- df %>%
    mutate(value = m[V1, V2])
 

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

Ожидаемый результат

 #> # A tibble: 25 x 3
#>       V1    V2   value
#>    <int> <int> <int>
#>  1     1     1     1
#>  2     1     2     6
#>  3     1     3    11
#>  4     1     4    16
#> and so on...
 

Вопрос

Как мне это сделать с помощью mutate в R?

Примечание

Я знаю, что в этом случае я мог бы просто изменить данные. Однако я хотел бы применить тот же подход к многомерному массиву (т. Е. , mutate(value = m[V1,V2,V3]) , Который содержит только подмножество комбинаций индексов. Надеюсь, вопрос ясен, в противном случае: дайте мне знать :)!

Ответ №1:

Использовать cbind :

 df %>%
  mutate(value = m[cbind(V1, V2)])
# # A tibble: 25 x 3
#       V1    V2 value
#    <int> <int> <int>
#  1     1     1     1
#  2     1     2     6
#  3     1     3    11
#  4     1     4    16
#  5     1     5    21
#  6     2     1     2
#  7     2     2     7
#  8     2     3    12
#  9     2     4    17
# 10     2     5    22
# # ... with 15 more rows
 

И он работает с n-мерными массивами (a matrix — это 2-тусклый массив, так что это естественное расширение этого):

 m <- array(seq_len(5^3), dim=c(5, 5, 5))
expand_grid(V1 = 1:2, V2 = 2:3, V3 = 3:4) %>%
  mutate(value = m[cbind(V1, V2, V3)])
# # A tibble: 8 x 4
#      V1    V2    V3 value
#   <int> <int> <int> <int>
# 1     1     2     3    56
# 2     1     2     4    81
# 3     1     3     3    61
# 4     1     3     4    86
# 5     2     2     3    57
# 6     2     2     4    82
# 7     2     3     3    62
# 8     2     3     4    87
 

Комментарий к обсуждению для использования rowwise :

rowwise полезна в очень специфических ситуациях и несет в себе немалое снижение производительности. Ее полезность заключается в том, что нужные вам функции не векторизуются, вместо этого требуется один ввод (из нуля или более моделей) за раз. Часто я считаю, что лучше явно выполнять вычисления такого типа, используя sapply / lapply / vapply / mapply (базовый R) или purrr::map* варианты. Хотя эффект относительно одинаков (вычисления выполняются поэлементно), для меня он немного понятнее и позволяет выполнять вычисления не по строкам в одном и том же mutate (и исключает случайное забывание в ungroup строковом фрейме).