【Python】DataFrameをマルチにまとめたい
・お題:複数のDataFrameを纏めて、マルチインデックスやマルチカラムの一つのDataFrameとして扱いたい。
・pandasのDataFrameの扱い方がよく分からなかったので、少し調べてみた。すぐ忘れるので、メモしておく。
・とりあえず、csvをDataFrameとして読み込む。
import pandas as pd
df1=pd.read_csv("xxx_1.csv")
とすると、df1の中身は以下になる。
・デフォルトで読み込むと、indexに0から始まる整数が振られる。別にこれでも問題ないが、せっかくなので、CompoundとDoseをインデックスとして読み込む。
df1=pd.read_csv("xxx_1.csv",index_col=(0,1))
とすると、df1の中身は以下になる。
・ちなみに、df1=pd.read_csv("xxx_1.csv")としてDataFrameを読み込んだ後に、df1.set_index(["Compound","Dose"])としてindexを振ることもできる(結果は割愛)。
・次に、複数のDataFrameをマルチにまとめる方法を考える。
・まず、df2として、df1と似たような構成のcsvを読み込む。
df2=pd.read_csv("xxx_2.csv",index_col=(0,1))
df2の中身は以下。
・DataFrameをくっつけるなら、pd.concat()でいけそう。
pd.concat([df1,df2])
とすると、以下が返ってきた。concatはデフォルトだと縦にくっつけることになる。
・これだとdf1とdf2を区別してくっつけられていない。df1とdf2をkeysとしてくっつけ、マルチインデックスを1層追加したい。
pd.concat([df1,df2],keys=["df1","df2"])
とすると、以下が返ってくる。
・仮にここからdf1のみをとってきたいなら、これをdf3など名付けて、df3.loc["df1"]などすればdf1のデータのみを引っ張ってこれる。
・次に、マルチカラムでくっつける場合を考える。pd.concatはデフォルトが縦にくっつける感じだったので、横にくっつけたい場合は引数にaxis=1を加える。
pd.concat([df1,df2],axis=1)
とすると、以下が返ってくる。
・インデックスの場合と同様に、keysを指定してやれば、マルチカラムになる。
pd.concat([df1,df2],axis=1,keys=["df1","df2"])
・ちなみに、ここからdf2をとってきたい場合、これをdf3など名付けて、df3.loc[:,"df2"]などすればdf2のデータのみを引っ張ってこれる。
・縦持ちの表でずらっと処理した方が、ハンドリング自体は楽かもしれないなぁと少し思った。
おわり。
【Python】マルチカラムから列をとってきたい
・お題:マウスに試験物質を連投したところ、以下の体重データが得られた。各処置条件の平均値、中央値、最大値、最小値を一つの表に作成し、そこからデータを切り出すことで、経日的なグラフで示したい。
データ
Compound | Dose | No | Day0 | Day1 | Day2 | Day3 | Day4 | Day5 | Day6 | Day7 |
A | 1 | 1 | 25.9 | 25.9 | 26.1 | 26.9 | 27.8 | 28.6 | 28.9 | 29.3 |
A | 1 | 2 | 25.2 | 25.9 | 26 | 26.9 | 26.9 | 27 | 27.1 | 27.7 |
A | 1 | 3 | 25.4 | 25.4 | 26.3 | 26.8 | 26.8 | 27.8 | 28.4 | 29.2 |
A | 3 | 1 | 25.7 | 25.5 | 25.5 | 25.1 | 25 | 24.9 | 24.7 | 24.6 |
A | 3 | 2 | 25.8 | 25.5 | 25.2 | 24.7 | 24.3 | 24.3 | 24.2 | 23.8 |
A | 3 | 3 | 25.7 | 25.5 | 25.1 | 25.1 | 24.8 | 24.5 | 24.1 | 24 |
A | 10 | 1 | 25.1 | 24.4 | 24.3 | 24 | 23.7 | 23.6 | 22.8 | 22.5 |
A | 10 | 2 | 25.3 | 24.7 | 24.3 | 23.6 | 23.6 | 23 | 23 | 22.6 |
A | 10 | 3 | 25.4 | 24.8 | 24.4 | 24.1 | 23.6 | 23 | 22.4 | 21.8 |
B | 1 | 1 | 25.1 | 25.7 | 26.2 | 26.8 | 27.2 | 28.1 | 28.6 | 28.8 |
B | 1 | 2 | 25.2 | 25.9 | 26.5 | 26.5 | 27.7 | 28.9 | 29.5 | 30.2 |
B | 1 | 3 | 25.2 | 25.9 | 25.9 | 27 | 27.4 | 27.7 | 28.4 | 28.5 |
B | 3 | 1 | 25.4 | 27 | 28.4 | 29.7 | 30.5 | 30.9 | 31.3 | 32.7 |
B | 3 | 2 | 25.8 | 26.8 | 26.9 | 28.5 | 29.2 | 29.5 | 30.7 | 31.8 |
B | 3 | 3 | 25.6 | 26.3 | 26.7 | 27.2 | 28.8 | 30 | 30.9 | 32.4 |
B | 10 | 1 | 25.2 | 25.4 | 27.3 | 28 | 28.6 | 29.3 | 29.7 | 31.5 |
B | 10 | 2 | 25.5 | 27.1 | 28.1 | 29.5 | 31.1 | 31.4 | 32.7 | 34.5 |
B | 10 | 3 | 25.6 | 27.5 | 27.9 | 29.2 | 29.4 | 30.2 | 31.3 | 31.7 |
・やりたいことは先日とほぼ同じで、平均値、中央値、最大値及び最小値を個別に求めるのではなく、すべて算出した一つの表を作成し、そこから切り出して図示するような感じ。マルチカラム・インデックスの練習をしたい。
・まずは、csvを読み込んでpandasのデータフレームを作成し、処置条件でまとめる(前回と全く同じ)。
import pandas as pd
df=pd.read_csv("xxx.csv")
matome=df.drop("No", axis=1).groupby(["Compound","Dose"])
・平均値、中央値、最大値及び最小値をdf2にする。
df2=matome.agg(["mean","median","max","min"])
df2の中身は以下の通り。マルチカラムかつマルチインデックスになっている。
・ここから、Day0とDay2の平均値、中央値、最大及び最小を抜き出すなら、以下で良い。
df2.loc[:,["Day0","Day2"]]
・各日の中央値をdf2からとってきたくて、df2.loc[:,"median"]と打つとエラーが返ってくる。どうやら、マルチカラムが階層構造になっており、各集計方法("median")が評価日の下層に位置しているため、うまく働かないっぽい。
・そこで、集計方法と評価日の階層を入れ替える(以下)。
df3=df2.swaplevel(0,1, axis=1)#axis = 0にすると、indexの階層が変わるっぽい。
こうすると、df3の中身は以下のようになる。
・こうした後に、
df4=df3.loc[:,"mean"]
を実行すると、df4の中身は以下になる。
ここまでくれば、転置して.plot()すればグラフを描くことができる。
df4.loc[:,"mean"].T.plot()
この"mean"のところを、"median"や"max"、"min"にすれば、平均値だけではなく、中央値、最大値、最小値を切り出してグラフを描いてくれる(割愛)。
・ちなみに、df5=df3.reset_index()すればマルチインデックスを解除できる(df5の中身は下図)。
・ちなみに、df6=df5.set_index(["Compound","Dose"])でマルチインデックスを設定できる(df6の中身は下図)。
・表のハンドリングをスムーズにできるようになりたい。
おわり。
【Python】平均値を算出してグラフにしたい
・お題:マウスに試験物質を連投したところ、以下の体重データが得られた。各処置条件の平均値を、経日的なグラフで示したい。
データ
Compound | Dose | No | Day0 | Day1 | Day2 | Day3 | Day4 | Day5 | Day6 | Day7 |
A | 1 | 1 | 25.9 | 25.9 | 26.1 | 26.9 | 27.8 | 28.6 | 28.9 | 29.3 |
A | 1 | 2 | 25.2 | 25.9 | 26 | 26.9 | 26.9 | 27 | 27.1 | 27.7 |
A | 1 | 3 | 25.4 | 25.4 | 26.3 | 26.8 | 26.8 | 27.8 | 28.4 | 29.2 |
A | 3 | 1 | 25.7 | 25.5 | 25.5 | 25.1 | 25 | 24.9 | 24.7 | 24.6 |
A | 3 | 2 | 25.8 | 25.5 | 25.2 | 24.7 | 24.3 | 24.3 | 24.2 | 23.8 |
A | 3 | 3 | 25.7 | 25.5 | 25.1 | 25.1 | 24.8 | 24.5 | 24.1 | 24 |
A | 10 | 1 | 25.1 | 24.4 | 24.3 | 24 | 23.7 | 23.6 | 22.8 | 22.5 |
A | 10 | 2 | 25.3 | 24.7 | 24.3 | 23.6 | 23.6 | 23 | 23 | 22.6 |
A | 10 | 3 | 25.4 | 24.8 | 24.4 | 24.1 | 23.6 | 23 | 22.4 | 21.8 |
B | 1 | 1 | 25.1 | 25.7 | 26.2 | 26.8 | 27.2 | 28.1 | 28.6 | 28.8 |
B | 1 | 2 | 25.2 | 25.9 | 26.5 | 26.5 | 27.7 | 28.9 | 29.5 | 30.2 |
B | 1 | 3 | 25.2 | 25.9 | 25.9 | 27 | 27.4 | 27.7 | 28.4 | 28.5 |
B | 3 | 1 | 25.4 | 27 | 28.4 | 29.7 | 30.5 | 30.9 | 31.3 | 32.7 |
B | 3 | 2 | 25.8 | 26.8 | 26.9 | 28.5 | 29.2 | 29.5 | 30.7 | 31.8 |
B | 3 | 3 | 25.6 | 26.3 | 26.7 | 27.2 | 28.8 | 30 | 30.9 | 32.4 |
B | 10 | 1 | 25.2 | 25.4 | 27.3 | 28 | 28.6 | 29.3 | 29.7 | 31.5 |
B | 10 | 2 | 25.5 | 27.1 | 28.1 | 29.5 | 31.1 | 31.4 | 32.7 | 34.5 |
B | 10 | 3 | 25.6 | 27.5 | 27.9 | 29.2 | 29.4 | 30.2 | 31.3 | 31.7 |
・Excelで作成したダミーデータなので、CSVで保存してpandasのdataframeで読み込んだ。
import pandas as pd
df=pd.read_csv("xxx.csv")
・処置条件を纏める。今回振っている処置条件は、試験物質"Compound"と用量"Dose"なので、"Compound"と"Dose"でgroupbyする。個体番号"No"の情報は目的の解析(平均値の算出)に使わないので、列を除く。
matome=df.drop("No", axis=1).groupby(["Compound","Dose"])
・平均値をdf2にする。
df2=matome.agg("mean")
.agg("なにか")で、いろいろな集計ができる("median", "sum", "min", "max"など)。
平均値を算出したdf2の中身は以下の通り。なんだか平均値っぽい(n = 3にしたので割り切れにくい)。
・pandasのplotでグラフにする。
df2.T.plot(figsize=(12,8))
y軸が22始まりになっているので、好みによってはy軸をゼロスタートにしても良いかもしれない。
df2.T.plot(figsize=(12,8),ylim=(0,35))
ちなみに、列ごとに系列として認識されるので、転置を挟んでいる。転置を挟まないと、横軸が条件になる(下図)。
おわり。