2016-06-29 6 views
1

Ich bin auf der Suche nach einem schnellen Weg, um die Indizes von Spalten einer Matrix, die Werte in einem Vektor (idealerweise der Länge 1 oder die gleiche wie die Zahl der Reihen in der Matrix) zB:Matrix - Spaltenindizes mit passenden Werten zurücksenden in R

mat <- matrix(1:100,10) 
values <- c(11,2,23,12,35,6,97,3,9,10) 

die gewünschte Funktion, die ich rowMatches() nennen würde zurück:

rowMatches(mat, values) 
[1] 2 1 3 NA 4 1 10 NA 1 1 

Tatsächlich Wert 11 wird zuerst an der 2. Spalte der ersten Zeile gefunden wird, Wert 2 erscheint in der 1. Spalte der 2. Zeile, Wert 23 i s in der 3. Spalte der 3. Zeile, Wert 12 ist nicht in der 4. Zeile ... und so weiter.

Da ich keine Lösung im Paket matrixStats gefunden haben, kam ich mit dieser Funktion auf:

rowMatches <- function(mat,values) {    
    res <- integer(nrow(mat)) 
    matches <- mat == values 
    for (col in ncol(mat):1) { 
     res[matches[,col]] <- col 
    } 
    res[res==0] <- NA 
    res 
} 

Für meine bestimmungsgemäßen Gebrauch, wird es Millionen von Zeilen und Spalten wenige sein. Also wäre es viel zu langsam, die Matrix in Zeilen aufzuteilen (in einer Liste, die beispielsweise rows heißt) und Map(match, as.list(values), rows) aufzurufen.
Aber ich bin nicht zufrieden mit meiner Funktion, weil es eine Schleife gibt, die langsam sein kann, wenn es viele Spalten gibt. Es sollte möglich sein, apply() auf Spalten zu verwenden, aber es wird es nicht schneller machen.

Irgendwelche Ideen?

+1

Siehe 'max.col' - man könnte verwenden' max.col (Streichhölzer, "erste") 'und benutze 'NA' wo immer' rowSums (matches) == 0L' –

+0

Großartig! Ich wusste nicht über 'max.col()'. Sie können diese Lösung posten und ich werde sie validieren. (Für mtoto gibt es eine "NA" am entsprechenden Index in den Ergebnissen) – jeanlain

Antwort

0
res <- arrayInd(match(values, mat), .dim = dim(mat)) 
res[res[, 1] != seq_len(nrow(res)), 2] <- NA 
#  [,1] [,2] 
# [1,] 1 2 
# [2,] 2 1 
# [3,] 3 3 
# [4,] 2 NA 
# [5,] 5 4 
# [6,] 6 1 
# [7,] 7 10 
# [8,] 3 NA 
# [9,] 9 1 
#[10,] 10 1 
0

Roland Antwort ist gut, aber ich werde eine alternative Lösung abgeben:

res <- which(mat==values, arr.ind = T) 
res <- res[match(seq_len(nrow(mat)), res[,1]), 2]