0. はじめに

このページはKAKENHIデータベースからダウンロードできるCSVファイルの「研究機関」列をクリーニングする方法を紹介してきます。具体的には、研究機関の列について以下のような処理を行なっていきます。


- 「AA大学(2017)/BB大学(2016)」 → 「AA大学」 or 「BB大学」
- 「株式会社CC」、「DD大学」 → 「CC」、「DD」


1. 下準備

必要なパッケージとデータは以下の通りです。今回は2016年度の全採択課題を用います(kaken_2016_20191207.csv)。

# パッケージの読み込み
library(data.table)   # 高速なデータインポートのため
library(dplyr)        # データの整理のため
library(DT)           # 集計表の出力のため
library(stringr)      # 文字列操作のため

# インストールされていない場合は、以下のコマンドの「#」を外して実行
# install.packages("data.table")
# install.packages("dplyr")
# install.packages("DT")
# install.packages("stringr")


# 使用するデータのインポート
d <- fread("kaken_2016_20191207.csv")


2. データの確認

まず、研究機関列にどのようなデータが入っているのかを確認します。以下のコードは研究機関列の各値の個数を集計し、降順となるように並び替えを行なっています。

d %>% 
  group_by(研究機関)  %>%   # 研究機関列の値ごとにグループ化
  summarize(N = n()) %>%    # 各グループ内の行数を計算し、N列を作成
  arrange(-N) %>%           # N列の値が降順となるように並び替え
  datatable                 # 可視化

上記の表をざっと見ていて気になるのは以下の2点です。

  • 複数の研究機関が含まれる場合がある
    これは、特にページの後ろの方を見てもらえると確認できます。研究期間中に研究者の所属機関が変わることによって、移動前後の研究機関のデータが含まれるようになります。バリエーションはありますが、「AA大学(2017) / BB大学(2016)」のような形式です。これは研究機関ごとに集計する際に誤差を生じさせる直接的な要因となるため、何らかの処理が必要になってきます。

  • 所属機関を表す文字列が長い
    「株式会社」や「公益財団法人」、また、「〜大学」のように法人種別がつくパターンです。集計の正確さにはそこまで関係ありませんが、集計表やグラフにまとめる際に過剰なスペースを取ることになります。レポートにまとめる場合にはできるだけ短い形式にしておいた方が何かと便利です。

以下では、これら2点についてデータをきれいにしていきます。


3. 複数研究機関の処理

目的によって行う処理は変わってきますが、ここでは1つの研究機関を抜き出す方法を紹介します。


3.1. パターンの確認

具体的な処理に先立ち、どのようなパターンがあるのかを確認しておきます。以下のコードは、各値に含まれるスラッシュ(/)の数を取得し、スラッシュの数ごとに個数を集計しています。以下の通り、殆どの値が単一の研究機関デスガ、複数の研究機関を含む値が1500弱あることがわかります。また、3つの研究機関が含まれる値もあるので注意が必要です。

d %>% 
  mutate(N_slash = str_count(研究機関, "/")) %>%    # 各値の「/」個数を算出しN_slash列に格納
  group_by(N_slash) %>%                             # 「/」の数でグループ化
  summarise(N = n()) %>%                            # 各グループの行数を算出
  datatable                                         # 可視化


3.2. 単一の研究機関の抽出

それでは、単一の研究機関を抽出していきますが、ここからはstringrという文字列操作のパッケージだけでなく正規表現(Regex)に関する知識が必要になってきます。正規表現とは文字列のパターンの表現方法であり、これが使えると文字列操作が格段に楽になります。詳しくはhttps://stringr.tidyverse.orgをご参照ください。


最新の研究機関を抽出する

最新の研究機関は「文字列の先頭から最初のスラッシュの直前まで」の文字列です。正規表現ではこのパターンを「^.+?(?=/)」と表すことができます。あとは、str_extract関数を用いて、この正規表現にマッチする文字列を研究機関列から抽出するだけです。なお、スラッシュの前後には空白が入っていますので、最後にstr_trim関数を用いて余分な空白を削除しています。

d %>%
  
  # 「研究機関」列のみを抽出
  select(研究機関) %>%      
  
  # 「研究機関」列にスラッシュが含まれる行のみ抽出
  filter(str_detect(研究機関, "/")) %>%    
  
  # 「文字列の先頭から最短のスラッシュの直前まで」の文字列を取得し「研究機関2」列に代入
  mutate(研究機関2 = str_extract(研究機関, "^.+?(?=/)")) %>%    
  
  # 前後の空白を削除
  mutate(研究機関2 = str_trim(研究機関2, side = "both")) %>%

  # スラッシュの数をN_slash列
  mutate(N_slash = str_count(研究機関, "/")) %>% 
  
  # 可視化
  datatable

最も古い研究機関を抽出する

最も古い研究機関は「一番最後のスラッシュの直後から文字列の最後まで」です。これを取得する1つの方法としては、文字列を「先頭から一番最後のスラッシュまで」の部分と「最後のスラッシュ直後から文字列の最後まで」の2つのパートに分けて、2つ目の部分を取得する方法です。正規表現では全体を「(^.+/)(.+$)」と表現し、括弧によって2つのパートを分けています。以下のコードでは、str_replace関数を用いて全体を2つ目のパートで上書きすることにより、最も古い研究機関を抽出しています。

d %>%
  select(研究機関) %>%      
  filter(str_detect(研究機関, "/")) %>%    

  # 「最後のスラッシュの直後から最後まで」の文字列を取得し「研究機関2」列に代入
  mutate(研究機関2 = str_replace(研究機関, "(^.+/)(.+$)", "\\2")) %>%    
  
  # 前後の空白を削除
  mutate(研究機関2 = str_trim(研究機関2, side = "both")) %>%

  # スラッシュの数をN_slash列
  mutate(N_slash = str_count(研究機関, "/")) %>% 
  
  # 可視化
  datatable

3.3. 所属期間(西暦)の削除

単一の研究機関が取得できたところで、最後に西暦を削除します。この処理も先ほどと同じように、2つのパートに分けて、「先頭から最後の「(」の直前まで」の文字列部分のみを取得します。先頭から「(」の直前までの文字列のパターンは正規表現で「(^.+(?=\())」、残りの文字列のパターンは「(.+$)」です。

d %>%
  select(研究機関) %>%      
  filter(str_detect(研究機関, "/")) %>%    
  mutate(研究機関2 = str_replace(研究機関, "(^.+/)(.+$)", "\\2")) %>%    

  # 「先頭から最後の「(」の直前まで」の文字列を取得し「研究機関3」列に代入
 mutate(研究機関3 = str_replace(研究機関2, "(^.+(?=\\())(.+$)", "\\1")) %>%
  
  # 前後の空白を削除
  mutate(研究機関3 = str_trim(研究機関3, side = "both")) %>%

  # スラッシュの数をN_slash列
  mutate(N_slash = str_count(研究機関, "/")) %>% 
  
  # 可視化
  datatable

なお、「(文字列)」を削除すれば良いのではないかと思う方もいらっしゃるかと思いますが、このパターンでは1行目の「(研究所)(2016)」が丸々消えるという意図しない結果を招くのでご注意ください。


4. 法人種別の削除

最後に、「株式会社〜」、「一般社団法人〜」「〜大学」のような法人種別を表す文字列を削除していきます。以下のコードでは、これらの表現をstr_replace関数によって空白と置換しています。

a <- c("独立行政法人", "国立研究開発法人", "公益財団法人")

d %>%
  select(研究機関) %>%      
  filter(str_detect(研究機関, "/")) %>%    
  mutate(研究機関2 = str_replace(研究機関, "(^.+/)(.+$)", "\\2")) %>%    
 mutate(研究機関3 = str_replace(研究機関2, "(^.+(?=\\())(.+$)", "\\1")) %>%
  mutate(研究機関3 = str_trim(研究機関3, side = "both")) %>%

 # 法人種別の削除  
  mutate(研究機関4 = str_replace(研究機関3, "^独立行政法人", "")) %>%
  mutate(研究機関4 = str_replace(研究機関4, "^国立研究開発法人", "")) %>%
  mutate(研究機関4 = str_replace(研究機関4, "^地方独立行政法人", "")) %>%
  mutate(研究機関4 = str_replace(研究機関4, "^公益財団法人", "")) %>%
  
  # 〜大学の削除
  mutate(研究機関4 = str_replace(研究機関4, "大学$", "")) %>%

  # 可視化
  datatable

なお、注意点としては、「〜大学」を削除する際に「大学$」というパターンを使っているところです。単純に「大学」というパターンを削除しようとすると「〜大学院大学」が「〜院大学」になってしまいます。「$」は文字列の末尾を表しており、これをつけることにより文字列最後の「〜大学」を削除することができます。反対に文字列の先頭は「\^」で表していますが、法人種別はたいてい文字列の頭に現れるので、今回のケースではあってもなくても大きな影響はなさそうです。