2014-07-24 10 views
18

Ho un frame di dati con una colonna di caratteri separata da punti:Aggiungendo più colonne in un dplyr mutare chiamare

> set.seed(310366) 
> tst = data.frame(x=1:10,y=paste(sample(c("FOO","BAR","BAZ"),10,TRUE),".",sample(c("foo","bar","baz"),10,TRUE),sep="")) 
> tst 
    x  y 
1 1 BAR.baz 
2 2 FOO.foo 
3 3 BAZ.baz 
4 4 BAZ.foo 
5 5 BAZ.bar 
6 6 FOO.baz 
7 7 BAR.bar 
8 8 BAZ.baz 

e voglio dividere la colonna in due nuove colonne contenenti i pezzi su entrambi i lati della punto. str_split_fixed dal pacchetto stringr può fare il lavoro abbastanza bene. Tutti i miei valori sono sicuramente due parti separate da un punto in modo che io possa fare:

> require(stringr) 
> str_split_fixed(tst$y,"\\.",2) 
     [,1] [,2] 
[1,] "BAR" "baz" 
[2,] "FOO" "foo" 
[3,] "BAZ" "baz" 
[4,] "BAZ" "foo" 
[5,] "BAZ" "bar" 
[6,] "FOO" "baz" 
[7,] "BAR" "bar" 

Ora ho potuto solo cbind che al mio frame di dati, ma ho pensato di capire come farlo in una pipeline dplyr. Per prima cosa ho pensato mutate potuto farlo in uno:

> tst %.% mutate(parts=str_split_fixed(y,"\\.",2)) 
Error: wrong result size (20), expected 10 or 1 

posso ottenere mutate di farlo in due:

> tst %.% mutate(part1=str_split_fixed(y,"\\.",2)[,1], part2=str_split_fixed(y,"\\.",2)[,2]) 
    x  y part1 part2 
1 1 BAR.baz BAR baz 
2 2 FOO.foo FOO foo 
3 3 BAZ.baz BAZ baz 
4 4 BAZ.foo BAZ foo 
5 5 BAZ.bar BAZ bar 
6 6 FOO.baz FOO baz 

ma che è in esecuzione la spaccatura stringa di due volte.

"Best" che posso fare finora in modo dplyr è questo (che ho scoperto solo durante la scrittura a questa domanda ...):

> tst %.% do(cbind(.,data.frame(parts=str_split_fixed(.$y,"\\.",2)))) 
    x  y parts.1 parts.2 
1 1 BAR.baz  BAR  baz 
2 2 FOO.foo  FOO  foo 
3 3 BAZ.baz  BAZ  baz 
4 4 BAZ.foo  BAZ  foo 
5 5 BAZ.bar  BAZ  bar 

che non è male, ma perde un sacco di la leggibilità delle cose in pipe in R. C'è un approccio semplice usando mutate che mi sono perso?

risposta

36

È possibile utilizzare separate() da tidyr in combinazione con dplyr:

tst %>% separate(y, c("y1", "y2"), sep = "\\.", remove=FALSE) 

    x  y y1 y2 
1 1 BAR.baz BAR baz 
2 2 FOO.foo FOO foo 
3 3 BAZ.baz BAZ baz 
4 4 BAZ.foo BAZ foo 
5 5 BAZ.bar BAZ bar 
6 6 FOO.baz FOO baz 
7 7 BAR.bar BAR bar 
8 8 BAZ.baz BAZ baz 
9 9 FOO.bar FOO bar 
10 10 BAR.foo BAR foo 

Impostazione remove=TRUE rimuoverà colonna y

+1

guarda attorno come semplice come si arriva. Un altro motivo per eseguire l'aggiornamento a 3.1 ... – Spacedman

+1

Sfortunatamente 'separate' restituisce un errore quando il risultato dopo la divisione ha più colonne di quelle specificate. In questo senso funziona piuttosto come 'str_split' di' str_split_fixed'. Vedi [questa richiesta di funzionalità] (https://github.com/hadley/tidyr/issues/19). Ma ancora una risposta molto utile, grazie. – Beasterfield

+0

usando il parametro 'extra =" unione "' questo può essere controllato –

Problemi correlati