2016-11-20 3 views
1

Ich kenne die richtigen technischen Begriffe für diese Art von Operation nicht, so dass es schwierig war, nach vorhandenen Lösungen zu suchen. Ich dachte, ich würde versuchen, meine eigene Frage zu stellen, und hoffentlich kann mir jemand helfen (oder mir in die richtige Richtung zeigen).Verketten von Gruppen von Vektorzeichenelementen

Ich habe einen Vektor von Zeichen und ich möchte sie in Gruppen von zweien und dreien sammeln. Zur Veranschaulichung hier ist eine vereinfachte Version:

Die Tabelle habe ich:

 
"a" 
"b" 
"c" 
"d" 
"e" 
"f" 

Ich möchte durch den Vektor laufen und verketten Gruppen von zwei und drei Elemente. Dies ist das Endergebnis ich will:

 
"a b" 
"b c" 
"c d" 
"d e" 
"e f" 

Und

 
"a b c" 
"b c d" 
"c d e" 
"d e f" 

I unter Verwendung von for-Schleifen dies der einfachste und schmutzigsten Art und Weise möglich gelöst, aber es dauert eine lange Zeit zu laufen und ich bin überzeugt, es kann effizienter gemacht werden.

Hier ist mein Ghetto-Hack:

t1 <- c("a", "b", "c", "d", "e", "f") 

t2 <- rep("", length(t1)-1) 
for (i in 1:length(t1)-1) { 
    t2[i] = paste(t1[i], t1[i+1]) 
} 

t3 <- rep("", length(t1)-2) 
for (i in 1:length(t1)-2) { 
    t3[i] = paste(t1[i], t1[i+1], t1[i+2]) 
} 

Ich war auf der Suche in sapply und tapply usw., aber ich kann nicht scheinen, um herauszufinden, wie in dem Vektor „das folgende Element“ zu verwenden.

Jede Hilfe wird mit meiner ewigen Dankbarkeit belohnt!

-------------- -------------- bearbeiten

Laufzeiten der Vorschläge mit Eingangsdaten unter Verwendung von ~ 3 Millionen Zeilen:

 
START: [1] "2016-11-20 19:24:50 CET" 

For-loop: [1] "2016-11-20 19:28:26 CET" 

rollapply: [1] "2016-11-20 19:38:55 CET" 

apply(matrix): [1] "2016-11-20 19:42:15 CET" 

paste t1[-length...]: [1] "2016-11-20 19:42:37 CET" 

grep: [1] "2016-11-20 19:44:30 CET" 

Antwort

1

für Gruppen von zwei, wir können dies mit

paste(t1[-length(t1)], t1[-1]) 
#[1] "a b" "b c" "c d" "d e" "e f" 

und für höhere Zahlen, ist eine Option, shift von data.table

library(data.table) 
v1 <- do.call(paste, shift(t1, 0:2, type="lead")) 
grep("NA", v1, invert=TRUE, value=TRUE) 
#[1] "a b c" "b c d" "c d e" "d e f" 

Oder

n <- length(t1) 
n1 <- 3 
apply(matrix(t1, ncol=n1, nrow = n+1)[seq(n-(n1-1)),], 1, paste, collapse=' ') 
+0

Vielen Dank! Ich habe alle drei Lösungen getestet. Mein Eingabevektor hat ungefähr 3 Millionen Elemente und meine For-Schleife verbrachte ungefähr 4 Minuten. Ihre erste Lösung war unglaublich effizient und benötigte nur 20 Sekunden. Das zweitbeste war die Grep-Lösung. Die apply (Matrix) -Lösung verbrachte etwa so viel Zeit wie die for-Schleife. Ich benutze deine erste Version. – CoveredInChocolate

+0

@CoveredInChocolate Der dritte wurde verlangsamt, da 'apply' grundsätzlich einer' for' -Schleife ähnelt. Sie können in 'dat.frame' konvertieren und' do.call (paste, as.data.frame (matrix (t1, .... '' – akrun

+1

) Nun, es scheint, als ob ich dir eine Entschuldigung schulde: Wenn ich meine Tests durchgeführt habe, habe ich n1 <- 2 nicht verwendet, so dass der Vergleich unfair war ! Nach der Korrektur der Anwendung (Matrix-Version verbrachte 3 Minuten (1 Minute weniger als eine Schleife) und nach der Konvertierung in data.frame, es dauerte nur 1 Minute! Das ist eine deutliche Verbesserung. Awesome! :) – CoveredInChocolate

2

Haben Sie den Zoo-Paket in Betracht gezogen? Zum Beispiel

library('zoo') 
input<-c('a','b','c','d','e','f') 
output<-rollapply(data=input, width=2, FUN=paste, collapse=" ") 
output 

kehrt

"a b" "b c" "c d" "d e" "e f" 

Die width Argument steuert, wie viele Elemente verketten. Ich erwarte, dass Sie auch hier Laufzeiten verbessert haben, aber ich habe nicht getestet

+0

Danke für der Vorschlag! Mein Input-Vektor hat ungefähr 3 Millionen Zeilen und Ihre Lösung hat ca. 10 Minuten im Vergleich zu ca. 4 Minuten für die For-Schleife verbracht. Ihr Vorschlag war elegant, aber es sieht so aus, als müssten die Zoo-Entwickler etwas optimieren.) – CoveredInChocolate