2016-11-20 1 views
1

Je ne connais pas les termes techniques appropriés pour ce type d'opération, il a donc été difficile de rechercher des solutions existantes. J'ai pensé que j'essaierais d'afficher ma propre question et j'espère que quelqu'un pourra m'aider (ou me diriger dans la bonne direction). J'ai un vecteur de caractères et je veux les rassembler en groupes de deux et trois. Pour illustrer, voici une version simplifiée:Concaténation de groupes d'éléments de caractères vectoriels

Le tableau que j'ai:

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

Je veux courir à travers le vecteur et les groupes de concaténer deux et trois éléments. Ceci est le résultat final que je veux:

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

Et

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

Je résolu ainsi possible le plus simple et le plus sale en utilisant pour-boucles, mais il prend beaucoup de temps à courir et je suis convaincu cela peut être fait plus efficacement.

Voici mon ghetto-bidouille:

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]) 
} 

que je recherchais dans sapply et tapply etc., mais je ne peux pas sembler comprendre comment utiliser « l'élément suivant » dans le vecteur.

Toute aide sera récompensée par ma gratitude éternelle!

-------------- -------------- Modifier

temps d'exécution des suggestions à l'aide de données d'entrée avec 3 ~ millions de lignes:

 
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" 

Répondre

1

pour les groupes de deux, nous pouvons le faire avec

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

et pour un plus grand nombre, une option est de shiftdata.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" 

Ou

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

Merci! J'ai testé les trois solutions. Mon vecteur d'entrée a environ 3 millions d'éléments et ma boucle for-passée a duré environ 4 minutes. Votre première solution a été incroyablement efficace, en utilisant seulement 20 secondes. Le deuxième meilleur était la solution grep. La solution d'application (matrice) a passé autant de temps que la boucle for. J'utilise ta première version. – CoveredInChocolate

+0

@CoveredInChocolate Le troisième a été ralenti car 'apply' est fondamentalement similaire à une boucle' for'. Vous pouvez convertir en 'data.frame' et utiliser' do.call (paste, as.data.frame (matrix (t1, .... ' – akrun

+1

) Eh bien, on dirait que je te dois des excuses: quand j'ai fait mes tests, je n'ai pas utilisé n1 <- 2 donc la comparaison était injuste Après avoir corrigé cela, l'application (la version matricielle a passé 3 minutes (1 minute de moins qu'une boucle for) et après avoir été convertie en data.frame, elle n'a duré qu'une minute, c'est une amélioration significative, génial! :) – CoveredInChocolate

2

Avez-vous envisagé le package zoo? Par exemple

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

retournera

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

Les contrôles argument width combien éléments concaténer. Je m'attends à ce que vous ayez des temps d'exécution améliorés ici aussi, mais je n'ai pas testé

+0

la suggestion! Mon vecteur d'entrée a environ 3 millions de lignes et votre solution a passé environ 10 minutes contre environ 4 minutes pour la boucle for.Votre suggestion était élégante, mais il semble que les développeurs de zoo doivent faire une certaine optimisation.) – CoveredInChocolate