前回記事では、PubMedの検索結果のWebページをBeautifulSoupでパースして解析しました(邪道ですが、、、)。今回はNCBIのAPIを使って、以下に挑戦してみました。
- 特定の用語に関して、年ごとの検索ヒット数の変化を調べる
- ヒットした文献の情報をまとめて取得してリスト化する
PubMed情報を取得できるPythonパッケージとしてBiopythonがありますが、今回は一般的なAPIの取り扱いの練習のために自前で実装してみることにしました。
実行環境
- MacOS Sierra
- Xcode 9.2
- Python 3.6.1
- requests 2.14.2
- matplotlib 2.0.2
- pandas 0.20.1
- jupyter 1.0.0
ソースコード
PubMedクラスの関数として、以下の2つを用意しました。
- クエリから検索ヒット件数とidのリストを返す
search
関数 - idのリストから、論文の詳細情報を取得する
get_article_info
関数
ソースコード(折りたたみ)
%matplotlib inline
import matplotlib.pyplot as plt
import requests
import time
import pandas as pd
from collections import OrderedDict
class PubMed:
def __init__(self):
self.baseURL = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/"
def search(self,*terms):
terms = "+AND+".join(list(terms))
query = f"db=pubmed&term={terms}"
dataFormat = "json"
search_command = "esearch.fcgi"
self.searchURI = f"{self.baseURL}{search_command}?{query}&retmode={dataFormat}"
result = requests.get(self.searchURI)
print(f"{result}\n")
data = result.json()
self.count = data["esearchresult"]["count"]
self.id_list = data["esearchresult"]["idlist"]
time.sleep(2) #アクセスしすぎないように配慮
def get_article_info(self):
summary_command = "esummary.fcgi"
pubmedURL = "https://www.ncbi.nlm.nih.gov/pubmed/"
key_list = ['source','volume','issue','pages']
new_key_list = ['journal','volume','issue','pages']
self.result_list = []
for n,id in enumerate(self.id_list):
query = f"db=pubmed&id={id}"
dataFormat = "json"
result = requests.get(f"{self.baseURL}{summary_command}?{query}&retmode={dataFormat}")
print(f"{n}:{id}:{result}\n")
data = result.json()
result_dic = OrderedDict()
result_dic['title'] = data['result'][id]['title']
author_list = []
for author in data['result'][id]['authors']:
author_list.append(author['name'])
result_dic['all_authors'] = ", ".join(author_list)
publication_date = data['result'][id]['pubdate']
result_dic['year'] = publication_date.split(" ")[0]
for key,new_key in zip(key_list,new_key_list):
result_dic[new_key] = data['result'][id][key]
result_dic['link'] = f"{pubmedURL}{id}"
self.result_list.append(result_dic)
time.sleep(2) #アクセスしすぎないように配慮
結果
1. 特定の用語に関して、年ごとの検索ヒット数の変化を調べる
"rna-seq"という用語に対し、2004年から2018年までの変化を調べてグラフ化してみました。APIで出版年を指定するタグは[DP]
だそうです。
pubmed = PubMed()
hit_count = {}
for year in range(2004,2019):
pubmed.search("rna-seq",f"{year}[DP]")
hit_count[year] = int(pubmed.count)
うまくいくと、<Response [200]>
というメッセージが出るようになっています。HTTPのレスポンス状態コードについてはこちらを参照してください。
hit_count
をPandasのDataFrameに変換します。
df = pd.DataFrame(hit_count,index=["count"]).T
df
長いため結果のテーブルは折りたたんでいます。
count | |
---|---|
2004 | 0 |
2005 | 0 |
2006 | 0 |
2007 | 0 |
2008 | 6 |
2009 | 33 |
2010 | 156 |
2011 | 359 |
2012 | 631 |
2013 | 1127 |
2014 | 1723 |
2015 | 2322 |
2016 | 2809 |
2017 | 3583 |
2018 | 3072 |
Matplotlibでグラフ化した結果がこちら。
plt.plot(df)
plt.xlabel("Year")
plt.ylabel("Hit count")
plt.show()
2008年にはじめの報告があり、その後順調に報告数が増加していることがわかります。
近年はやや減少傾向にありますが、理由はよくわかりません。現状、誰でも実施可能なポピュラーな手法になっているため、わざわざ明記しない報告が増えてきた可能性はあります。
[9/30 22:37追記] 先程気づいたのですが、2018年のみ9ヶ月分の集計ですので、最終的には2017年を超える可能性が高いですね。お詫びして訂正いたします。
2. ヒットした文献の情報をまとめて取得してリスト化する
2008年でヒットした、6件の文献情報を取得してみます。
pubmed = PubMed()
pubmed.search("rna-seq","2008[DP]")
print(pubmed.id_list) #取得したidのリスト
#['19087247', '18599741', '18550803', '18516045', '18488015', '18451266']
pubmed.get_article_info() #全てのidの文献情報取得
こちらも実行すると番号:id:<Response [200]>
といった、HTTPレスポンス状態コードが返ってくるようにしました。
文献情報は`pubmed.result_list`に入っています。(折りたたみ)
import pprint
pprint.pprint(pubmed.result_list[-1])
#OrderedDict([('title',
# 'The transcriptional landscape of the yeast genome defined by '
# 'RNA sequencing.'),
# ('all_authors',
# 'Nagalakshmi U, Wang Z, Waern K, Shou C, Raha D, Gerstein M, '
# 'Snyder M'),
# ('year', '2008'),
# ('journal', 'Science'),
# ('volume', '320'),
# ('issue', '5881'),
# ('pages', '1344-9'),
# ('link', 'https://www.ncbi.nlm.nih.gov/pubmed/18451266')])
Pandasデータフレームで見るとこんな感じ。
df_paper = pd.DataFrame(pubmed.result_list[-1],index=["details"]).T
df_paper
details | |
---|---|
title | The transcriptional landscape of the yeast gen... |
all_authors | Nagalakshmi U, Wang Z, Waern K, Shou C, Raha D... |
year | 2008 |
journal | Science |
volume | 320 |
issue | 5881 |
pages | 1344-9 |
link | https://www.ncbi.nlm.nih.gov/pubmed/18451266 |
この論文が"RNA-Seq"という単語を使った、PubMed上で見られる一番最初の報告であると思われます。なんとなく感慨深いですね。