ドットで区切られた文字列を持つデータフレームがあります。
> 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
その列を、ドットの両側のパーツを含む2つの新しい列に分割したいと思います。 str_split_fixed
パッケージからstringr
は非常にうまく仕事をすることができます。私のすべての値は間違いなくドットで区切られた2つの部分なので、次のことができます。
> 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"
これで、データフレームにcbind
することができましたが、dplyr
パイプラインでそれを行う方法を理解できると思いました。最初に私はmutate
が1つでそれを行うことができると思いました:
> tst %.% mutate(parts=str_split_fixed(y,"\\.",2))
Error: wrong result size (20), expected 10 or 1
mutate
を2つに分けて実行できます。
> 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
しかし、それは文字列分割を2回実行しています。
これまでのところdplyr
の方法でできる「最善」はこれです(これは、この質問を書いているときにのみ発見しました...):
> 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
これは悪くはありませんが、Rでパイプされたものの読みやすさの多くを失います。私が見逃したmutate
を使用した簡単なアプローチはありますか?
tidyr
のseparate()
を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
設定remove=TRUE
列yを削除します