sembrate veramente avere due problemi separati qui.
Problema 1: Data una matrice index
, per ciascuna riga e colonna i
j
si desidera impostare test[i,j]
a 2 se j
appare in fila i
di index
. Questo può essere fatto con l'indicizzazione a matrice semplice, passando una matrice a 2 colonne di indici in cui la prima colonna è le righe di tutti gli elementi che si desidera indicizzare e la seconda colonna è le colonne di tutti gli elementi che si desidera indicizzare:
test[cbind(as.vector(row(index)), as.vector(index))] <- 2
test
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 2 2 0 2 2 2 2 0 2 2
# [2,] 2 0 2 2 2 2 2 0 2 2
# [3,] 2 2 2 2 0 0 2 2 0 0
# [4,] 2 2 0 0 0 2 2 2 0 2
# [5,] 2 2 2 2 0 0 0 0 2 0
# [6,] 0 0 0 0 0 2 2 2 2 0
# [7,] 2 0 2 2 2 2 2 0 0 0
# [8,] 2 0 2 2 2 2 0 2 0 2
# [9,] 2 2 2 2 0 0 2 0 2 2
# [10,] 2 0 2 0 0 2 2 2 2 0
Poiché esegue tutte le operazioni in una singola operazione vettoriale, dovrebbe essere più veloce di eseguire il ciclo delle righe e gestirle singolarmente. Ecco un esempio con 1 milione di righe e 10 colonne:
OP <- function(test, index) {
for (i in 1:nrow(test)){
test[i,index[i,]] <- 2
}
test
}
josliber <- function(test, index) {
test[cbind(as.vector(row(index)), as.vector(index))] <- 2
test
}
test.big <- matrix(0, nrow = 1000000, ncol = 10)
set.seed(1234)
index.big <- matrix(sample.int(10, 1000000*10, TRUE), 1000000, 10)
identical(OP(test.big, index.big), josliber(test.big, index.big))
# [1] TRUE
system.time(OP(test.big, index.big))
# user system elapsed
# 1.564 0.014 1.591
system.time(josliber(test.big, index.big))
# user system elapsed
# 0.408 0.034 0.444
qui, l'approccio vettorizzati è 3.5x più veloce.
Problema 2: si desidera impostare fila i
di test
per order
applicata al corrispondente fila di anyMatrix
. È possibile farlo con apply
:
(test <- t(apply(anyMatrix, 1, order)))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 1 10 7 8 4 5 3 6 2 9
# [2,] 8 7 1 6 3 4 9 5 10 2
# [3,] 4 9 7 1 3 2 6 10 5 8
# [4,] 1 2 6 4 10 3 9 8 7 5
# [5,] 9 6 5 1 2 7 10 4 8 3
# [6,] 9 3 8 6 5 10 1 4 7 2
# [7,] 3 7 2 5 6 8 9 4 1 10
# [8,] 9 8 1 3 4 6 7 10 5 2
# [9,] 8 4 3 6 10 7 9 5 2 1
# [10,] 4 1 9 3 6 7 8 2 10 5
non mi aspetto molto di un cambiamento in fase di esecuzione qui, perché apply
è in realtà solo scorrendo le righe in modo simile a come siete stati loop nella vostra soluzione. Tuttavia, preferirei questa soluzione perché è molto meno la digitazione e il modo più "R" di fare le cose.
Si noti che entrambe queste applicazioni utilizzavano codice piuttosto diverso, che è piuttosto tipico nella manipolazione dei dati R: ci sono molti operatori specializzati diversi e bisogna scegliere quello giusto per la propria attività. Non penso che esista una singola funzione o addirittura un piccolo insieme di funzioni che saranno in grado di gestire tutte le manipolazioni di matrici in cui tale manipolazione si basa su dati di un'altra matrice.
grazie, ma come è cbind più veloce nel primo? Non ci vorrà più tempo del solito ciclo? Hai un punto di riferimento? – rmania
@rmania Ho aggiornato questa risposta per includere un benchmark che mostra che le operazioni di indicizzazione vettorizzate producono aumenti di velocità rispetto alle alternative di looping. In R, la sostituzione di molte operazioni rapide ripetute con una singola operazione che le esegue tutte insieme comporta spesso massicci aumenti di velocità. – josliber