Rで文字列を作る
Rの文字列は引用符で囲んだテキストです。二重引用符と一重引用符はどちらも使え、意味もまったく同じです。慣習としては二重引用符を使い、テキスト自体に二重引用符が含まれるときだけ一重引用符に切り替えます。
バックスラッシュのエスケープは多くの言語と同じです。引用符そのものには \"、改行には \n、タブには \t、バックスラッシュ自体には \\ を使います。
さて、R初心者が必ず一度はやるミス。length() で文字列の長さを尋ねてしまうことです。
nchar() は文字数を数えて5を返します。length() はベクトルの要素数を数え、1つの文字列は要素1つのベクトルなので1と答えます。Rではテキストも含めてすべてがベクトルであり、このページのすべての関数は文字列ベクトル全体に対して静かに要素ごとに働きます。驚かなくなれば、これは長所です。
文字列の連結:paste() と paste0()
Rに文字列用の + はありません。連結は paste()(既定で引数をスペースでつなぐ)と paste0()(何も挟まずにつなぐ)が担当します。
pasteはベクトル化されているので、ベクトルを渡せば一度に多数の文字列を作れます。ファイル名、ラベル、IDを1行で生成するのはこの方法です。
そして collapse 引数はその逆をします。ベクトル全体を、選んだ区切り文字で1つの文字列に融合します。
使い分けを覚えておきましょう。sep は引数どうしの接着剤、collapse は1つのベクトルの要素どうしの接着剤です。1回の呼び出しで両方使うこともできます。
sprintf() による整形
テキストの中に数値を整形して埋め込みたいとき——小数点以下の桁数を固定する、幅を詰め物で揃えるなど——paste() では力不足で、sprintf() の出番になります。C言語スタイルの書式コードを使い、文字列は %s、整数は %d、小数は %f です。
%.1f は「小数点以下1桁」、%.3f は3桁、%05d はゼロ埋めで5桁に揃えます。%% を重ねるとパーセント記号そのものになります。sprintf() もベクトル化されているので、1回の呼び出しで列全体の値を整形できます。sprintf() と cat() を組み合わせたレポート出力のパターンは入力と出力を参照してください。
大文字小文字の変換と切り出し:toupper()・tolower()・substr()
大文字小文字の変換は名前のとおりです。
tolower() は比較の前に乱雑なデータを正規化する場面で真価を発揮します。"Yes"、"YES"、"yes" がすべて同じ値になります。
substr(x, start, stop) は文字位置でスライスを取り出します。数え始めは1です(Rはどこでも1始まりです)。
両端とも含まれます。1から11までの位置で "Programming" が得られます。
検索と置換:sub()・gsub()・grepl()
sub() はパターンの最初の出現を置換し、gsub()(global substitute)はすべてを置換します。
決定的に重要な点がひとつ。パターンは既定でリテラルなテキストではなく正規表現です。.、*、(、? のような正規表現の文字には特別な意味があり、素の . は任意の文字に一致します。リテラルなテキストを意図するなら fixed = TRUE を渡します。
1行目は a-b-c になり、2行目は ----- になります。正規表現としての . がすべての文字に一致したからです。正規表現を学ぶまでは fixed = TRUE を既定にしておけば、痛い目に遭うことはありません。
grepl() は置換をしません。各要素が一致するかを判定し、論理ベクトルを返します。そのためテキストを絞り込む標準的な道具になります。
最初の結果はどのファイル名が .csv を含むかを示し、2つ目はその論理ベクトルを使って一致したものだけを残しています。
分割と余白の除去:strsplit() と trimws()
strsplit() は区切り文字で文字列を切り分けます。ひとつ癖があり、複数の文字列を一度に分割できるため返り値はリストになります。単一の文字列なら [[1]] で最初の要素を取り出します。
そして trimws() は、現実のデータが必ずまとっている空白を剥がします。
既定では両端を削ります。which = "left" や "right" で片側だけを削ることもできます(名前は文字列の先頭と末尾を指します)。
stringr という選択肢
ここまではすべて基本Rで、常に利用でき、インストールも不要です。tidyverseの stringr パッケージは、同じ操作を一貫した str_* の命名体系で包み、常に文字列を第1引数に置きます。そのほうが覚えやすいと感じる人も多いでしょう(インストールについてはパッケージを参照)。
library(stringr)
str_detect(files, "csv") # like grepl(), data first
str_replace_all(s, "good", "great") # like gsub(), arguments reordered
str_length("hello") # like nchar()
とはいえ基本Rの文字列関数は知っておく価値があります。あらゆるスクリプト、Stack Overflowの回答、エラーメッセージで出会うからです。まず基本の名前を覚え、引数の順番の不揃いが煩わしくなってきたらstringrを取り入れましょう。
この記事のまとめ
- 文字列は慣習として二重引用符を使います。
nchar()は文字数、length()はベクトルの要素数を数えます。 - 連結は
paste()/paste0()。sepは引数どうしを、collapseはベクトルを1つの文字列に接着します。 sprintf()は書式付き出力を担当します:%s、%d、%.2f。sub()は最初の一致、gsub()はすべての一致を置換し、grepl()は一致を判定します。いずれも既定は正規表現なので、リテラルなテキストにはfixed = TRUEを渡します。strsplit()はリストを返します([[1]]を取り出す)。trimws()は余白付きの入力を整えます。
次は、プログラムへのテキストの出し入れです。print() と cat() による表示と、ユーザー入力の読み取りを扱います。
よくある質問
Rで文字列を連結するには?
paste() か paste0() を使います。Rには文字列用の + はありません。paste("data", "science") は "data science"(既定でスペース区切り)、paste0("data", "science") は何も挟まずに連結します。区切り文字を変えるには sep =、ベクトル全体を1つの文字列に融合するには collapse = を使います。
Rで文字列の長さを取得するには?
nchar("hello") は文字数である5を返します。length("hello") は1を返します。Rの length() はベクトルの要素数を数えるもので、1つの文字列は要素1つのベクトルだからです。length() と nchar() の取り違えは初心者の定番のミスです。
Rのsub()とgsub()の違いは何ですか?
どちらも検索と置換を行いますが、sub() は最初の一致だけを置換し、gsub()(global sub)はすべての一致を置換します。どちらも既定でパターンを正規表現として扱うので、リテラルなテキストとして一致させたいときは fixed = TRUE を渡します。
Rで文字列を分割するには?
strsplit(x, split) がパターンで分割しますが、返り値はリストです(複数の文字列を一度に分割できるため)。単一の文字列なら最初の要素を取り出します。strsplit("a,b,c", ",")[[1]] で文字列ベクトル "a" "b" "c" が得られます。