このページはKAKENHIデータベースからダウンロードできるCSVファイルの「研究代表者」列から以下の情報を抽出する方法を紹介していきます。
- 研究者番号の取得
- 研究者の職名の取得
- 所属部局の取得
必要なパッケージとデータは以下の通りです。今回は2019年度の全採択課題を用います(kaken_2019_20191201.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_2019_20191201.csv")
まず、研究代表者列に入っているデータのパターンを確認しておきます。個人情報満載なのでサイト上ではコードを実行しませんが、概ね、以下のようなパターンでデータが格納されているのではないかと思われます。
「苗字 名前 所属機関, 所属部局, 職名 (研究者番号)」
d %>% select("研究代表者") %>%
datatable()
研究者番号のパターンは「数字8桁」であり、これを正規表現で表すと「\\d{8}」になります。以下のコードではstr_extract関数により、研究代表者列からこのパターンを抽出しています。なお、研究者番号保有者に限定するため、研究種目から「奨励研究」を除外し、また、研究代表者列が空白でないデータのみを対象にしています。
d %>%
# 奨励研究を削除
filter(研究種目 == "奨励研究") %>%
# 研究代表者の列のみ抽出
select(研究代表者) %>%
# 研究代表者が空白でない行だけ抽出
filter(!(研究代表者 == "")) %>%
# 研究代表者列から8桁の数字を抽出し、Res.ID列に格納
mutate(Res.ID = str_extract(研究代表者, "\\d{8}")) %>%
datatable()
次に、研究者の職名を抽出します。研究代表者列は「苗字 名前 所属機関, 所属部局, 職名 (研究者番号)」の形式でデータが入っているので、「最後のコンマの直後から「(」の直前まで」が職名を表していると考えられます。この部分を一気に取り出すのは難しいので、以下の2段階に分けて職名を抽出します。
1. 最後のコンマの直後から末尾までの文字列を取得
2. 「(研究者番号)」の削除
なお、1段階目の処理については、全体を「先頭から最後のコンマまで」のパートとそれ以降のパートに分割し、str_replace関数を用いて2つ目のパートで上書きするような処理を行なっています。
d %>%
filter(研究種目 != "奨励研究") %>%
select(研究代表者) %>%
filter(!(研究代表者 == "")) %>%
# 最後のコンマ直後の文字列から末尾までを取得
mutate(職名 = str_replace(研究代表者, "(^.+,)(.+$)", "\\2")) %>%
# 「(研究者番号)」の削除
mutate(職名 = str_replace(職名, "\\(\\d{8}\\)", "")) %>%
# 前後の空白を削除
mutate(職名 = str_trim(職名, side = "both")) %>%
# 職名の列のみ選択
select(職名) %>%
# 可視化
datatable()
最後に、所属部局を抽出します。所属部局は2つのコンマに挟まれた部分の文字列が該当し、正規表現を用いると「(?<=,).+(?=,)」となります。以下のコードでは、str_extract関数を用いてこの正規表現にマッチする文字列を抽出しています。
d %>%
filter(研究種目 != "奨励研究") %>%
select(研究代表者) %>%
filter(!(研究代表者 == "")) %>%
# 「最後のコンマの直後から末尾まで」の文字列を取得
mutate(所属部局 = str_extract(研究代表者, "(?<=,).+(?=,)")) %>%
# 前後の空白を削除
mutate(所属部局 = str_trim(所属部局, side = "both")) %>%
# 可視化
datatable()
職名と所属部局の抽出の例では、研究代表者列にはコンマが2つ含まれていることを前提とし、コンマの位置を手掛かりに抽出を行なってきました。この前提は正しかったのでしょうか。以下のコードでは研究代表者列の各値に含まれるコンマの数を取得し、コンマの数ごとに何行のデータがあるのかを集計しています。
d %>%
filter(研究種目 != "奨励研究") %>%
select(研究代表者) %>%
filter(!(研究代表者 == "")) %>%
# 研究代表者に含まれるコンマの数をN_comma列に格納
mutate(N_comma = str_count(研究代表者, ",")) %>%
# コンマの数によってデータのグループ化
group_by(N_comma) %>%
# 各グループの行数を集計
summarize(N = n()) %>%
# 可視化
datatable()
残念ながら今まで対象としてきたデータにはコンマが1つしかないデータが存在しているようです。これらのデータについては上記で紹介してきた方法は適用できませんので、例外処理を行います。以下のコードは所属部局を取得するコードを改変したものです。あらかじめ研究代表者列に含まれるコンマの数を取得しておき、コンマの数が2の場合は上記の処理を、それ以外の場合は「NA」を格納しています。
d %>%
filter(研究種目 != "奨励研究") %>%
select(研究代表者) %>%
filter(!(研究代表者 == "")) %>%
# 研究代表者に含まれるコンマの数をN_comma列に格納
mutate(N_comma = str_count(研究代表者, ",")) %>%
# コンマの数が2つの時には「最後のコンマ直後から末尾まで」の文字列を取得、それ以外は「NA」
mutate(所属部局 = ifelse(N_comma == 2, str_extract(研究代表者, "(?<=,).+(?=,)"), NA)) %>%
# 前後の空白を削除
mutate(所属部局 = str_trim(所属部局, side = "both")) %>%
# 可視化
datatable()