R — изменение значений матрицы на основе индексов другой матрицы

#r #matrix

#r #матрица

Вопрос:

У меня есть две матрицы:

 m1 <- matrix(runif(750), nrow = 50, byrow=T)
m2 <- matrix(rep(TRUE,750), nrow = 50, byrow=T)
  

Для каждой m1 строки мне нужно найти индексы двух наименьших значений. Затем мне нужно использовать оставшиеся индексы (т. Е. Не Два самых низких значения) для назначения FALSE m2 .

Это довольно легко сделать для одной строки:

 ind <- order(m1[1,], decreasing=FALSE)[1:2]
m2[1,][-ind] <- FALSE
  

Поэтому я могу использовать цикл, чтобы сделать то же самое для всех строк:

 for (i in 1:dim(m1)[1]){
  
  ind <- order(m1[i,], decreasing=FALSE)[1:2]
  m2[i,][-ind] <- FALSE
  
}
  

Однако в моем наборе данных этот цикл выполняется медленнее, чем хотелось бы (поскольку мои матрицы довольно большие — 500000×150000).

Есть ли более быстрый R способ добиться того же результата без использования циклов?

Ответ №1:

Вы можете попробовать следующий код

 m2 <- t(apply(m1,1,function(x) x %in% head(sort(x),2)))
  

Комментарии:

1. возможно, аргумент «partial = 2» для сортировки может ускорить его, если матрицы действительно большие

Ответ №2:

Вы можете попробовать apply , поскольку у вас есть матрица :

 val <- rep(TRUE, ncol(m1))
m3 <- t(apply(m1, 1, function(x) {val[-order(x)[1:2]] <- FALSE;val}))
  

Комментарии:

1. Поскольку это был самый быстрый вариант для моего набора данных, я принимаю его как ответ.

Ответ №3:

Вы можете сделать:

 m2 <- t(apply(m1, 1, function(x) rank(x)<3))
  

Ответ №4:

Использование pmap

 library(purrr)
pmap_dfr(as.data.frame(m1), ~ min_rank(c(...)) < 3)