大菌輪_CCCデータセット:同定ツール


(daikinrin_CCC_dataset_version1.2を使用)
2017/2/21更新

以下の解析を再現するには、jupyterと必要に応じて各種ライブラリ (pandas、NumPyなど) のインストールが必要です。
準備の仕方や基本操作に関してはweb上に多数の資料があるので、そちらを参照ください。

※注1:筆者はプログラミング初心者かつ独学なので、もっとよいやり方があるかもしれません。あくまで参考ということでお願いいたします。
※注2:以下でご紹介する方法はたぶん全てExcelでも代替できます。コードの読み方が分からない方も、「CCCデータセットを加工するとこんなことができる」という例としてご参考にしていただけます。

下の写真のきのこを同定してみます


傘が緑色で表面に細かい鱗片があり、ひだが褐色で、柄表面にも細かい鱗片があることなどが特徴です。

Copyright © 2013 Caleb Brown
(CC-BY-SA)

In [1]:
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import sys
%matplotlib inline
df = pd.read_csv("C:\\Users\\Atsushi Nakajima\\Dropbox\\大菌輪_CCC\\daikinrin_CCC_dataset_version1.2\\basidiomycota_daikinrin_ccc_ver._1.2_for_informal_or_mining_use_only.csv")
dfccc = pd.read_csv("C:\\Users\\Atsushi Nakajima\\Dropbox\\大菌輪_CCC\\daikinrin_CCC_dataset_version1.2\\ccclist_daikinrin_ccc_ver._1.2_for_informal_or_mining_use_only.csv")
cccdict = dict(zip(dfccc["CCC_JP"],"<"+dfccc["CCC"]+">"))
cccdictr = {v:k for k, v in cccdict.items()}
ccclist = list(dfccc["CCC"])
cccjplist = [cccdictr[a] for a in df.columns[5:] if cccdictr.get(a) != None]
cccjplist.insert(0, "-------------------")
from ipywidgets import *
CCCselects = [Dropdown(description="CCC"+str(i+1), options=cccjplist) for i in range(6)]
VBox([HBox([CCCselects[0], CCCselects[1], CCCselects[2]]), HBox([CCCselects[3], CCCselects[4], CCCselects[5]])])
#↓実行するとボタンが表示されます
C:\Users\Atsushi Nakajima\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2717: DtypeWarning: Columns (257,263) have mixed types. Specify dtype option on import or set low_memory=False.
  interactivity=interactivity, compiler=compiler, result=result)
In [3]:
#ドロップダウンメニューから値を取得し、CCCを辞書で英語に変換
#今回は「傘_色_緑」「子実層托_型_襞」「傘_表面_鱗片」「子実層托_色_褐」「柄_表面_鱗片」の5つを選択しました
cccs = [cccdict[CCCselects[i].value] for i in range(len(CCCselects)) if CCCselects[i].value != "-------------------"]
print(cccs)
if len(cccs) == 0:
    print("何も選択されていないので終了します。")
    sys.exit()
#属名の列を追加して重複除去属名リストからなるデータフレームを作成
df["genus"] = [a[0] for a in df["学名"].str.split(" ")]
resultdf = pd.DataFrame()
for ccc in cccs:
    buf =[]
    for a in sorted(set(list(df["genus"]))):
        genusdf = df[df["genus"]==a]
        genuscnt = genusdf.shape[0]
        genusdfn = df[df["genus"]!=a]
        ariari = genusdf[~genusdf[ccc].str.contains("【0】")].shape[0]
        #ariariが1以上(ヒットあり)のみ絞り込み
        if ariari != 0:
            arinasi = genusdf.shape[0]-ariari
            nasiari = genusdfn[~genusdfn[ccc].str.contains("【0】")].shape[0]
            nasinasi = genusdfn.shape[0]-nasiari
            se = round(ariari/(ariari+arinasi),2)
            sp = round(nasinasi/(nasiari+nasinasi),2)
            if sp == 1:
                sp = 0.99
            logpLR = round(np.log(se/(1-sp)),2)
            buf.append([a,logpLR,genuscnt])
            #陽性尤度比の対数をとったもの(logpLR)を足し合わせます
            #print(ccc,a,ariari,arinasi,nasiari,nasinasi,se,sp,logpLR)
    df2 = pd.DataFrame(buf)
    df2.columns = ["genus","logpLR","genuscnt"]
    #print(len(df2["genus"]),df2["genus"])
    #df2にある属のみを残す
    df = df[df["genus"].isin(df2["genus"])]
    print(str(df.shape[0])+"件の記載文を絞り込み")
    if resultdf.shape[0] == 0:
        resultdf = df2
    else:
        #古いdf2を基にして左外部結合
        resultdf = pd.merge(df2,resultdf,left_on="genus",right_on="genus",how="left")
        #pLRを足し合わせて元の2列をdropする
        resultdf["logpLR"] = resultdf["logpLR_x"]+resultdf["logpLR_y"]
        resultdf = resultdf.drop(["logpLR_x","logpLR_y"],axis=1)
    print(ccc+" "+str(resultdf.shape[0])+"属hit!!")
['<pileus_color=greenish>', '<hymenophore=lamellate>', '<pileus_surface=scaly>', '<hymenophore_color=brownish>', '<stipe_surface=scaly>']
1994件の記載文を絞り込み
<pileus_color=greenish> 87属hit!!
1735件の記載文を絞り込み
<hymenophore=lamellate> 60属hit!!
1500件の記載文を絞り込み
<pileus_surface=scaly> 32属hit!!
1496件の記載文を絞り込み
<hymenophore_color=brownish> 31属hit!!
1219件の記載文を絞り込み
<stipe_surface=scaly> 25属hit!!
In [4]:
#重複したgenuscntの列を削除
resultdf = resultdf.T.drop_duplicates().T
sns.set(font_scale=1.2)
resultdf.index = resultdf["genus"]
resultdf = resultdf.sort_values("logpLR",ascending=False)
resultdf[:30]["logpLR"].plot.barh().invert_yaxis()
plt.xlabel("logpLR")
plt.show()
In [5]:
#上の図で一番値が大きかったStropharia(モエギタケ属)を調べてみます
genusselect = Dropdown(description="属内の種をさらに絞り込み", options=list(resultdf[:30]["genus"]))
genusselect
#↓実行するとボタンが表示されます
In [6]:
import re
from heapq import merge
columnlist = ["和名","学名"]
df2 = df[df["genus"]==genusselect.value][list(merge(cccs,columnlist))]
df2 = df2.where(df2!="【0】[]", np.nan)
df2 = df2.replace(re.compile("\[.*|【|】"),"")
df2.columns = [cccdictr[a] if cccdictr.get(a) is not None else a for a in df2.columns]
#1つもヒットしなかった分類群を落とす(和名なしも除く)
df2 = df2[~df2["和名"].str.contains("(和名なし)")].dropna(subset=[cccdictr[a] for a in cccs],how="all")
df2 = df2.style.highlight_null("grey")
df2
Out[6]:
傘_色_緑 子実層托_型_襞 傘_表面_鱗片 子実層托_色_褐 柄_表面_鱗片 和名 学名
3001 2 2 2 2 2 モエギタケ Stropharia aeruginosa
3006 nan 2 nan 2 1 コシワツバタケ Stropharia coronilla
3010 nan 2 nan 2 1 ツヅレタケ Stropharia hornemannii
3013 nan 3 1 1 nan サケツバタケ Stropharia rugosoannulata
3014 1 2 nan 2 nan キバフンタケ Stropharia semiglobata

モエギタケ属の中で選んだ形質を全て持っているのは「モエギタケ (Stropharia aeruginosa)」であることが分かりました(これが正解です)
http://mushroomobserver.org/image/show_image/379798?q=1Lb2