2016-04-27 17 views
0

Ich mag würde wissen, wie String verketten Sequenzen unterschiedlicher und unterschiedlichen Längen & Gehalt nach einem Bedingungsänderungs zu bilden.Concatenate/paste Strings der Länge variierender Index entsprechend

Hier ist ein Dataframe Beispiel (mein DF ist eigentlich etwa 60000 Zeilen).

  1. column index: nur ein Index
  2. to_concat: der String Artikel i
  3. max_seq verketten möchten: ein Beispiel für die Bedingung für die Verkettung (to_concat sollte nur verketten, wenn sie Teil derselben Sequenz ist - und ich habe jetzt die Position der Zeichenfolge in der angegebenen Reihenfolge
  4. concat_result. Das Ergebnis ich mag würde haben

    index to_concat max_seq concat_result 
    1  Abc!  1   <abc!+def+_> 
    2  def  2   <abc!+def+_> 
    3  _   3   <abc!+def+_> 
    4  x93  1   <x93+afza+5609+5609+Abc!+def> 
    5  afza  2   <x93+afza+5609+5609+Abc!+def> 
    6  5609  3   <x93+afza+5609+5609+Abc!+def> 
    7  5609  4   <x93+afza+5609+5609+Abc!+def> 
    8  Abc!  5   <x93+afza+5609+5609+Abc!+def> 
    9  def  6   <x93+afza+5609+5609+Abc!+def> 
    10  _   1   <_+x93+afza> 
    11  x93  2   <_+x93+afza> 
    12  afza  3   <_+x93+afza> 
    

Ich kenne paste & aggregate, length, wahrscheinlich nützlich .. Aber nicht sehen, in welcher Reihenfolge, das zu tun und vor allem, wie die Paste zu formulieren.

Ich denke, ich sollte auch einen "zweiten" Index besser für max_seq getan (wie: alle Ketten in der gleichen Reihenfolge verkettet haben die gleiche Nummer, so würden wir hier eine 3 Sequenzen haben "1 1 1 2 2 2 2 2 2 3 3 3“.

Aber ich weiß nicht, ob das die schnellste/einfachste Lösung ist, und auch ich weiß nicht, wie unterschiedliche Länge einfügen ...

Könnten Sie bitte helfen einer Kollegen PhD? Vielen Dank im Voraus.


reproduzierbares Beispiel: dput(dat)

> dput(dat) 
structure(list(V1 = c("index", "1", "2", "3", "4", "5", "6", 
"7", "8", "9", "10", "11", "12"), V2 = c("to_concat", "Abc!", 
"def", "_", "x93", "afza", "5609", "5609", "Abc!", "def", "_", 
"x93", "afza"), V3 = c("max_seq", "1", "2", "3", "1", "2", "3", 
"4", "5", "6", "1", "2", "3"), V4 = c("concat_result", "<abc!+def+_>", 
"<abc!+def+_>", "<abc!+def+_>", "<x93+afza+5609+5609+Abc!+def>", 
"<x93+afza+5609+5609+Abc!+def>", "<x93+afza+5609+5609+Abc!+def>", 
"<x93+afza+5609+5609+Abc!+def>", "<x93+afza+5609+5609+Abc!+def>", 
"<x93+afza+5609+5609+Abc!+def>", "<_+x93+afza>", "<_+x93+afza>", 
"<_+x93+afza>")), .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c(NA, 
-13L)) 

Antwort

4

Mehr Optionen, um das gewünschte Ergebnis zu erhalten:

1) unter Verwendung einer Base R:

mydf$grp <- cumsum(mydf$max_seq < c(1,head(mydf$max_seq, -1))) + 1 
mydf$concat_result <- ave(mydf$to_concat, mydf$grp, 
          FUN = function(x) paste0('<',paste(x,collapse='+'),'>')) 

, das gibt:

> mydf 
    index to_concat max_seq grp     concat_result 
1  1  Abc!  1 1     <Abc!+def+_> 
2  2  def  2 1     <Abc!+def+_> 
3  3   _  3 1     <Abc!+def+_> 
4  4  x93  1 2 <x93+afza+5609+5609+Abc!+def> 
5  5  afza  2 2 <x93+afza+5609+5609+Abc!+def> 
6  6  5609  3 2 <x93+afza+5609+5609+Abc!+def> 
7  7  5609  4 2 <x93+afza+5609+5609+Abc!+def> 
8  8  Abc!  5 2 <x93+afza+5609+5609+Abc!+def> 
9  9  def  6 2 <x93+afza+5609+5609+Abc!+def> 
10 10   _  1 3     <_+x93+afza> 
11 11  x93  2 3     <_+x93+afza> 
12 12  afza  3 3     <_+x93+afza> 

2) Oder mit dem data.table Paket:

library(data.table) 
setDT(mydf)[, grp := cumsum(max_seq < shift(max_seq, fill = 0))+1 
      ][, concat_result := paste0('<',paste(to_concat,collapse='+'),'>'), grp][] 

3) Oder mit dem dplyr Paket:

library(dplyr) 
mydf %>% 
    mutate(grp = cumsum(max_seq < lag(max_seq, n=1, default=0))+1) %>% 
    group_by(grp) %>% 
    mutate(concat_result = paste0('<',paste(to_concat,collapse='+'),'>')) 

Gebraucht Daten :

mydf <- structure(list(index = 1:12, 
         to_concat = c("Abc!", "def", "_", "x93", "afza", "5609", "5609", "Abc!", "def", "_", "x93", "afza"), 
         max_seq = c(1L, 2L, 3L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L)), 
        .Names = c("index", "to_concat", "max_seq"), class = "data.frame", row.names = c(NA, -12L)) 
+0

Vielen Dank für die verschiedenen Optionen in Ihrer schnellen Antwort @ProcrastinatusMaximus. Ich würde persönlich mit der Base R gehen, da es für jeden R-Benutzer am lesbarsten ist. – prosodis

+1

@prosodis Wahr. Aber wenn Geschwindigkeit und Speichereffizienz ein Problem sind, dann wäre die 'data.table' Alternative der beste Weg zu gehen. – Jaap