R言語で文字列(character型)の変数の操作方法について解説します。
ここでは、検索、置換、切り出し、結合、分割といった基本的な操作を実行する関数やその実行例を紹介していきます。
文字列に関するデータ整形がしたい場合、文字列の操作は必須のとなります。是非、この記事を参考にしてください。
また、この記事で紹介するプログラミングコードは以下のzipファイル中のRスクリプトに保存しています。
R言語 正規表現 Rスクリプト
文字列の操作
文字列の操作方法を紹介します。
基本的な操作方法である検索、置換、切り出し、結合、分割、文字数の実行方法をみていきます。
関数の引数などの詳細については、それぞれの関数のRdocumentを参照してください。
検索 match, charmatch, pmatch, grep, grepl, gregexpr
まず、文字列の検索方法について紹介します。
R言語には文字列を検索するための便利が沢山あります。
完全に一致する文字列を検索したい場合は関数matchを用い、部分的に一致する文字列を検索したい場合はそれ以外の上記の関数charmatch, pmatch, grep, grepl, gregexprなどを用います。
以下、各々の関数の実行例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | > meta <- c("foo", "bar", "foobar", "baz", "qux", "quux", "corge", "grault", + "garply", "waldo", "fred", "plugh", "xyzzy", "thud") > > match(c("bar", "foob", "ba", "foo"), meta) #一致する最初のインデックス [1] 2 NA NA 1 > charmatch(c("bar", "foob", "ba", "foo"), meta) #部分的に一致するインデックス [1] 2 3 0 1 > pmatch(c("bar", "foob", "ba", "foo"), meta) #部分的に一致するインデックス(一致するものを優先) [1] 2 3 4 1 > grep("bar", meta) #部分的に一致するインデックス [1] 2 3 > grepl("bar", meta) #部分的に一致しているかどうか [1] FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE > gregexpr("bar", meta) #文字の一致数や一致する位置 [[1]] [1] -1 attr(,"match.length") [1] -1 attr(,"index.type") [1] "chars" attr(,"useBytes") [1] TRUE . . . [[14]] [1] -1 attr(,"match.length") [1] -1 attr(,"index.type") [1] "chars" attr(,"useBytes") [1] TRUE |
matchは完全に一致する文字列のインデックス、charmatchは部分的に一致する文字列のインデックス、pmatchは完全一致する文字列を優先し部分一致する文字列のインデックスを返します。
charmatchとpmatchの違いとして、charmatchは部分的に一致する文字列が複数ある場合は0を返すのに対して、pmatchは完全に一致する文字列と部分的に一致する文字列が第一引数のベクトルの要素にある場合には両方のインデックスを返してくれる点です。
また、関数grep等を用いることで同様の結果を得ることが可能です。charmatchやpmatchと同様に、grepを用いることで部分的に一致する文字列のインデックスを得ることができます。greplだとインデックスではなくlogical型のベクトルを返します。さらに、gregexprを用いれば文字の一致数や一致する位置などの詳細な結果を得ることも可能です。
置換 sub, gsub, chartr, toupper, tolower
検索方法に続いて、文字列の置換方法について紹介します。
R言語には文字列を置換する関数としてsub、gsub、chartr、toupper、tolowerなどがあります。
文字列中の最初の一文字のみ置き換えたいときは関数subを用い、一致する文字を全て置き換えたい場合は関数gsub、chartrを用います。また、アルファベットの小文字と大文字に関して置き換えを行いたい場合はtoppuerとtolowerを用います。小文字を大文字にしたい場合はtoupper、大文字を小文字にしたい場合はtolowerを用います。
以下、各々の関数の実行例です。
1 2 3 4 5 6 7 8 9 10 11 | > sub("o", "0", meta) #文字列中の最初の"o"を"0"に置換 [1] "f0o" "bar" "f0obar" "baz" "qux" "quux" "c0rge" "grault" "garply" "wald0" "fred" "plugh" "xyzzy" [14] "thud" > gsub ("o", "0", meta) #"o"を"0"に置換 [1] "f00" "bar" "f00bar" "baz" "qux" "quux" "c0rge" "grault" "garply" "wald0" "fred" "plugh" "xyzzy" [14] "thud" > chartr("o", "0", meta) [1] "f00" "bar" "f00bar" "baz" "qux" "quux" "c0rge" "grault" "garply" "wald0" "fred" "plugh" "xyzzy" [14] "thud" |
"foo"などの"o"を複数もつ文字列に対し関数subを用いて"o"を"0"に置き換えると、最初の"o"のみが"0"に置き換わり"f0o"となっていることが分かります。
それ以外の関数gsub、chartrについてはすべての"o"が"0"に置き換わり、"foo"は"f00"になっていることが確認できます。
また、関数toupperとtolowerの実行例は以下の通りです。
1 2 3 4 5 6 7 8 9 | > META <- toupper(meta) > META [1] "FOO" "BAR" "FOOBAR" "BAZ" "QUX" "QUUX" "CORGE" "GRAULT" "GARPLY" "WALDO" "FRED" "PLUGH" "XYZZY" [14] "THUD" > meta <- tolower(meta) > meta [1] "foo" "bar" "foobar" "baz" "qux" "quux" "corge" "grault" "garply" "waldo" "fred" "plugh" "xyzzy" [14] "thud" |
toupperを用いるとmeta中の文字列が全て大文字に置き換わり、tolowerを用いるとMETA中の大文字が全て小文字に置き換わることが分かります。
また、次のようにしてシーザー暗号を取得することもできます。
1 2 3 4 5 6 7 8 9 | > #例 シーザー暗号 > nfub <- meta > for (i in seq_len(length(letters))) { + nfub <- gsub(letters[i], LETTERS[i %% length(letters) + 1], nfub) + } > nfub <- tolower(nfub) > nfub [1] "gpp" "cbs" "gppcbs" "cba" "rvy" "rvvy" "dpshf" "hsbvmu" "hbsqmz" "xbmep" "gsfe" "qmvhi" "yzaaz" [14] "uive" |
関数gsubやtolwerを用いることで、1つずつアルファベットがずラスことが可能です。
切り出し substr, substring
次に、文字列の切り出し方法について紹介します。
切り出しを行う関数としてsubstr、substringなどがあります。
substrとsubstringを用いると文字列の切り出しを行うことができます。すなわち、ある文字列の部分文字列を取得することができます。
以下、各々の関数の実行例です。
1 2 3 4 5 | > substr(meta, 1, 3) #1文字目から3文字目 [1] "foo" "bar" "foo" "baz" "qux" "quu" "cor" "gra" "gar" "wal" "fre" "plu" "xyz" "thu" > substring(meta, 1, 3) [1] "foo" "bar" "foo" "baz" "qux" "quu" "cor" "gra" "gar" "wal" "fre" "plu" "xyz" "thu" |
上の実行結果のように、引数で指定したインデックスについて文字列を切り出してくれます。上の例では1文字目から3文字目を切り出していることが分かります。
substrとsubstringの2種類の関数が用意されていますが、特に実行結果に違いはありません。
結合 paste, paste0
次に、文字列の結合方法について紹介します。
R言語には文字列を結合する関数としてpaste、paste0などがあります。
関数pasteとpaste0の違いとして区切り文字の設定があります。pasteはデフォルトでスペース区切りで文字列を結合するのに対して、paste0は区切り文字なしで直接文字列を結合させます。区切り文字を用いたくない場合は関数paste0を用いることをお勧めします。
以下、各々の関数の実行例です。
1 2 3 4 5 6 7 8 9 10 | > paste(meta, nfub) #metaとnfubをスペース区切りで結合 [1] "foo gpp" "bar cbs" "foobar gppcbs" "baz cba" "qux rvy" "quux rvvy" "corge dpshf" [8] "grault hsbvmu" "garply hbsqmz" "waldo xbmep" "fred gsfe" "plugh qmvhi" "xyzzy yzaaz" "thud uive" > paste(meta, collapse = "") #ベクトル中の要素を全て結合 [1] "foobarfoobarbazquxquuxcorgegraultgarplywaldofredplughxyzzythud" > paste0(meta, nfub) #metaとnfubを結合 [1] "foogpp" "barcbs" "foobargppcbs" "bazcba" "quxrvy" "quuxrvvy" "corgedpshf" "graulthsbvmu" [9] "garplyhbsqmz" "waldoxbmep" "fredgsfe" "plughqmvhi" "xyzzyyzaaz" "thuduive" |
pasteを用いるとmetaとnfubをスペース区切りで結合させることができます。また5行目のように、pasteの引数collapseを""にすると、character型のベクトルの要素を全て結合させることができます。
また、paste0を用いるとmetaとnfubを区切り文字なしで結合させることができます。
次のように、metaと上で作ったmetaのシーザー暗号nfubの関係を説明したりでき、pasteを使って色々な表現が可能です。
1 2 3 4 5 6 7 8 | > #例 > CeasarCipher <- paste(meta, "⇒", nfub, "(Caesar n=1)") > CeasarCipher [1] "foo ⇒ gpp (Caesar n=1)" "bar ⇒ cbs (Caesar n=1)" "foobar ⇒ gppcbs (Caesar n=1)" [4] "baz ⇒ cba (Caesar n=1)" "qux ⇒ rvy (Caesar n=1)" "quux ⇒ rvvy (Caesar n=1)" [7] "corge ⇒ dpshf (Caesar n=1)" "grault ⇒ hsbvmu (Caesar n=1)" "garply ⇒ hbsqmz (Caesar n=1)" [10] "waldo ⇒ xbmep (Caesar n=1)" "fred ⇒ gsfe (Caesar n=1)" "plugh ⇒ qmvhi (Caesar n=1)" [13] "xyzzy ⇒ yzaaz (Caesar n=1)" "thud ⇒ uive (Caesar n=1)" |
分割 strsplit
文字列の分割方法について紹介します。
R言語には文字列を分割する関数としてstrsplitなどがあります。
関数strsplitを使うと、指定した文字を基準に文字列を複数に分割してくれます。
以下、関数の実行例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | > date <- c("2021-05-15", "2021-05-16","2021-05-17", "2021-05-18", "2021-05-19") > strsplit(date, "-") #-区切りで分割 [[1]] [1] "2021" "05" "15" [[2]] [1] "2021" "05" "16" [[3]] [1] "2021" "05" "17" [[4]] [1] "2021" "05" "18" [[5]] [1] "2021" "05" "19" > strsplit(meta, "") #文字列を1文字ずつのベクトルに変換 [[1]] [1] "f" "o" "o" [[2]] [1] "b" "a" "r" [[3]] [1] "f" "o" "o" "b" "a" "r" [[4]] [1] "b" "a" "z" [[5]] [1] "q" "u" "x" [[6]] [1] "q" "u" "u" "x" [[7]] [1] "c" "o" "r" "g" "e" [[8]] [1] "g" "r" "a" "u" "l" "t" [[9]] [1] "g" "a" "r" "p" "l" "y" [[10]] [1] "w" "a" "l" "d" "o" [[11]] [1] "f" "r" "e" "d" [[12]] [1] "p" "l" "u" "g" "h" [[13]] [1] "x" "y" "z" "z" "y" [[14]] [1] "t" "h" "u" "d" |
2行目では、日付の文字列から成るベクトルdateを"-"区切りで分割 で分割しています。実行するとdateのそれぞれの要素に対する分割後のベクトルc(年, 月, 日)をリストで返してくれます。
また、区切り文字を""に設定すると1文字ずつに分割されたcharacter型のベクトルを得ることができます("abcdef"をc("a", "b", "c", "d", "e", "f")にすることができます)。
以下、strsplitの応用です。文字列の結合で作ったCeasarCipherを再度分割しmetaとnfubの文字列を抽出したり、いままで紹介した関数を使って文字列を逆順にすることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | > #例 文字列の分割 > metanfub <- lapply(strsplit(CeasarCipher, " "), function(x) { + c(x[[1]], x[[3]]) + }) > matrix(unlist(metanfub), ncol = 2, byrow = TRUE) #抽出したmetaとnfubを行列に格納 [,1] [,2] [1,] "foo" "gpp" [2,] "bar" "cbs" [3,] "foobar" "gppcbs" [4,] "baz" "cba" [5,] "qux" "rvy" [6,] "quux" "rvvy" [7,] "corge" "dpshf" [8,] "grault" "hsbvmu" [9,] "garply" "hbsqmz" [10,] "waldo" "xbmep" [11,] "fred" "gsfe" [12,] "plugh" "qmvhi" [13,] "xyzzy" "yzaaz" [14,] "thud" "uive" [15,] "foo" "gpp" > #例 文字列を逆順に > sapply(strsplit(meta, ""), function(x) { + paste(rev(x), collapse = "") + }) [1] "oof" "rab" "raboof" "zab" "xuq" "xuuq" "egroc" "tluarg" "ylprag" "odlaw" "derf" "hgulp" "yzzyx" [14] "duht" |
文字数
最後に、文字数の取得方法について紹介します。
R言語には文字数を取得する関数としてncharなどがあります。
以下、関数の実行例です。
1 2 | > nchar(meta) [1] 3 3 6 3 3 4 5 6 6 5 4 5 5 4 |
metaのそれぞれの要素の文字数を返しいることが分かります。
正規表現
次に、R言語の正規表現について解説します。
正規表現を用いることでより複雑な文字列の操作が可能となります。
正規表現で扱うメタ文字とその意味を以下にまとめました。
メタ文字 | 意味 |
. | 任意の1文字。 |
\ | メタ文字を回避するために用いる。正規表現中で"."を表したい場合"\\."とする。 |
| | 論述演算のor。または。 |
() | ()中の複数の文字を一単位で扱う。"(a|b|c)"は"a"または"b"、"c"の一文字を表す。 |
[] | []中の文字の1文字を表す。 |
{} | {}中の数分、{}の前の文字を繰り返していることを表す。"a{1,3}"は1回以上3回以下"a"が繰り返す。 |
^ | 先頭の文字を表す。"^a"は先頭が"a"。[]の中で用いると、^以降の文字以外を表す。"[^a]"は"a"以外。 |
$ | 後尾の文字を表す。"z$"は後尾が"z"。 |
* | *の前の文字が0回以上繰り返すことを表す。"a*"は"a"が0回以上。 |
+ | +の前の文字が1回以上繰り返すことを表す。"a+"は"a"が1回以上。 |
? | *の前の文字が0回か1回繰り返すことを表す。"a?"は"a"が0回か1回。 |
また、アルファベットなどの複数の文字や,.?_などの英数字以外の特殊な文字を表す特殊な正規表現を以下に列挙します。
正規表現 | 意味 |
[a-z] | アルファベット |
[0-9] | 数字 |
[:punct:] | 英数字、改行、タブ、スペース以外の文字 |
[:alpha:] | アルファベット |
[:lower:] | アルファベット(小文字) |
[:upper:] | アルファベット(大文字) |
[:digit:] | 10進数字 |
[:digit:] | 16進数字 |
[:alnum:] | 英数字 |
[:contrl:] | 制御文字 |
[:graph:] | 英数字と英数字、改行、タブ、スペース以外の文字 |
[:print:] | 英数字とホワイトスペースと英数字、改行、タブ、スペース以外の文字 |
[:space:] | スペース |
[:blank:] | スペースとタブ |
正規表現を用いた文字列の操作の例をいくつか紹介します。
先頭の文字で検索したり数字以外を削除したりする例をのせました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | > #正規表現##### > grep("^b", meta) #aで始まる文字列のインデックス [1] 2 4 > grep("z$", meta) #zで終わる文字列のインデックス [1] 4 > grep("q.+x", meta) #q___xをもつ文字列のインデックス [1] 5 6 > gsub("a|b|c", "", meta) #a,b,cを削除 [1] "foo" "r" "foor" "z" "qux" "quux" "orge" "grult" "grply" "wldo" "fred" "plugh" "xyzzy" "thud" > lengths <- c("120.44m", "90.26m", "230.89m", "150.72m", "43.47m", "340.91m") > lengths <- as.numeric(gsub("[^0-9\\.]", "", lengths)) #数字以外削除 > lengths [1] 120.44 90.26 230.89 150.72 43.47 340.91 > qwerts <- NULL > for (i in seq_len(10)) { + qwerts <- append(qwerts, paste(sample(c("q", "w", "e", "r", "t"), 5, replace = TRUE), collapse = "")) + } > grep("we|q[et]", qwerts) [1] 2 3 4 6 10 |
まとめ
R言語で文字列を操作する方法を紹介しました。
R言語には、検索、置換、切り出し、結合、分割といった基本的な文字列の操作をするための関数が標準で導入されています。
文字列の操作はデータ整形を行う際にたびたび必要となります。今回紹介した実行例などをぜひデータ整形の際に役立ててください。