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
今日はここまで