ねこすたっと

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

文字列の操作(2):文字列を加工する(stringrパッケージ)[R]

stringrパッケージは文字列データの操作を楽にしてくれるパッケージ。 前回は指定したパターンにマッチする文字列を検出したり、一部を抽出する方法を説明した。

necostat.hatenablog.jp

今回は文字列を加工する方法をみていく(実際には違う関数を使っても同じ操作を行うことはできるので、役割で2つに分けきれないとは思うんですが、分量が多くなったので...)。

tidyverseのコアパッケージに含まれているので、tidyverseパッケージを読み込めば使用可(ダメならlibrary(stringr)で直接読み込む)。

library(tidyverse)

文字列を変換する

文字列の一部を置換したり、小文字・大文字を変換したりする。 ここで扱う関数は以下のとおり。

  • str_replace( ), str_replace_all( ):対象の文字列の中でパターンにマッチした部分を置換する(_allがついていると初出に限定されない)
  • str_remove( ), str_remove_all( ):対象の文字列の中でパターンにマッチした部分を除去する(_allがついていると初出に限定されない)
  • str_to_upper( ):大文字にする(例:upper → UPPER)
  • str_to_lower( ):小文字にする(例:LOWER → lower)
  • str_to_title( ):先頭のみ大文字にする(例:a title → A Title)

文字列の一部分を置換する・除去する

str_replace( )を使って置換するときは、引数としてstring(対象とする文字列)、pattern(検索するパターン)、replacement(置換に使用する文字)を指定する。

下のコードでは、先程定義したkeihanshinの要素において、最初に登場した"a","e","i","o","u"を、"_"で置換する。

> str_replace(keihanshin, "[aeiou]", "_") 
[1] "ky_to" "_saka" "k_be" 

str_replace_all( )とすると、最初に限らずマッチするところ全てを置換する。

> str_replace_all(keihanshin, "[aeiou]", "_") 
[1] "ky_t_" "_s_k_" "k_b_" 

str_replace( )で置換に使用する文字に「""(=何もない)」を指定すると、str_remove( )と同じになる。

大文字・小文字を変換する

最後にstr_to_upper( )の使い方を示す。引数localeは使用する言語(ここでは英語="en")。

> str_to_upper(keihanshin, locale="en")
[1] "KYOTO" "OSAKA" "KOBE" 

新しい文字列を生成する

文字列を結合する

文字列同士を結合して新しい文字列を作成する。ここで扱う関数は以下のとおり。

  • str_c( ):文字列ベクトル同士を結合する
  • str_flatten( ):文字列ベクトルの要素をつなげて1つの文字列にする
  • str_dup( ):文字列を指定の回数だけ繰り返す

対象となる文字列の各要素に決まった文字を追加したいときは、str_c( )を使う。 例えば、関西の県名の冒頭に"a"と数字(1〜6)を追加したいときは下のコードを使う。

つなぐ文字列の間に挿入する文字は、引数sepで指定する。 また、引数collapseはベクトルの要素同士をつなぐときに使用する文字。 ここではcollapse=NULLとしておかないと、全体が1つの文字列につながってしまう。。

> str_c("a", 1:6, kansai, sep="-", collapse=NULL) 
[1] "a-1-滋賀県"   "a-2-京都府"   "a-3-大阪府"   "a-4-兵庫県"  
[5] "a-5-奈良県"   "a-6-和歌山県"

全体を1つの文字列としてつなげたいときは、str_flatten( )を使う。 この場合は引数collapseで要素同士をつなぐときに使用する文字を指定する。。

> str_flatten(keihanshin, collapse="-")
[1] "kyoto-osaka-kobe"

ちなみに%>%も使える(今更感)。

keihanshin %>% 
  str_to_upper() %>% 
  str_flatten(collapse="-")

結果は下のとおり(大文字にして、"-"でつなげて1つの文字列にした)。

[1] "KYOTO-OSAKA-KOBE"

文字列を分割する

文字列同士を分割して新しい文字列を作成する。ここで扱う関数は以下のとおり。

  • str_split( ):指定したパターンが検出される部分で文字列を分割する
  • str_split_fixed( ):上記において、指定した数に分割する

例えば、「鹿児島県志布志市志布志町志布志」という地名を「志」で分割してみる。

x <- c("鹿児島県志布志市志布志町志布志")
str_split(x, pattern="志")

str_split( )を使うと、「志」は6つ含まれているので7つに分けられる(ただし、文字列の最後が「志」なので、7つ目は空っぽ)。

[[1]]
[1] "鹿児島県" "布"       "市"       "布"       "町"       "布"       ""       

str_split( )で分ける個数をn=3に指定すると、

str_split_fixed(x,pattern="志", n=3)
     [,1]       [,2] [,3]              
[1,] "鹿児島県" "布" "市志布志町志布志"

最初に出現した2つの「志」を使って、全体が3つに分割された。

文字列を挿入する

str_glue( )やstr_glue_data( )*1を使うと、他で計算された値や変数が持っている値を文章の中に挿入することができる(glueは「のり・接着剤」の意味)。

下のコードのように、挿入したい変数名は{ }で囲む。長さが同じベクトルを引用すればそれぞれに対して文章を作る。片方が長さ1なら繰り返し利用されるが、それ以外で長さが合っていなければエラーが出るみたい。

couple <- c("I","My wife")
our_ages <- c(35,30)
x <- our_ages + 1
str_glue("{couple} will be {x} years old next year.")
I will be 36 years old next year.
My wife will be 31 years old next year.

(2人とも若干サバを読んだ。)

str_glue_data( )を使うとデータフレームの変数に対して適応することができる。 下のコードでrownames( )はデータフレームの行名を取り出す関数(mtcarsデータでは行名が車種名になっているので)。 引数の.はパイプ記号で渡されたデータフレーム、つまりmtcarsのこと。

mtcars %>% str_glue_data("{rownames(.)} has {hp} hp")
Mazda RX4 has 110 hp
Mazda RX4 Wag has 110 hp
Datsun 710 has 93 hp
~~~(省略)~~~

あまり使い所はないかもしれないが、作成した文章を新たな変数として保持することもできる。このときは変数の個々の値に対して処理するのでstr_glue_data( )ではなくstr_glue( )を使う。

mtcars %>%
  mutate(description = str_glue("{rownames(.)} has {hp} hp"))

結果は割愛。

文字列の長さを調整する

最後に、対象となる文字列の長さを調べたり、長さを揃えたりする関数。 ここで扱う関数は以下のとおり。

  • str_length( ):対象となる文字列の各要素の長さ(何文字あるか)を返す
  • str_pad( ):対象となる文字列に指定した文字を追加して、長さを揃える
  • str_trunc( ):対象となる文字列の一部を指定した文字に置き換えて、長さを揃える
  • str_trim( ):スペース(タブや改行も含む)を除去
  • str_squish( ):両側のスペース(タブや改行も含む)を除去

まずはstr_length( )から。

> str_length(keihanshin)
[1] 5 5 4

当たり前だがstr_length("keihanshin")だと違う結果が返ってくる。

str_pad( )*2では以下の引数を指定する。

  • width:最終的に揃えたい長さ
  • side:文字を追加する場所。right, left, bothのいずれかを指定。
  • pad:追加する文字列

下のコードだと「対象の文字列の右側に"_"を追加して、長さを6に揃える」という意味。

> str_pad(keihanshin, width=6, side="right", pad="_") 
[1] "kyoto_" "osaka_" "kobe__"

widthで指定した値以上の長さの文字列では何も起こらない。

str_trunc( )ではstr_pad( )の反対で、文字列の一部を置き換えて長さを揃える。 指定する引数は以下のとおり。

  • width:最終的に揃えたい長さ
  • side:文字を置換する場所。right, left, centerのいずれかを指定。
  • ellipsis:置換に使用する文字列

下のコードだと「対象の文字列の右側を"."で置換して、長さを3に揃える」という意味。

> str_trunc(keihanshin, width=3, side="right", ellipsis = ".") 
[1] "ky." "os." "ko."

widthで指定した値以下の長さの文字列では何も起こらない。

対象となる文字列のスペースを除去したいときはstr_trim( )を使う。 これを使えば、半角スペース、全角スペース、タブ、改行のいずれも除去できる。

下のコード例では"中央区"の左側に全角スペースが1個、右側に半角スペースが2個あるが、side="right"を指定してるので右側のスペースは全て除去された。

> str_trim(" 中央区  ", side="right") 
[1] " 中央区"

str_squish( )*3を使うと両端の空白を除去する。str_trim( )でside="both"を指定した場合と同じ。

> str_squish(" 中央区  ")
[1] "中央区"

おわりに

  • glueは奥が深そうなので、また別の機会に勉強します。
  • 第5シーズン用に、と思った記事は1日で全て放出してしまいました。

参考資料

qiita.com

  • tidyverse内のglueのページです。

glue.tidyverse.org

*1:それぞれglueパッケージのglue( ), glue_data( )と同じ使い方だが、ここはstringrの記事なのでstr_***で統一しました。

*2:padding = 詰め物

*3:squish = 押しつぶす