ねこすたっと

ねこの気持ちと統計について悩む筆者の備忘録的ページ。

文字列の操作(1):文字列を検出する・並べ替える(stringrパッケージ)[R]

stringrパッケージは文字列データの操作を楽にしてくれるパッケージ。 tidyverseのコアパッケージに含まれているので、tidyverseパッケージを読み込めば使用可(ダメならlibrary(stringr)で直接読み込む)。

library(tidyverse)

今回はstringrパッケージの基本関数を見ていくだけにして、正規表現(regular expression)についてはまた別の機会に。

パターンにマッチする文字列を検出する

対象となる文字列の中に、指定するパターンがあるかを調べる。前者を引数string、後者を引数patternで指定する(見やすさのためstring=, pattern=は省略)。 ここで扱う関数は以下のとおり。

  • str_detect( ):指定するパターンが含まれるかどうかの真偽
  • str_which( ):指定するパターンが、対象となる文字列ベクトルの何番目の要素に含まれるか
  • str_starts( ):指定するパターンで始まるかどうかの真偽
  • str_locate( ):指定するパターンが最初に登場する位置
  • str_locate_all( ):指定するパターンが登場する位置(最初かどうかを問わない)
  • str_count( ):指定するパターンが登場する回数
  • %in%:指定する文字列のリスト(ベクトル)に含まれているかどうかの真偽

例示のため、次のような2つのサンプルデータ(中四国および瀬戸内の県名)を定義する。

chushikoku <- c("鳥取県","島根県","岡山県","広島県","山口県",
                "徳島県","香川県","愛媛県","高知県")
setouchi <- c("兵庫県","岡山県","広島県","山口県","徳島県","香川県","愛媛県")

指定パターンが含まれるかどうか判定する

まずstr_detect( )を使って、各要素に「"山”が含まれているかどうか」を判定してみる。

> str_detect(chushikoku,"山") 
[1] FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE

上の判定が何番目の要素でTRUEとなっているかを見たいときは、str_which( )を使う。

> str_which(chushikoku,"山")
[1] 3 5

3番目(岡山県)と5番目(山口県)が該当する。

str_starts( )を使うと、「"山"で始まっているか」を判定する。

> str_starts(chushikoku,"山") 
[1] FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE

今回は岡山県はマッチせず、山口県のみが抽出された。

指定パターンが含まれる位置を返す

str_locate( )では、「対象の文字列の中で、指定した文字列がどこにあるか」を返す。複数の"山"が含まれていても、帰ってくるのは先頭のみ。

> str_locate("山本山","山")
     start end
[1,]     1   1

これに対して、str_locate_all( )を使うと、対象の文字列に含まれる全ての"山"が対象になる。

> str_locate_all("山本山","山")
[[1]]
     start end
[1,]     1   1
[2,]     3   3

指定したパターンが含まれる数を数えたいときは、str_count( )を使う。

> str_count(chushikoku, "山")
[1] 0 0 1 0 1 0 0 0 0

str_*( )ではないが、指定する文字列のリスト(あるいはベクトル)に含まれているかどうかの真偽を判定したいときは、%in%を使う。 例えば、中四国の県の中で、瀬戸内に面しているかどうかを判定したいときは、下のコードでわかる。

> chushikoku %in% setouchi
[1] FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

文字列の一部分を抽出する

対象となる文字列の一部を抽出したり、置換したりする。 ここで扱う関数は以下のとおり。

  • str_sub( ):対象となる文字列における位置(例:前から1番目〜後ろから2番目など)を指定して部分抽出する
  • str_subset( ):対象となる文字列の中で、指定パターンを含む要素の全体を抽出する
  • str_extract( ), str_match( ):対象となる文字列の中で、指定パターンにマッチする部分を抽出する(最初に登場した箇所のみ)
  • str_extract_all( ), str_match_all( ):対象となる文字列の中で、指定パターンにマッチする部分を抽出する(全て)

例示のため、次のような2つのサンプルデータ(関西の県名)を定義する。

kansai <- c("滋賀県","京都府","大阪府","兵庫県","奈良県","和歌山県")

keihanshin <- c("kyoto","osaka","kobe")

まずはstr_sub( )で文字列内での位置をもとにして部分抽出してみる。
引数startで部分抽出する最初の位置、引数endで部分抽出する最後の位置を指定する。 位置は数字で指定する。プラスなら先頭から数えた位置、マイナスなら末尾から数えた位置。

下のコードで、「各要素の先頭(=1)〜 末尾から2番目(=-2)」が抽出される(つまり、末尾の1文字が除外される)。

> str_sub(kansai, start=1, end=-2)
[1] "滋賀"   "京都"   "大阪"   "兵庫"   "奈良"   "和歌山"

str_subset( )を使うと、指定したパターンを含む要素を抽出できる(マッチした部分だけではなく要素全体)。 例えば下のコードで"府"を含む要素だけが抽出される。

> str_subset(kansai,"府") 
[1] "京都府" "大阪府"

"府"だけではなく要素全体が抽出されている。

次に、str_extract( )でパターンにマッチする部分を抽出してみる。この関数では初めにマッチする部分だけが抽出される。 下のコードで[aeiou]は、「"a","e","i","o","u"のいずれか」を表している(正規表現についてはまた別の機会に)ので、最初に出てくる母音が抽出される。

> str_extract(keihanshin,"[aeiou]") 
[1] "o" "o" "o"

str_extract_all( )とすると、最初に登場するものだけではなく、対象の文字列に含まれている該当部位が全て抽出される。

> str_extract_all(keihanshin,"[aeiou]")
[[1]]
[1] "o" "o"

[[2]]
[1] "o" "a" "a"

[[3]]
[1] "o" "e"

抽出された部分は、対象の文字列毎にベクトルとして返される。

str_match( )およびstr_match_all( )も同様にマッチする部分を抽出するが、こちらは「ベクトルのリスト」ではなく行列として結果が返ってくる。

> str_match_all(keihanshin,"[aeiou]")
[[1]]
     [,1]
[1,] "o" 
[2,] "o" 

[[2]]
     [,1]
[1,] "o" 
[2,] "a" 
[3,] "a" 

[[3]]
     [,1]
[1,] "o" 
[2,] "e" 

正直、未熟な私には使い分け方が分かりません。

文字列を並べ替える

次に、文字列の並べ替え(ソート)で使う関数を紹介する。

  • str_order( ):元の文字列ベクトルで何番目の要素がどのような順序に並ぶかを返す
  • str_sort( ):各要素を並べ替えて返す

指定する引数は、

  • decreasing:TRUEなら降順、FALSEなら昇順。
  • na_last:NAを最後にするかどうか。TRUEなら最後、FALSEなら先頭。
  • numeric:TRUEなら数字は数字として扱う。FALSEなら文字列として扱う。
  • locale:使用する言語(ここでは英語="en")

例えば、str_order( )だと下のようになる。

str_order(keihanshin,
          decreasing = FALSE, 
          na_last = TRUE, 
          numeric = FALSE, 
          locale = "en")
[1] 3 1 2

元々の文字列ベクトルで3番目の要素("kobe")が先頭、2番目の要素("osaka)が最後ということ。

str_sort( )だと下のような感じ。

str_sort(keihanshin,
         decreasing = FALSE, 
         na_last = TRUE, 
         numeric = FALSE, 
         locale = "en")
[1] "kobe"  "kyoto" "osaka"

おわりに

  • 長かったので2つに分けました。後編は下のリンクから。

necostat.hatenablog.jp

参考資料

qiita.com