2016-05-25 9 views
1

I eine Tabelle mit einer Zeichenfeld haben, die einem dieser Muster haben kann:Spliting String mit einem bestimmten Muster

input    

97     # a single number 
210 foo   # a number and a word 
87 bar 89   # a number, a word, a number 
21 23    # two numbers 
123 2 fizzbuzz  # two number, a word   
12 fizz 34 buzz # a number, a word, a number, a word 

Ich möchte aufzuspalten jede Zeile bis zu 4 Teilen, enthalten, jeweils the first number, the first word Wenn es existiert, the second number wenn es existiert, und the second word wenn es existiert. So würde mein Beispiel:

input    nb_1 word_1 nb_2 word_2 

97     97 
210 foo    210  foo 
87 bar 89   87  bar  89 
21 23    21    23 
123 2 fizzbuzz  123    2  fizzbuzz 
12 fizz 34 buzz  12  fizz  34  buzz 

Bitte beachten Sie, den Fall two number, a word (das Beispiel vor dem letzten): es hat nichts in word_1 da kein Wort zwischen den beiden Zahlen.

Gibt es eine Möglichkeit, dies ohne eine lästige if/if/else Struktur zu tun?

Wenn es helfen kann, gehören alle Wörter zu einer Liste von 10 spezifischen Wörtern. Wenn zwei Wörter vorhanden sind, können sie gleich oder verschieden sein. Außerdem können die Nummern eine, zwei oder drei Ziffern lang sein.

Dank

+2

Verwenden Sie 'dput', um das Beispiel anzuzeigen. Ist es eine einzelne Zeichenfolge oder zwei Spalten in einem dat.frame dh '" eine einzige Zahl: 97 "' – akrun

+0

Entschuldigung, es war nur, um das Muster anzuzeigen, änderte ich die Frage in einer hoffentlich klareren Weise –

Antwort

1

Hier ist eine Idee gsub und cSplit aus splitstackshape Paket verwenden,

library(splitstackshape) 
df$num <- gsub('\\D', ' ', df$V1) 
df$wrds <- gsub('\\d', ' ', df$V1) 
newdf <- cSplit(df, 2:3, ' ', 'wide') 
newdf 
#         V1 num_1 num_2 wrds_1 wrds_2 
#1:         97 97 NA  NA  NA 
#2:        210 foo 210 NA  foo  NA 
#3:       87 bar 89 87 89  bar  NA 
#4:        21 23 21 23  NA  NA 
#5:      123 2 fizzbuzz 123  2 fizzbuzz  NA 
#6:      12 fizz 34 buzz 12 34  fizz buzz 

Das einzige Problem ist die Zeile 5, die wie folgt festgelegt werden kann,

newdf$wrds_1 <- as.character(newdf$wrds_1) 
newdf$wrds_2 <- as.character(newdf$wrds_2) 
newdf$wrds_2[grep('[0-9]+\\s+[0-9]+\\s+[A-Za-z]', newdf$V1)] <- newdf$wrds_1[grep('[0-9]+\\s+[0-9]+\\s+[A-Za-z]', newdf$V1)] 
newdf$wrds_1[grep('[0-9]+\\s+[0-9]+\\s+[A-Za-z]', newdf$V1)] <- NA 

welcher schließlich gibt

newdf 
#         V1 num_1 num_2 wrds_1 wrds_2 
#1:         97 97 NA  NA  NA 
#2:        210 foo 210 NA foo  NA 
#3:       87 bar 89 87 89 bar  NA 
#4:        21 23 21 23  NA  NA 
#5:      123 2 fizzbuzz 123  2  NA fizzbuzz 
#6:      12 fizz 34 buzz 12 34 fizz  buzz 

DATA

dput(df) 
structure(list(V1 = c("97", "     210 foo", "       87 bar 89", 
"     21 23", "     123 2 fizzbuzz", 
"     12 fizz 34 buzz")), .Names = "V1", row.names = c(NA, 
-6L), class = "data.frame") 
+0

Danke für alle drei Antworten, ging mit diesem, wie es mir schien einfacher. –

1
Tried in a different way... 
library(splitstackshape) 
    abc <- data.frame(a=c(97,"210 foo","87 bar 89","21 23","123 2 fizzbuzz","12 fizz 34 buzz")) 
    abc1 <- data.frame(cSplit(abc, "a", " ", stripWhite = FALSE)) 
    abc <- cbind(abc,abc1) 
    names(abc) <- c("input","nb_1", "word_1", "nb_2","word_2") 
    abc[,1:5] <-apply(abc[,1:5] , 2, as.character) 
    for(i in 1:nrow(abc)){ 
     abc$word_2[i] <- replace(abc$word_2[i] , is.na(abc$word_2[i]),abc$nb_2[grepl("[a-z]",abc$nb_2[i])][i]) 
     abc$nb_2[i] <- replace(abc$nb_2[i] , is.na(abc$nb_2[i])|grepl("[a-z]",abc$nb_2[i]),abc$word_1[grepl("[0-9]",abc$word_1[i])][i]) 
     } 
    abc$word_1 <- ifelse(grepl("[0-9]",abc$word_1),NA,abc$word_1) 
    abc[is.na(abc)] <- "" 
    print(abc) 
      input nb_1 word_1 nb_2 word_2 
1    97 97      
2   210 foo 210 foo    
3  87 bar 89 87 bar 89   
4   21 23 21   23   
5 123 2 fizzbuzz 123   2 fizzbuzz 
6 12 fizz 34 buzz 12 fizz 34  buzz 
+0

Bitte fügen Sie Ihre Kommentare hinzu, wenn mein Ansatz falsch ist –

1

Dies ist eine Hacky Funktion, es zu tun ... obwohl Sie könnten auch andere Fälle, die es brechen.

f <- function(x){ 
    string2 <- strsplit(x, " ")[[1]] 
    if (length(string2) < 2) 
    return(c(string2, NA, NA, NA)) 
    arenums <- grepl("\\d", string2) 
    c(string2[which(arenums)[1]], 
    if (arenums[2]) NA else string2[which(!arenums)[1]],  
    string2[which(arenums)[2]], 
    if (arenums[2]) string2[which(!arenums)[1]] else string2[which(!arenums)[2]]) 
} 

> f("97") 
[1] "97" NA NA NA 
> f("210 foo") 
[1] "210" "foo" NA NA 
> f("87 bar 89") 
[1] "87" "bar" "89" NA 
> f("21 23") 
[1] "21" NA "23" NA 
> f("123 2 fizzbuzz") 
[1] "123"  NA   "2"  "fizzbuzz" 
> f("12 fizz 34 buzz") 
[1] "12" "fizz" "34" "buzz" 
Verwandte Themen