Excelシートの任意の位置(範囲)からデータを抜き取りmatplotlibでグラフ化したい
データフレームからデータフレームをつくりたい
pandasで読み込んだExcelデータ(下図)の(X1,Y1)〜(X4,Y4)の部分だけを、
別にデータフレーム化したいことないですか?
僕はよくあるんです。(後先考えずにExcelデータ作ってしまうので…)
(下図)X,Yの部分は先の(1)で述べたような方法でサクっと読み込めます。
データフレームになっていると後々、楽できるので大変便利なのですが
このようなExcelデータシートだと、データフレームを作ることがそもそも面倒という・・・
今回は、このデータフレームから子データフレームを作り出すためのメモです。
ぜったいこれより簡単な1行くらいで解決できそうなコードありそうなんですが、
いじっているうちにいろいろとデータフレーム構造を理解できたりしたのでメモに残したいと思います。
親データフレームの読み込み
Excelファイルは、pandasで一発で読み込めて楽勝なんですが、自分のクソExcelデータはどれもindexやcolumnがきちんとしていないケースがほとんどです。
ということで、読み込んだデータ(親)の範囲を指定して新たにデータフレーム(子)を作りたいと思います。
冒頭部はいつもと同じimport設定とファイルパス指定。
# coding: utf-8
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
# フォントファイルの場所を指定 ubuntu (C:\Windows\Fonts\任意のFont)
fp = FontProperties(fname="/usr/share/fonts/truetype/fonts-japanese-gothic.ttf")
####################################################################
filepath='~/Desktop/sample2.xls' #Xlsファイルの場所
親データフレームの読み込み
# 親データフレーム
df=pd.read_excel(filepath) #Pandas DataFrameに読込み
子データフレームを作る
ilocによる範囲指定読み込み
さっそく、親dfの範囲を指定してデータを抜き出します。
ここでは、ilocを使って指定します。
# グラフ化したいセル範囲を指定する
df1=df.iloc[8:20,4:6] #[行開始:終,列開始:終]で指定する
df1=df1.reset_index(drop=True) #インデックスをあたらしく振り直す
下図のX1,Y1ラベルを含む全体(10行目から21行目、E-F列)を指定しています。
ヘッダと、ゼロから始まるというルールのせいか
シートのセルから指定位置を直接読み取るのはちょっと感覚的にずれます。
なのであたりをつけてprint(df1)とかしながら範囲指定するとよいです。
ilocによる範囲指定読み込み結果
ここで、指定範囲から読み込んだdf1をみてみると、
こんな具合(下図)に、親dfの列データ(Unnamed:)を元に読み込まれていて、X1,Y1もデータとなっています。
このX1とY1は、次にあたらしく作る「子データフレーム」のラベルとして使用します。
ilocによる範囲指定読み込み結果から列データを抜き取る
そこで、df1の列データ(X1,Y1)を抜き取ってみましょう。
# 1行目の列をリスト化 →子データフレームの列で使う
COL_LIST1=df1[0:1].values.flatten()
するとCOL_LIST1は['X1' 'Y1']
が返ってきます。
欲しかった列データがとれました。
列データを使って空っぽの子データフレームを作る
取り出した列データを元に子データフレーム(co_df1)をつくります。
この時点では列データだけで中身はありません。
# 子データフレーム(empty)を作成、列は先に作成したCOL_LISTとする
co_df1=pd.DataFrame({},columns=COL_LIST1,index=[])
子データフレームにデータをいれる
for文を使って、列データ(COL_LIST1)ごとに指定範囲データフレーム(df1)の各列にぶらさがっている
データを、子データフレームに移します。
# 子データフレームの各列にデータを書き込む(〜[1:]とすることで列ラベル以降のデータを取得)
# Graph1
for i,col in enumerate(COL_LIST1):
#各列のデータを読み込む
co_df1[col]=df1[[i]][1:].reset_index(drop=True)
df1[[i]] で、ilocで指定して読み込んだdf1の1列目、2列目…のデータが読み込まれます。
しかし、ここにはラベルデータであるX1,Y1も含まれています。そこで
df1[[i]][1:]
とすることでラベルデータを除いた数値データだけを取り出すことができます。
しかし、このままだと元のindex情報が残っていて後々、厄介です。
df1[[i]][1:].reset_index(drop=True)
をつけてindexをリセットしておきます。
これを、空っぽの子データフレームであるco_df1に順次(COL_LIST1にあるだけ)入れていくと、目的の子データフレームが完成します。
グラフデータとして取り出す
あとは、plot用のx,y軸データに
投げ込むだけです。
x1=co_df1[[0]]
y1=co_df1[[1]]
冗長に4つのグラフを作ってみる
最初に示したExcelデータのX1,Y1〜X4,Y4までをすべて子データフレーム化しグラフにしてみました。
コード
子データ4個でグラフ化したものと、1個だけのものを貼ります。
グラフ4つ版
# coding: utf-8
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
# フォントファイルの場所を指定 ubuntu (C:\Windows\Fonts\任意のFont)
fp = FontProperties(fname="/usr/share/fonts/truetype/fonts-japanese-gothic.ttf")
####################################################################
filepath='~/Desktop/sample2.xls' #Xlsファイルの場所
# 親データフレーム
df=pd.read_excel(filepath) #Pandas DataFrameに読込み
# 親データフレームから子データフレームを作成
# グラフ化したいセル範囲を指定する
df1=df.iloc[8:20,4:6] #[行開始:終,列開始:終]で指定する
df1=df1.reset_index(drop=True) #インデックスをあたらしく振り直す
df2=df.iloc[8:20,7:9]
df2=df2.reset_index(drop=True)
df3=df.iloc[21:33,4:6]
df3=df3.reset_index(drop=True)
df4=df.iloc[21:33,7:9]
df4=df4.reset_index(drop=True)
# 列(名)を読み込む
COL_LIST1=df1[0:1].values.flatten() #1行目の列をリスト化 →子データフレームの列で使う
COL_LIST2=df2[0:1].values.flatten()
COL_LIST3=df3[0:1].values.flatten()
COL_LIST4=df4[0:1].values.flatten()
# 子データフレーム(empty)を作成、列は先に作成したCOL_LISTとする
co_df1=pd.DataFrame({},columns=COL_LIST1,index=[])
co_df2=pd.DataFrame({},columns=COL_LIST2,index=[])
co_df3=pd.DataFrame({},columns=COL_LIST3,index=[])
co_df4=pd.DataFrame({},columns=COL_LIST4,index=[])
# 子データフレームの各列にデータを書き込む
# Graph1
for i,col in enumerate(COL_LIST1):
#各列のデータを読み込む
co_df1[col]=df1[[i]][1:].reset_index(drop=True)
# Graph2
for i,col in enumerate(COL_LIST2):
#各列のデータを読み込む
co_df2[col]=df2[[i]][1:].reset_index(drop=True)
# Graph3
for i,col in enumerate(COL_LIST3):
#各列のデータを読み込む
co_df3[col]=df3[[i]][1:].reset_index(drop=True)
# Graph4
for i,col in enumerate(COL_LIST4):
#各列のデータを読み込む
co_df4[col]=df4[[i]][1:].reset_index(drop=True)
# グラフのX,Yデータの抽出
# 親データフレーム
x=df[[0]]
y=df[[1]]
# 子データフレーム
x1=co_df1[[0]]
y1=co_df1[[1]]
x2=co_df2[[0]]
y2=co_df2[[1]]
x3=co_df3[[0]]
y3=co_df3[[1]]
x4=co_df4[[0]]
y4=co_df4[[1]]
####################################################################
# Graph
####################################################################
fig = plt.figure()
# 複数グラフ設定
ax1 = fig.add_subplot(221) #Graph1
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
# y軸のスケール設定
ax1.set_yscale('linear')
ax2.set_yscale('linear')
ax3.set_yscale('log')
ax4.set_yscale('log')
# 軸の範囲
ax1.set_ylim(-1.1, 1.1)
ax1.set_xlim(0,300)
ax2.set_ylim(0,10)
ax2.set_xlim(0,10)
ax3.set_ylim(1E+0,1E+5)
ax3.set_xlim(0,10)
ax4.set_ylim(1E-13,1E+1)
ax4.set_xlim(0,10)
# 個別タイトル
ax1.set_title("Graph1",fontdict = {"fontproperties": fp},fontsize=12)
ax2.set_title("Graph2",fontdict = {"fontproperties": fp},fontsize=12)
ax3.set_title("Graph3",fontdict = {"fontproperties": fp},fontsize=12)
ax4.set_title("Graph4",fontdict = {"fontproperties": fp},fontsize=12)
# 軸
ax1.set_xlabel("x",fontdict = {"fontproperties": fp},fontsize=12)
ax1.set_ylabel("y",fontdict = {"fontproperties": fp},fontsize=12)
# プロット
ax1.plot(x1, y1,'blue',label='graph1')
ax2.plot(x2, y2,'green',label='graph2')
ax3.plot(x3, y3,'red',label='graph3')
ax4.plot(x4, y4,'black',label='graph4')
# Legend 位置
ax1.legend(loc="upper right")
ax2.legend(loc="upper left")
ax3.legend(loc="upper left")
ax4.legend(loc="upper left")
# レイアウト調整
plt.tight_layout()
# グラフ全体のタイトル
fig.suptitle('Graph', fontsize=14)
plt.subplots_adjust(top=0.85)
# ファイルを保存 pngとepsの両方で保存
plt.savefig("sample.png")
plt.savefig("sample.eps")
plt.show()
グラフ1つ版
# coding: utf-8
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
# フォントファイルの場所を指定 ubuntu (C:\Windows\Fonts\任意のFont)
fp = FontProperties(fname="/usr/share/fonts/truetype/fonts-japanese-gothic.ttf")
####################################################################
filepath='~/Desktop/sample2.xls' #Xlsファイルの場所
# 親データフレーム
df=pd.read_excel(filepath) #Pandas DataFrameに読込み
# 親データフレームから子データフレームを作成
# グラフ化したいセル範囲を指定する
df1=df.iloc[8:20,4:6] #[行開始:終,列開始:終]で指定する
df1=df1.reset_index(drop=True) #インデックスをあたらしく振り直す
# 列(名)を読み込む
COL_LIST1=df1[0:1].values.flatten() #1行目の列をリスト化 →子データフレームの列で使う
# 子データフレーム(empty)を作成、列は先に作成したCOL_LISTとする
co_df1=pd.DataFrame({},columns=COL_LIST1,index=[])
# 子データフレームの各列にデータを書き込む(〜[1:]とすることで列ラベル以降のデータを取得)
# Graph1
for i,col in enumerate(COL_LIST1):
#各列のデータを読み込む
co_df1[col]=df1[[i]][1:].reset_index(drop=True)
# グラフのX,Yデータの抽出
# 親データフレーム
x=df[[0]]
y=df[[1]]
# 子データフレーム
x1=co_df1[[0]]
y1=co_df1[[1]]
####################################################################
# Graph
####################################################################
fig = plt.figure()
# 複数グラフ設定
ax1 = fig.add_subplot(111) #Graph1
# y軸のスケール設定
ax1.set_yscale('linear')
# 軸の範囲
ax1.set_ylim(-1.1, 1.1)
ax1.set_xlim(0,300)
# 個別タイトル
ax1.set_title("Graph1",fontdict = {"fontproperties": fp},fontsize=12)
# 軸
ax1.set_xlabel("x",fontdict = {"fontproperties": fp},fontsize=12)
ax1.set_ylabel("y",fontdict = {"fontproperties": fp},fontsize=12)
# プロット
ax1.plot(x1, y1,'blue',label='graph1')
# Legend 位置
ax1.legend(loc="upper right")
# レイアウト調整
plt.tight_layout()
# グラフ全体のタイトル
fig.suptitle('Graph', fontsize=14)
plt.subplots_adjust(top=0.85)
# ファイルを保存 pngとepsの両方で保存
plt.savefig("sample.png")
plt.savefig("sample.eps")
plt.show()