唆のメモ

ラボに配属されて遺伝子発現解析などでデータ解析とかが必要になりそうな大学生の技術学習メモ。あくまでもメモです。もし、このブログを参考にする場合は自己責任でお願いします。

Pandas DataFrameのサブクラス

DataFrameに格納されたデータに対してルーティンで施す処理が多いので、DataFrameのサブクラスを作成して、そこにメソッドをつけようとしたら苦戦したのでメモ

サブクラス作成

まずは必要なライブラリをimport

import pandas as pd
import numpy as np
import copy

クラスを作成。単純なmethodをつける。

class MyDataFrame(pd.DataFrame):
    def __init__(self,data,school):
        super( MyDataFrame,self).__init__(data)
        self.school=school
        
    def showschool(self):
        print(self.school)

インスタンスを作成し、操作してみる。

data=[['Kumiko', 1, 'euphonium'], ['Reina', 1, 'trumpet'], ['Asuka', 3, 'euphonium'], ['Yuko', 2, 'trumpet']]
mdf=MyDataFrame(data,'Kitauji')
mdf.index=['Omae', 'Kosaka', 'Tanaka', 'Yoshikawa']
mdf.columns=['name', 'grade', 'instrument']
print(mdf)
print(type(mdf))
mdf.showschool()

出力

            name  grade instrument
Omae       Kumiko      1  euphonium
Kosaka      Reina      1    trumpet
Tanaka      Asuka      3  euphonium
Yoshikawa    Yuko      2    trumpet
<class '__main__.MyDataFrame'>
Kitauji

上手くいっていそうな気がする。

ところが

DataFrame.copy()を流用すると、

mdf2=mdf.copy()
print(type(mdf2))

出力

<class 'pandas.core.frame.DataFrame'>

なんと(当たり前と言えば当たり前だが)、元のDataFrameクラスのインスタンスに戻っている。DataFrame.copy()はDataFrameクラスのインスタンスを返すようにできているからだろう。

必要に応じて自作クラスを返すように定義するしかないらしい。

例えば、

class MyDataFrame(pd.DataFrame):
    def __init__(self,data,school):
        super( MyDataFrame,self).__init__(data)
        self.school=school
        
    def showschool(self):
        print(self.school)
        
    def copy(self):
        cp=MyDataFrame(data=self, school=self.school)
        attr=copy.deepcopy(self.__dict__)
        cp.__dict__.update(attr)
        return cp
    
    def __copy__(self):
        return self.copy()
    
    def __deepcopy__(self,memo):
        return self.copy()

これで、

mdf2=mdf.copy()
print(type(mdf2))
mdf2.showschool()

出力

<class '__main__.MyDataFrame'>
Kitauji

上手くいったようだ。

locやilocも同様にしたいのだけど、もともとどういう実装になっているのかわからなくて調査中。いいやり方があったら教えてほしい。

Pandas DataFrame の基本その1

はじめに

最近、pandasを使ってデータを扱うことが増えてきたので、一度基本からまとめてみようと思って記事を作成した。

DataFrameの作成

まずはpandasとnumpyをimport

import pandas as pd
import numpy as np 

各行が一つのリスト。それをさらにリストにして、dataというパラメーターとして渡す。

df=pd.DataFrame(data=[['Kumiko', 1, 'euphonium'], ['Reina', 1, 'trumpet'], ['Asuka', 3, 'euphonium'], ['Yuko', 2, 'trumpet']])
print(df)

出力

       0  1          2
0  Kumiko  1  euphonium
1   Reina  1    trumpet
2   Asuka  3  euphonium
3    Yuko  2    trumpet

index、column名の変更

それぞれ、 df.index, df.columns にリストを代入する。

df.columns=['name', 'grade', 'instrument']
df.index=['Omae', 'Kosaka', 'Tanaka', 'Yoshikawa']
print(df)

出力

            name  grade instrument
Omae       Kumiko      1  euphonium
Kosaka      Reina      1    trumpet
Tanaka      Asuka      3  euphonium
Yoshikawa    Yuko      2    trumpet

以下のように、DataFrame作成時にindex、columnsというパラメーターで指定することもできる。

df=pd.DataFrame(data=[['Kumiko', 1, 'euphonium'], ['Reina', 1, 'trumpet'], ['Asuka', 3, 'euphonium'], ['Yuko', 2, 'trumpet']], index=['Omae', 'Kosaka', 'Tanaka', 'Yoshikawa'], columns=['name', 'grade', 'instrument'])

ついでに、以下のようにすると、df.index, df.columnsでそれぞれindex,column名にアクセスできる。

print(df.index)
print(df.columns)

出力

Index(['Omae', 'Kosaka', 'Tanaka', 'Yoshikawa'], dtype='object')
Index(['name', 'grade', 'instrument'], dtype='object')

これらはシーケンス型として扱える。

print(df.index[0])

出力

Omae

データの追加

列を追加するときはColumn名を指定してデータを渡す。

df['hight']=[162,158,171,156]
print(df)

出力

             name  grade instrument  hight
Omae       Kumiko      1  euphonium    162
Kosaka      Reina      1    trumpet    158
Tanaka      Asuka      3  euphonium    171
Yoshikawa    Yuko      2    trumpet    156

行を追加するときはappend methodを使う。

df2=pd.DataFrame(data=[['Mizore', 2, 'Oboe', 154]],index=['Yoroizuka'],columns=df.columns)
df=df.append(df2)
print(df)

出力

             name  grade instrument  hight
Omae       Kumiko      1  euphonium    162
Kosaka      Reina      1    trumpet    158
Tanaka      Asuka      3  euphonium    171
Yoshikawa    Yuko      2    trumpet    156
Yoroizuka  Mizore      2       Oboe    154

特定の行や列を取得

column名を用いて列を取得することができる。

print(df['hight'])

出力

Omae         162
Kosaka       158
Tanaka       171
Yoshikawa    156
Yoroizuka    154
Name: hight, dtype: int64

以下でもOK

print(df.hight)

行はdf[start:end]とするとstart番目(0番目から数え始める)からend-1番目の行を取得できる。

print(df[1:4])

出力

            name  grade instrument  hight
Kosaka     Reina      1    trumpet    158
Tanaka     Asuka      3  euphonium    171
Yoshikawa   Yuko      2    trumpet    156​

locを使った抽出。カラム名、index名を使って抽出できる。

print(df.loc['Kosaka':'Yoshikawa', 'grade':'hight'])

出力

           grade instrument  hight
Kosaka         1    trumpet    158
Tanaka         3  euphonium    171
Yoshikawa      2    trumpet    156

区間だけでなくリストで指定もできる。

index=['Kosaka','Yoshikawa']
cols=['name','instrument']
print(df.loc[index,cols])

出力

            name instrument
Kosaka     Reina    trumpet
Yoshikawa   Yuko    trumpet

ilocを用いると、行番号、列番号で指定できる。

print(df.iloc[1:4,2:4])

出力

          instrument  hight
Kosaka       trumpet    158
Tanaka     euphonium    171
Yoshikawa    trumpet    156

これもリストで指定することができる。

index=[3,2]
cols=[0,3]
print(df.iloc[index,cols])

出力

            name  hight
Yoshikawa   Yuko    156
Tanaka     Asuka    171

今日はここまで

投稿テストを兼ねた最初の投稿

 ラボに配属されたらRNAseqなどのためデータ分析をする必要が出てきた。必然的に簡単なプログラミングも要求されるので、そのあたりの勉強メモとして書いていく。

 言語はpython3を使うつもりだが、遺伝子発現解析の分野では、いろいろR言語によるパッケージがすでに開発されているので、適宜使い分けるか、どちらか一本に絞るかは勉強しながら考えたい。

 したがって、内容としてはpython、R、遺伝子発現解析、その他生物学の話題が主になりそう。

以下、投稿テスト

hoge='hoge'