Paperpileに登録している論文の引用関係をグラフで可視化(Python)


ブラウザ版を作りました! - 2021.01.16

はじめに

  • この記事は, 私が所属する会社のアドベントカレンダー( https://qiita.com/advent-calendar/2020/ppt )の記事です.
  • 弊社は受託がメインのため, 統一性はないものの幅広く富んだジャンルの記事がありますのでよろしければご参照ください.
  • 新卒のsarashiniくんの記事( https://qiita.com/sarashin/items/96a40571c66dc223f83d )などは彼の専門分野の知識からの語り口でとても興味深いポストなので是非.

概要

  • この記事は, Paperpile( https://paperpile.com/ )に登録してある論文の引用関係を, ネットワークグラフで可視化した試みの共有です.
  • 言語にはPythonを用いて, crossrefapi, networkx, plotlyを主に使用しています.

モチベーション

  • 論文のグラフ解析は古来よりある研究分野であり,著者の関係や論文の関係などをグラフ化し,経路検索やネットワーク中心性の計算や,シーズ探索を目的としているものがあります.
  • 今回の私のモチベーションは,自分が読んだ(登録した)論文の範囲の中の関係性,あるいはもう一つ先の引用論文を一度に可視化して整理したいと思ったため,今回この記事を書いています.

関連研究・事例

Connected Papers

  • https://www.connectedpapers.com/
  • 論文の引用関係だけではなく,独自に計算した類似性をエッジを貼る特徴量として用いてるところが興味深いネットワークです.

CitNetExplorer

Microsoft Academic

  • https://academic.microsoft.com/home
  • 意外と知られていないのですが, Microsoftが提供する論文データベース.これはグラフネットワークではないのですが, スクレイピングが禁止されているGoogle Scholarとは異なり, 論文のメタ情報がAPIで取得できる経路が用意されていて,それがAzureと同じ課金でできるので便利です.

手法

  • 極めてシンプルで, PaperpileからExportしたjsonファイルを元に, DOIをキーとしてcrossref( https://www.crossref.org/ )からメタ情報を取得し, グラフを作成します.

この記事は何が新しいのか

  • paperpileのjsonを利用している,すなわちデータソースの部分のみだと思います.zoteroやMendleyなどでは古よりやり尽くされているように思います.

ソースコード

全てこちらにおいてあります.
各自ランタイム起動後, PaperpileからExportしたjsonをアップロードすると動作すると思います.
https://colab.research.google.com/drive/1556vrlPU6phlHfa-B7AmiLumJtT0EMV0?usp=sharing
*不具合などありましたらこの記事にコメントください.

実装ポイント

Paperpileからのエクスポート

  • settingから選択できます

メタ情報の取得

  • DOIがPaperpileに登録されているものは,そのDOIからメタ情報を取得します.
  • なので,DOIが自動登録されなかった場合は,タイトルなどから逆引きして登録しておくことをおすすめします.
def makeGraph(row):
    if row["doi"] != "":
        # doiが存在している場合,引用文献を取得
        works = Works()
        paper = works.doi('https://doi.org/' + row["doi"])

        if paper is not None:
            graph_nodes[row["doi"]] = {
                "title": row["title"],
                "author": row["author"],
                "citedByLink": row["citedByLink"],
                "citedByCount": int(paper["is-referenced-by-count"]) if "is-referenced-by-count" in paper else -1,
                "referenceCount": int(paper["reference-count"]) if "reference-count" in paper else -1,
                "inPaperPile": True
            }

            if "reference" in paper:
                for ref in tqdm(paper["reference"]):
                    if "DOI" in ref:
                        if not ref["DOI"] in graph_nodes:
                            works = Works()
                            refpaper = works.doi('https://doi.org/' + ref["DOI"])
                            print(refpaper)
                            if refpaper is not None:
                                graph_nodes[ref["DOI"]] = {
                                    "title": refpaper["title"] if "title" in refpaper else "",
                                    "author": refpaper["author"] if "author" in refpaper else "",
                                    "citedByLink": "",
                                    "citedByCount": int(refpaper["is-referenced-by-count"]) if "is-referenced-by-count" in refpaper else -1,
                                    "referenceCount": int(refpaper["reference-count"]) if "reference-count" in refpaper else -1,
                                    "inPaperPile": False
                                }

                            if not row["doi"] in graph_edges:
                                graph_edges[row["doi"]] = []
                            graph_edges[row["doi"]].append(ref["DOI"])

結果・評価

  • 下記の図のとおりの出力となります.
  • ノードの大きさは,論文の被引用数に比例しています.
  • ノードの色が青いものはPaperpileに存在するもの, ノードの色が白いものはPaperpileに存在しないもの(Paperpileに存在する論文が参照しているものを1ホップだけ探索したもの)になります.
  • いまは私自身の問題として, メインをMendleyで試運用でPaperpileを利用しているため, 論文数が少ないのでほとんどが白い丸になってしましました.
  • しかし,自分が読んだ論文がどのような引用関係にあるかが一目でわかり,頭を整理する際に役に立ちそうな印象を抱きました.

Future work

  • 毎回コードを実行するのも手間なので,webサービス化(OSS)を考えています.
  • ブラウザでアクセスし,Exportしたjsonをアップロードするとグラフが可視化されるシステムです.
  • 論文数が増えてくると処理オーダーが悲惨なことになるので,ある程度制限をつける必要があるかもしれません.
  • Paperpileのタグ情報などを本当は使いたい・・・.のでそれも可視化の要素に加えたいです.
  • いまは引用だけなのですが,やはり被引用を辿ることでその研究のその先を知ることができるので,その情報を取得できるAPIなりサービスを模索中です.