Как эффективно выполнять поэлементное умножение двух матриц в r

Я хочу выполнить поэлементное умножение двух больших матриц, я хочу сделать это максимально эффективно.

В настоящее время я использую базовый оператор *

Например, если у меня есть DF1, подобный следующему:

А Б 1 2 3 4

и DF2, подобный следующему:

Икс Да 5 6 7 8

DF1*DF2 приводит к

Икс Да 5 12 21 32

как я могу сделать это быстрее?

оператор base * это так медленно?

Derf 17.05.2024 04:13

Имена DF1 и DF2 предполагают, что у вас есть фреймы данных, а не матрицы. Если бы они на самом деле были матрицами, умножение было бы быстрее, поэтому используйте as.matrix, чтобы сначала преобразовать каждую из них в матрицы, а затем выполнить умножение.

G. Grothendieck 17.05.2024 04:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
82
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ниже представлено несколько возможных вариантов, и вы сможете выбрать тот, который вам по душе.

Для скорости можете попробовать метод в f3()

set.seed(0)
A <- as.data.frame(matrix(runif (100), 10, 10))
B <- as.data.frame(matrix(runif (100), 10, 10))

f1 <- function() A * B
f2 <- function() as.data.frame(as.matrix(A) * as.matrix(B))
f3 <- function() as.data.frame(`dim<-`(unlist(A, FALSE, FALSE) * unlist(B, FALSE, FALSE), dim(A)))
f4 <- function() list2DF(Map(`*`, A, B))

microbenchmark(
    f1(),
    f2(),
    f3(),
    f4(),
    check = "equal",
    unit = "relative"
)

и ты увидишь

Unit: relative
 expr       min        lq     mean    median        uq       max neval
 f1() 19.315789 18.795854 9.927453 16.090020 14.320574 1.0078119   100
 f2()  5.318182  5.192839 3.243506  4.736301  4.274322 0.7957232   100
 f3()  1.000000  1.000000 1.000000  1.000000  1.000000 1.0000000   100
 f4()  3.533493  3.342965 2.057707  2.988258  2.640750 0.6603172   100

Если вам не нужно сохранять оба A и B, вы можете обновить один из них по ссылке с помощью collapse::setop, что будет быстрее, чем любая базовая версия A*B. Разница во времени более очевидна при использовании больших матриц:

library(collapse)

set.seed(0)
A <- as.data.frame(matrix(runif (1e4), 100, 100))
B <- as.data.frame(matrix(runif (1e4), 100, 100))

f1 <- function() A * B
f2 <- function() as.data.frame(as.matrix(A) * as.matrix(B))
f3 <- function() as.data.frame(`dim<-`(unlist(A, FALSE, FALSE) * unlist(B, FALSE, FALSE), dim(A)))
f4 <- function() list2DF(Map(`*`, A, B))
f5 <- function() setop(AA, "*", B)

Для теста нам нужно добавить setup = {AA <- A*1}, потому что AA обновляется по ссылке каждый раз, когда вызывается f5.

microbenchmark::microbenchmark(
  f1(),
  f2(),
  f3(),
  f4(),
  f5(),
  setup = {AA <- A*1},
  check = "equal",
  unit = "relative"
)
#> Unit: relative
#>  expr       min         lq      mean    median        uq       max neval
#>  f1() 246.80887 269.968102 229.09017 334.57839 333.18018 16.703191   100
#>  f2()  53.29693  51.886762  46.97326  52.85084  75.09009  6.544267   100
#>  f3()  10.31741   9.972887  12.58650  10.11263  13.70399 16.416862   100
#>  f4()  35.90785  34.858054  36.90257  38.21005  57.01931  5.161036   100
#>  f5()   1.00000   1.000000   1.00000   1.00000   1.00000  1.000000   100

Другие вопросы по теме