2016-05-21 7 views
0

unique() entfernt doppelte Elemente eines Vektors und dupliziert Zeilen eines Arrays.is.element() für mehr als eine Variable

, %in% und match() funktioniert nur auf Vektoren (oder NULL).

Gibt es Wertevergleichsoperationen für mehrere Variablen? (z. B. Zeilen eines Arrays)

Meine aktuelle Problemumgehung ist dies. Es ist nicht sehr elegant, und es ist offensichtlich empfindlich für "_" -Matching.

match.multiple <- function (x, table, nomatch = NA_integer_, incomparables = NULL) { 
    x_vector <- apply(x, 1, paste, collapse="_") 
    table_vector <- apply(table, 1, paste, collapse="_") 
    match(x_vector, table_vector, nomatch, incomparables)} 

is.element.multiple <- "%in.multiple%" <- function (el, set) match.multiple(el, set, 0) > 0 

Edit: Hinzufügen eines reproduzierbaren Beispiel

können sagen, dass Sie ein Auto kaufen wollen, die eine gleiche Anzahl von Vorwärtsgängen und Vergasern hat. Es kann 1-Stück, 2-Stück usw. sein. Sie wissen nicht, ob die Autos, die auf dem Markt verfügbar sind (cf. mtcars) mit Ihren Präferenzen entsprechen.

preferences <- cbind(1:8, 1:8) 
available <- cbind(mtcars$gear, mtcars$carb) 

So haben Sie eine passende für beide Variablen: Getriebe und Vergasern.

m <- match.multiple(preferences, available) 
m 
# [1] NA NA 12 1 NA NA NA NA 
which(!is.na(m)) 
# [1] 3 4 

Dies sind die Anzahl der Vorwärtsgänge und Vergaser, die in gleichen Mengen kommen.

willbuy <- m[!is.na(m)] 
mtcars[willbuy, ] 
#  mpg cyl disp hp drat wt qsec vs am gear carb 
# 1: 16.4 8 275.8 180 3.07 4.07 17.40 0 0 3 3 
# 2: 21.0 6 160.0 110 3.90 2.62 16.46 0 1 4 4 

Und das sind Katalogeinträge für Autos, die Sie beachten sollten.

+0

@dww Es ist nicht das Gleiche: es wird ein Spiel für 'c („A“,„C“)' in 'rbind finden (c ("A", "B"), c ("C", "D")) ' – 9877126

+0

ok Ich habe die Frage missverstanden. Dachte, du wolltest ein Objekt in mehreren Objekten finden.Anscheinend möchten Sie auch das Auftreten einer Liste als Teilmenge innerhalb eines Arrays oder einer Liste von Listen testen. Möglich, die Frage zu bearbeiten, um dies deutlicher zu machen? – dww

+0

@dww Ich möchte keine Listen in meine Frage aufnehmen - es macht es nur komplizierter. Aber ich möchte es klarstellen. ** Ich möchte Reihen einer Matrix mit Reihen einer anderen Matrix zusammenbringen. ** – 9877126

Antwort

0

Eine Funktion Vorkommnissen eines Vektors innerhalb der Reihen eines Arrays zu finden:

Um zu testen, ob ein Vektor (v) ist eine Zeile einer Matrix oder einer Matrix (m), kann man eine zweite Matrix-Konstrukt die gleichen Abmessungen wie das wollen wir ihnen suchen, aber die aus wiederholten Reihen des Vektors wir suchen, und überprüfen, ob alle Zeilen in diesem konstruierten Array identisch sind mit dem ursprünglichen

is.row.in.rows <- function(v,m) { 
    which(length(v) == rowSums(m == matrix(v, nrow(m), ncol(m), byrow=TRUE))) 
} 

Beachten sie, dass es Es ist auch möglich, denselben Test mit einer Schleife unter Verwendung von which(apply(m, 1, all.equal, v) == TRUE) durchzuführen. Aber die obige vektorisierte Version mit rowSums ist schneller.

dieser Funktion die reproduzierbare Beispiel in der Frage zu lösen:

a <- unlist(apply(preferences, MARGIN = 1, is.row.in.rows, available)) 
a 
# [1] 12 13 14 1 2 10 11 

mtcars[a,] 
#    mpg cyl disp hp drat wt qsec vs am gear carb 
# Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 
# Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 
# Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 
# Mazda RX4  21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 
# Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 
# Merc 280  19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 
# Merc 280C  17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 
+0

Die 'is.row.in.rows' Funktion wirft ein Fehler beim Vergleich von Arrays unterschiedlicher Größe (wie im vorherigen Beispiel): 'm <- matrix (1:25, 5); v <- rep (1, 6); is.row.in.rows (v, m) ' Sie sollten dies versuchen:' any (apply (m, 1, identisch, v)) '- was empfindlich auf Klassenunterschied ist. Oder das: 'any (anwenden (m, 1, all.equal, v) == TRUE) - was nicht ist. – 9877126

+0

Ich habe nicht bemerkt, dass Sie den Code Ihrer Funktion geändert haben. Der obige Kommentar gilt ohne das 'was'. Die aktuelle Version von 'is.row.in.rows' sollte mit' which (apply (m, 1, all.equal, v) == TRUE) 'verglichen werden. – 9877126

+0

Ja, das ist ähnlich, aber nicht genau das Gleiche. all.equal test, wenn Objekte nahezu identisch und nicht identisch sind. Und ich denke, dass rowsSums schneller sein kann als anwenden (all.equal) – dww

1

Wie ich in den Kommentaren erwähnt, kann meine Antwort auf this question angepasst werden, dieses Problem zu lösen. Hier ist, wie es getan werden kann, mit der OP der reproduzierbaren Beispiel demonstriert:

avail <- cbind(mtcars$gear,mtcars$carb); 
prefs <- cbind(1:8,1:8); 
do.call(rbind,apply(prefs,1L,function(x) mtcars[findarray(avail,matrix(x,1L))[,1L],])); 
##    mpg cyl disp hp drat wt qsec vs am gear carb 
## Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 
## Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 
## Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 
## Mazda RX4  21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 
## Merc 280  19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 
## Merc 280C  17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 
+0

Trotz all meiner Bemühungen konnte ich Rtools nicht richtig installieren. Wenn wir jedoch 'findarray (avail, matrix (x, 1L)) [, 1L]' in Ihrem Code ändern, um 'apply (avail, 1, all.equal, x) == TRUE' anzuwenden, erhalten Sie das gleiche Ergebnis - - ohne Notwendigkeit für gcc. Ich verstehe, dass Ihr n-dimensionaler Submatrixfinder ein viel mächtigeres Werkzeug ist, ich kann einfach nicht sehen, wie wir seine Stärken hier ausnutzen könnten. – 9877126

+0

Dies sollte sogar schneller als @ dww Lösung sein, da es in C++ geschrieben ist. Es ist nicht so einfach zu bedienen, da es mehrere Komplikationen mit einem funktionierenden Rtools gibt. [#bitterexperience] (https://cran.r-project.org/doc/manuals/R-admin.html#The-Windows-toolset) – 9877126

Verwandte Themen