pandasのカラム番号を検索する小ネタ

こちらです

def c_index(c_name='', data_frame=df):
    c_zip = zip(list(range(len(data_frame.columns))),data_frame.columns)
    # c_name = input('column name?')
    return {key:value for key,value in c_zip if c_name in value}

defaultではdfをDataFrameとして全てのカラムの番号を表示します。
第一引数に指定した文字列を含むカラムとそのカラム番号を表示できます。
第二引数に指定したDataFrameのカラムを取り扱います。

カラムが多すぎるDataFrameで困った

前回までの記事でChEMBLからデータを引っ張ってきました。

keetaneblog.hatenablog.com

DataFrameのカラムが多すぎてチンプンカンプンになるので最後はSummary Tableを作りましたが、実際はカラムの数が多いので把握するのも大変です。

df.columns

# Index(['Molecule ChEMBL ID', 'Molecule Name', 'Molecule Max Phase',
#       'Molecular Weight', '#RO5 Violations', 'AlogP', 'Compound Key',
#       'Smiles', 'Standard Type', 'Standard Relation', 'Standard Value',
#       'Standard Units', 'pChEMBL Value', 'Data Validity Comment', 'Comment',
#       'Uo Units', 'Ligand Efficiency BEI', 'Ligand Efficiency LE',
#       'Ligand Efficiency LLE', 'Ligand Efficiency SEI', 'Potential Duplicate',
#       'Assay ChEMBL ID', 'Assay Description', 'Assay Type', 'BAO Format ID',
#       'BAO Label', 'Assay Organism', 'Assay Tissue ChEMBL ID',
#       'Assay Tissue Name', 'Assay Cell Type', 'Assay Subcellular Fraction',
#       'Assay Parameters', 'Assay Variant Accession', 'Assay Variant Mutation',
#       'Target ChEMBL ID', 'Target Name', 'Target Organism', 'Target Type',
#       'Document ChEMBL ID', 'Source ID', 'Source Description',
#       'Document Journal', 'Document Year', 'Cell ChEMBL ID', 'Properties',
#       'MW', 'Ligand Efficiendy SEI', 'Ligand Efficiendy BEI',
#       'Ligand Efficiendy LE', 'Molecule_Image', 'Murcko_SMILES',
#       'Murcko_generic_SMILES', 'Murcko_Mol', 'Murcko_generic_Mol', 'TPSA',
#       'Ct HA', 'Ct F', 'HBD', 'HBD_Ro5', 'HBA', 'HBA_Ro5', 'Ct RB', 'Ct Ar',
#       'Fsp3', 'QED'],
#       dtype='object')

カラムの数だけでも65もありました...
大文字と小文字が混ざってたり_が入ってたり#が入ってたりでタイポも増えるしと地味に悩んでいました。

DataFrameからdataを取り出す方法

pandasでは特定のカラムを抽出する方法がいくつか用意されています。
代表的なものは

df['Molecule ChEMBL ID']

#0       CHEMBL2181327
#1       CHEMBL2181315
#2         CHEMBL21156
#3           CHEMBL535
#4        CHEMBL475251
#            ...      
#1806    CHEMBL3968872
#1807    CHEMBL3983594
#1808    CHEMBL3957838
#1809    CHEMBL4563864
#1810    CHEMBL4873733

みたいな方法です。 例えば複数のカラムを抽出したいときは[]の中にさらにカラム名のリストを入れます。

df[['Molecule ChEMBLE ID', 'Molecule Name', 'Smiles']]

#  Molecule ChEMBL ID  Molecule Name   Smiles
#0 CHEMBL2181327   NaN CN(C)CCN(C)c1ccc2cc1COCC=CCOCc1cccc(c1)-c1ccnc...
#1 CHEMBL2181315   NaN C1=CCCOc2cccc(c2)-c2ccnc(n2)Nc2cccc(c2)OCC1
#2 CHEMBL21156 NaN CC(C)(C)c1nc2c3ccc(F)cc3c3c(=O)[nH]ccc3c2[nH]1
#3 CHEMBL535   SUNITINIB   CCN(CC)CCNC(=O)c1c(C)[nH]c(/C=C2\C(=O)Nc3ccc(F...
#4 CHEMBL475251    R-406   COc1cc(Nc2ncc(F)c(Nc3ccc4c(n3)NC(=O)C(C)(C)O4)...
#...   ... ... ...
#1806  CHEMBL3968872   NaN CN(CC(F)(F)F)C[C@H]1CC[C@H](N2CN(CC#N)C(=O)c3c...
#1807  CHEMBL3983594   NaN N#CCN1CN([C@H]2CC[C@H](CNC3(C(F)(F)F)CC3)CC2)c...
#1808  CHEMBL3957838   NaN O=C1c2cnc3[nH]ccc3c2N([C@H]2CC[C@H](CN3CCCS3(=...
#1809  CHEMBL4563864   NaN COCCn1cc(Nc2cc(NCc3cccc(NC(=O)CC#N)c3)ncn2)cn1
#1810  CHEMBL4873733   NaN Cc1cnc(Nc2ccc3c(c2)CCN3C(=O)[C@H]2CCCN2C(=O)C2...

わたしはいつもカラム名をタイポするので地味にストレスです。

.locメソッドと.ilocメソッド

.loc[].iloc[]は(多分)locationとindex locationに由来するメソッドです。
引数はそれぞれ

df.loc[row index, column name]

df.iloc[row index number, column index number]

となってます。
DataFrameのindexがrow numberの場合は、どちらも数字で同じ結果が返ってきます。
indexたdatatimeのようにrow number以外を採用しているときはやっかいなので、.iloc[]を使うことが多いのかなと思います。

例えば

df.loc[0, 'Molecule Name']
# nan

のように値を取り出したり代入するときに使います。
第二引数を省略することで行全体も抽出できます。

df.loc[0]

# Molecule ChEMBL ID    CHEMBL2181327
# Molecule Name                   NaN
# Molecule Max Phase                0
# Molecular Weight             459.59
# #RO5 Violations                   0
#                           ...      
# HBA_Ro5                           7
# Ct RB                             4
# Ct Ar                             3
# Fsp3                       0.333333
# QED                        0.577017
# Name: 0, Length: 65, dtype: object

同じ要領で.iloc[]メソッドだと行と列のindex numberを入力するだけで同じことができます。
非常に簡単な反面、正しくindex numberを把握しておく必要があります。

df.iloc[0,1]
# nan
df.iloc[0]

# Molecule ChEMBL ID    CHEMBL2181327
# Molecule Name                   NaN
# Molecule Max Phase                0
# Molecular Weight             459.59
# #RO5 Violations                   0
#                           ...      
# HBA_Ro5                           7
# Ct RB                             4
# Ct Ar                             3
# Fsp3                       0.333333
# QED                        0.577017
# Name: 0, Length: 65, dtype: object

# このDataFrameはrow index numberを採用しているので.locと同じ結果が返ってくるはず

じゃあカラムのindex numberを簡単に把握できれば少し楽になるかも??

Column index identifier

というわけでメソッドを作ってみました。

def c_index(c_name='', data_frame=df):
    c_zip = zip(list(range(len(data_frame.columns))),data_frame.columns)
    # c_name = input('column name?')
    return {key:value for key,value in c_zip if c_name in value}

引数なしで使うとカラムにindex numberを割り当てた結果を全て出力します。

c_index()

# Output exceeds the size limit. Open the full output data in a text editor
# {0: 'Molecule ChEMBL ID',
# 1: 'Molecule Name',
# 2: 'Molecule Max Phase',
# 3: 'Molecular Weight',
#...
# 63: 'Fsp3',
# 64: 'QED'}

第一引数に検索したい文字列を入力すると、文字列を含むカラム名index numberの割り当てを出力します。

c_index('As')

# {21: 'Assay ChEMBL ID',
# 22: 'Assay Description',
# 23: 'Assay Type',
# 26: 'Assay Organism',
# 27: 'Assay Tissue ChEMBL ID',
# 28: 'Assay Tissue Name',
# 29: 'Assay Cell Type',
# 30: 'Assay Subcellular Fraction',
# 31: 'Assay Parameters',
# 32: 'Assay Variant Accession',
# 33: 'Assay Variant Mutation'}

第二引数にDataFrameを入れることも出来ます。面倒なのでデフォルトはdfにしてあります。   これを使うと特定の情報をシンプルに抽出できます。

df.iloc[[0,3,50, 23,11], [0,1,22]]

#      Molecule ChEMBL ID  Molecule Name   Assay Description
# 0    CHEMBL2181327       NaN             Inhibition of recombinant TYK2
# 3    CHEMBL535           SUNITINIB       Binding constant for TYK2(JH2domain-pseudokina...
# 50   CHEMBL3949572       NaN             Enzyme Assay: The inhibitory activity of the c...
# 23   CHEMBL1088856       NaN             Inhibition of recombinant GST tagged TYK2 prot...
# 11   CHEMBL3655081       ABROCITINIB     Inhibition of N-terminal GST-tagged human TYK2...

コードの可読性は下がるので必ずしもオススメはしませんが、どんなカラムがあったかも検索できるので便利かもです。