2016-03-21 7 views
2

Ich habe eine Matrix namens "ft", ein Ergebnis einiger logischer Tests. Hier ist das Beispiel, eine Matrix von [10,5]. In der realen Arbeit wird es Tausende von Zeile, mehr Spalte und um Hunderte von Matrix.R Programmierung: Logischer Test der vorherigen/vorhergehenden/aufeinanderfolgenden Spalte

 [,1] [,2] [,3] [,4] [,5] 
[1,] 1 1 1 1 1 
[2,] 1 1 1 1 1 
[3,] 0 1 1 1 1 
[4,] 1 1 1 1 1 
[5,] 1 1 1 1 1 
[6,] 1 1 1 1 1 
[7,] 1 1 1 1 1 
[8,] 1 1 1 1 1 
[9,] 1 1 1 1 1 
[10,] 1 0 1 1 1 

Ich muss einen logischen Test des Werts aus der vorherigen Spalte durchführen. Wenn der Wert aus der vorherigen Spalte Null ist, ist der Rest der Spalte Null. Zum Beispiel ist der Wert von Vektor [3,1] Null, daher wird der Rest der Spalte in Zeile [3,] Null sein. Ebenso das Element in [10,2] Null ist, also die Zeile [10,3:5] wird Null So das Ergebnis in einer neuen Matrix wird so sein:

 [,1] [,2] [,3] [,4] [,5] 
[1,] 1 1 1 1 1 
[2,] 1 1 1 1 1 
[3,] 0 0 0 0 0 
[4,] 1 1 1 1 1 
[5,] 1 1 1 1 1 
[6,] 1 1 1 1 1 
[7,] 1 1 1 1 1 
[8,] 1 1 1 1 1 
[9,] 1 1 1 1 1 
[10,] 1 0 0 0 0 

Ich bin völlig neu in R, habe ich mehrere Alternative wie die versuchten folgende:

ctes=cbind(ftes[,1], (ftes[,2:t]==1 & ctes[,-1]==1)) 

Aber es ist völlig falsch. Wie man dies effizient mit der vektorisierten Methode anstelle des Schleifentests durchführt.

Antwort

2

Ich glaube nicht, Base R eine vektorisiert Weise bietet diese zu lösen, aber man konnte das matrixStats Paket versuchen, wenn Effizienz

matrixStats::rowCummins(ft) 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 1 1 1 1 1 
# [2,] 1 1 1 1 1 
# [3,] 0 0 0 0 0 
# [4,] 1 1 1 1 1 
# [5,] 1 1 1 1 1 
# [6,] 1 1 1 1 1 
# [7,] 1 1 1 1 1 
# [8,] 1 1 1 1 1 
# [9,] 1 1 1 1 1 
# [10,] 1 0 0 0 0 

wichtig ist ein Maßstab für eine 200MB große Matrix

set.seed(123) 
Bigft <- matrix(sample(0:1, 5e7, replace = TRUE), ncol = 100) 
system.time(matrixStats::rowCummins(Bigft)) 
# user system elapsed 
# 0.08 0.01 0.10 
+0

Nette Funktion, die du dort gefunden hast (+1). Es sollte jedoch darauf hingewiesen werden, dass diese Lösung eine Matrix mit nur 1 und 0 Werten benötigt. Obwohl diese Bedingung in dem vom OP beschriebenen Fall erfüllt zu sein scheint, wird dies nicht ausdrücklich erwähnt. – RHertel

+0

@RHertel, yeah Ich realisiere das, aber der Benutzer sagte, dass die Matrix ein Ergebnis einiger "* logischer Tests *" ist - also denke ich, es sollte immer eine binäre Matrix sein. –

+0

@DavidArenburg wow! das ist mächtig. Vielen Dank für Ihre Antwort, es funktioniert und ausreichend für meinen Fall oben. Prost. – mnx

1

Es könnte ein einfacher Weg, aber dies sollte funktionieren:

zeros <- which(ft==0,arr.ind=TRUE) 
sapply(1:nrow(zeros), function(x) ft[zeros[x,1], zeros[x,2]:ncol(ft)] <<- 0) 
#> ft 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] 1 1 1 1 1 
# [2,] 1 1 1 1 1 
# [3,] 0 0 0 0 0 
# [4,] 1 1 1 1 1 
# [5,] 1 1 1 1 1 
# [6,] 1 1 1 1 1 
# [7,] 1 1 1 1 1 
# [8,] 1 1 1 1 1 
# [9,] 1 1 1 1 1 
#[10,] 1 0 0 0 0 

Diese nicht vektorisiert wird, aber die Schleife erstreckt sich nur über die Zeilen eine Null ist, und nicht die gesamte Matrix enthält. Abhängig von der Dichte der Matrix kann dies einen großen Unterschied machen oder auch nicht.

Daten

ft <- structure(c(1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
     1L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
     1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
     1L, 1L, 1L, 1L, 1L), .Dim = c(10L, 5L), .Dimnames = list(NULL, NULL)) 
+1

Oder mit 'apply' und' cummin', d. h. 't (apply (ft, 1, Funktion (x) cummin (x)))' – akrun

+0

@Rhetel danke für die Antwort, aber ich muss für den Moment mit dem von David gehen. – mnx