2016-05-04 8 views
3

Gibt es eine Möglichkeit, den folgenden Ersatz in einer einzigen Zeile in R zu tun? Wenn möglich, wäre es mehr/weniger effizient?Mehrere Ersetzungen innerhalb einer Matrix in einer einzelnen Zeile in R

m <- matrix(rnorm(100), ncol=10) 

threshold <- 0.5 

# Is there a single-line way to do the following in R 
m[m < threshold] <- 0 
m[m >= threshold] <- 1 

Ich frage mich, ob die ifelse() Funktion diese aufnehmen kann, im Sinne von wenn < Schwelle dann 0, sonst 1

Antwort

7

Da Sie einen Vektor von 1 und 0 möchten, können Sie einfach Umkehren Sie Ihre Bedingung, konvertieren Sie die logischen Werte in Integer und erstellen Sie eine neue Matrix mit den gleichen Dimensionen wie m.

matrix(as.integer(m >= threshold), nrow(m)) 

Sie können auch einfach den Matrix-Modus ändern. Normalerweise Modi ändern in zwei Linien durchgeführt werden würde, aber man kann es mit

`mode<-`(m >= threshold, "integer") 

Zusätzlich in einem tun, als @nicola betont, ist die schnelle und schmutzige Methode

(m >= threshold) + 0L 

die Null Durch das Hinzufügen Integer wir zwingen die gesamte Matrix zu Integer.

Ein paar andere (dank @Frank):

+(m >= threshold) 
m[] <- m >= threshold 

Also im Grunde ja. Alle diese führen die Aufgabe in einer Linie durch und ich kann fast garantieren, dass sie alle schneller sind als ifelse().

Einige Benchmarks auf einer größeren Matrix (mit dem Ersatz-Verfahren weggelassen):

m <- matrix(rnorm(1e7), ncol=100) 
threshold <- 0.5 

library(microbenchmark) 

microbenchmark(
    matrix = matrix(as.integer(m >= threshold), nrow(m)), 
    mode = `mode<-`(m >= threshold, "integer"), 
    plus0 = (m >= threshold) + 0L, 
    unary = +(m >= threshold) 
) 

# Unit: milliseconds 
# expr  min  lq  mean median  uq  max neval 
# matrix 295.9292 315.4463 351.9149 351.8144 379.9840 453.4915 100 
# mode 163.2156 172.0180 208.9348 202.8014 232.4525 347.0616 100 
# plus0 170.2059 177.6111 202.3536 192.3516 223.8284 294.8367 100 
# unary 144.0128 150.2696 183.2914 173.4010 203.7955 382.2397 100 

Aus Gründen der Vollständigkeit, hier ein Maßstab auf der Ersatzmethode ist times = 1 verwenden.

microbenchmark(
    replacement = { m[] <- m >= threshold }, 
    times = 1 
) 
# Unit: milliseconds 
#   expr  min  lq  mean median  uq  max neval 
# replacement 499.4005 499.4005 499.4005 499.4005 499.4005 499.4005  1 
+0

groß - liebe es – Megatron

+1

Auch '(m> = Schwelle) + 0L'. – nicola

+2

@nicola Wenn Sie sich mit obskuren Zwängen zufrieden geben, können Sie auch '+ (m> = Schwellwert)' ' – Frank

Verwandte Themen