医療職からデータサイエンティストへ

統計学、機械学習に関する記事をまとめています。

R使いのための文字列処理stringrの使い方

R文字列

Rで文字列処理をすることって地味によくありますよね。

そんな突如として必要性が湧いてくる文字列処理、Rには文字列を扱うパッケージがいくつかありますが、その中でも抜群に使いやすいのが{stringr}の特徴です。

文字列処理を統一的な方法で行えるため、直感的にも分かりやすく、さらには{dplyr}などのデータフレーム加工パッケージとも相性が良いです。

www.medi-08-data-06.work

今回はそんな{stringr}の使い方をまとめていきます。

文字列の基本処理関数

まずは、文字列の連結や分割、切り出しなどの基本関数を紹介します。

  • str_length:文字の長さを調べる
  • str_trim:空白の除去
  • str_dup:文字の繰り返し
  • str_c:文字の連結
  • str_sub:文字の切り出し
  • str_split:文字の分割

str_length:文字の長さを調べる

単に文字列の長さを返します。通常のlengthはオブジェクトの長さを返すため、文字列の長さは測れません。

library(stringr)

str_length("Apple")
[1] 5

#lengthはだめ
length("Apple")
[1] 1

str_trim:空白の除去

str_trimは文字の前後にある空白を取り除きます。引数のsideには(both,right,left)があり、どこの空白を除去するかを指定できます。

str_trim(" Apple ",side = "both")
[1] "Apple"

str_dup:文字の繰り返し

str_dupは指定の文字列を繰り返します。repと何が違うかというと、repはベクトル、str_dupは一つの文字列として返します。

str_dup("Apple",5)
#一つの文字列になる
[1] "AppleAppleAppleAppleApple"

#ベクトルになる
rep("Apple",5) 
[1] "Apple" "Apple" "Apple" "Apple" "Apple"

str_c:文字の連結

str_cは私が一番よく使う関数なのですが、文字列を空白なしで連結します。Rの基本関数の中ではpaste0と同じ働きです。 str_cはsepという引数を受け取って、任意の文字で繋げることができます。

#デフォルトは空白なし
str_c("Apple","Banana")
[1] "AppleBanana"

#+で繋げる
> str_c("Apple","Banana","Pineapple",sep="+")
[1] "Apple+Banana+Pineapple"

また、文字列をベクトルで渡すとそれぞれの文字に対して、文字を結合してくれます。

#フルーツ名をベクトルで格納
fruits <- c("Apple","Banana","Pineapple")

#Iとfruitsをlike a で繋げる(a appleなのはご愛嬌)
str_c("I",fruits,sep=" like a ")
[1] "I like a Apple"     "I like a Banana"    "I like a Pineapple"

逆にベクトルの中の要素を繋げたいときは、collapseという引数を指定します。 collapseに指定した文字で結合します。

#str_cのみだとそのまま返ってくる
str_c(fruits)
[1] "Apple Banana Pineapple"

#空白で結合
str_c(fruits,collapse = " ")
[1] "Apple Banana Pineapple"

str_sub:文字の切り出し

str_subはstartとendを受け取って、文字数で指定した箇所を切り出します。

#1文字目から5文字目まで
str_sub(fruits,start = 1,end=5)
[1] "Apple" "Banan" "Pinea"

#マイナスは後ろから(後ろから3文字目から後ろから2文字目まで)
str_sub(fruits,start = -3,end=-2)
[1] "pl" "an" "pl"

さらに、これを使うと任意の箇所の文字を変更できます。

#最後一文字を大文字に変更
str_sub(fruits,start = -1) <- c("E","A","E")
> fruits
[1] "ApplE"     "BananA"    "PineapplE"

str_split:文字の分割

文字列を任意の文字で分割するにはstr_splitを使います。結果はリストで返ってきますが、simplify=Tとするとマトリックス型で返ってきます。

例えばID番号と名前が空白で区切られて格納されている文字列を分割してみます。

ID_name <- c("01 Tanaka Hanako","02 Yamada Taro","03 Sato Jiro","04 Yamamoto Jun")


str_split(ID_name," ")
[[1]]
[1] "01"     "Tanaka" "Hanako"

[[2]]
[1] "02"     "Yamada" "Taro"  

[[3]]
[1] "03"   "Sato" "Jiro"

[[4]]
[1] "04"       "Yamamoto" "Jun"     

#simplify=Tでマトリックスで返ってくる
 str_split(ID_name," ",simplify=T)
     [,1] [,2]       [,3]    
[1,] "01" "Tanaka"   "Hanako"
[2,] "02" "Yamada"   "Taro"  
[3,] "03" "Sato"     "Jiro"  
[4,] "04" "Yamamoto" "Jun"  

さらに分割数も指定できるので、n=2とすると、ID番号と名前に分割することもできます。

str_split(ID_name," ",simplify=T,n=2)

     [,1] [,2]           
[1,] "01" "Tanaka Hanako"
[2,] "02" "Yamada Taro"  
[3,] "03" "Sato Jiro"    
[4,] "04" "Yamamoto Jun"

すごい! ちなみに日本語、全角にも対応しています。

文字列マッチング

目視でデータが確認できない時、条件にマッチした文字のみを処理したい場合があります。そんな時もstringrには便利な関数がたくさんあります。

指定できるパターンに正規表現を使うと、自由自在にお望みの文字列を検索できるのですが、今回は正規表現を使わずに関数の使い方に注目して紹介していきます。

  • str_subset:指定パターンを含む文字列を返す
  • str_locate:指定パターンにマッチする箇所の文字数を返す
  • str_detect:指定パターンを含んでいるかどうかをTRUE,FALSEで返す
  • str_replace:指定パターンにマッチした箇所を違う文字に置き換える

それではいきましょう。

www.medi-08-data-06.work

str_subset:指定パターンを含む文字列を返す

こちらは、指定パターンを含む文字列を返してくれます。例えば"A"を含む文字列を探してみます。

fruits <- c("Apple","Banana","Pineapple","Grape","Orange")

#Aを含むフルーツ
str_subset(fruits,"A")
[1] "Apple"

#AまたはBを含むフルーツ
> str_subset(fruits,"(A|B)")
[1] "Apple"  "Banana"

上記の通り、論理式でも指定できます。論理式ごとクウォート、もしくはダブルクウォートで囲うことに注意です。

str_detect:指定パターンを含んでいるかどうかをTRUE,FALSEで返す

str_detectstr_subsetと違ってTRUE、FALSEで結果が返ってきます。

fruits <- c("Apple","Banana","Pineapple","Grape","Orange")

str_detect(fruits,"A")
[1]  TRUE FALSE FALSE FALSE FALSE

str_detect(fruits,"(A|B)")
[1]  TRUE  TRUE FALSE FALSE FALSE

str_locate:指定パターンにマッチする箇所の文字数を返す

str_locateは、マッチする箇所の最初と最後の文字数をマトリックスで返してくれます。

fruits <- c("Apple","Banana","Pineapple","Grape","Orange")

#ppを含む箇所
str_locate(fruits,"pp")
    start end
[1,]     2   3
[2,]    NA  NA
[3,]     6   7
[4,]    NA  NA
[5,]    NA  NA

str_locateは最初にマッチした場所しか返さないので、全ての場所を知りたい場合は、str_locate_allとします。

#naを含むのはBananaの3~4文字目と5~6文字目
str_locate_all(fruits,"na")
[[1]]
     start end

[[2]]
     start end
[1,]     3   4
[2,]     5   6

[[3]]
     start end

[[4]]
     start end

[[5]]
     start end

str_replace:指定パターンにマッチした箇所を違う文字に置き換える

str_replaceはマッチした箇所を違う文字に置き換えることができます。

fruits <- c("Apple","Banana","Pineapple","Grape","Orange")

#aをXに置き換える
str_replace(fruits,"a","X")
[1] "Apple"     "BXnana"    "PineXpple" "GrXpe"    
[5] "OrXnge"  

しかし、この関数もマッチした最初の一文字しか置き換えれないため、全てを置き換えるには、str_replace_allを使います。

#全てのaをXXXに置き換える
str_replace_all(fruits,"a","XXX")
[1] "Apple"        "BXXXnXXXnXXX" "PineXXXpple" 
[4] "GrXXXpe"      "OrXXXnge"

その他便利な関数

その他にも便利な関数を紹介しておきます。

  • str_to_ lower,str_to_ upper:大文字、小文字の変換
  • str_pad:指定の文字数まで任意の文字で埋める

str_to_ lower,str_to_ upper:大文字、小文字の変換

これは簡単で、大文字、小文字の変換を行います。

str_to_lower("AAABBB")
[1] "aaabbb"
str_to_upper("aaabbb")
[1] "AAABBB"

str_pad:指定の文字数まで任意の文字で埋める

str_padは文字数の違う文字列ベクトルを指定の文字数まで、任意の文字(デフォルトはスペース)で埋めることができます。引数では埋める方向(both,right,left)も指定できます。

#文字数が10文字になるまで左を空白で埋める
str_pad(fruits,width = 10,side="left")
[1] "     Apple" "    Banana" " Pineapple" "     Grape"
[5] "    Orange"

#文字数が10文字になるまで右を0で埋める
str_pad(fruits,width = 10,side="right","0")
[1] "Apple00000" "Banana0000" "Pineapple0" "Grape00000"
[5] "Orange0000"

まとめ

いかかでしょうか? Rで文字列操作を行う時には、{stringr}を使えば文字列を自由自在に扱えます。

さらにパターンマッチングでは、正規表現を使うと文字列処理に関しては怖いもの無しですね。

正規表現については、またどこかでまとめていきます。

参考

stringr: Rの文字列をまともな方法で処理する - Heavy Watal

14 Strings | R for Data Science

上記サイトの和書版です。dplyrやpurrr、tidyrなどモダンなパッケージをまとめたtidyverseを中心に、データの解析手法そのものよりも、いかに効率よくデータを解析するかが書かれています。Rに慣れ始めた頃に読むのがおすすめです!

Rではじめるデータサイエンス

Rではじめるデータサイエンス