本記事では、下図のようにエクセルファイル中の先頭行ではなくて、中途半端な位置に表データ(行列範囲)がある場合に、特に適用します。この行列範囲を自動で判別して、抽出してpandasデータフレーム形式へ読み込む雛形コードを記載しました。
その仕組みは次の通りです。まず、先頭行はA列に対して「水準No」というキーワードで検索して、その行番号を取得します。これが表データの開始行になります。次に、最終列は、「水準No」の行に対して右側から検索して空白文字でなくなった列番号を取得します。これが表データの最終列になります。最後に、単にシート内の最終行は、「ws.max_row」で取得できます。これが表データの最終行になります。以上により、表データの行数や列数が決まってない場合でもデータを抽出することが出来ます。
■本プログラムの仕様を説明します。
上図のようなエクセルファイルがいくつかあります(下図)。
これら各々から、冒頭で述べた行列範囲の表データを自動抽出して、下図のようにひとつのcsvファイルへスタックデータにします
(備考)本例題では、スタックデータにするために全てのファイルの表データの列数が同じである必要があります。もし、処理したいエクセルファイルがひとつのみの場合には問題ありません。
そして、カテゴリ変数をラベルとして下図のように散布図を作成します。
■本プログラム
import os
import glob
import re
import openpyxl
import pandas as pd
import numpy as np
filepath_list = glob.glob(os.getcwd() + '/excel_files/*.xlsx')
filepath_list
filename_list = []
dir_path = ''
for i, mypath in enumerate(filepath_list):
mypath = str(mypath)
mydir_path, file_name = os.path.split(mypath)
filename_list.append(file_name)
if i == 0:
dir_path = mydir_path
filename_list_sorted = sorted(filename_list, key=lambda x:int((re.search(r"[0-9]+", x)).group(0)))
print(filename_list_sorted)
new_filepath_list = []
for myfilename in filename_list_sorted:
mypath = os.path.join(dir_path, myfilename)
new_filepath_list.append(mypath)
new_filepath_list
df_list = []
for k, filepath in enumerate(new_filepath_list, start=1):
wb = openpyxl.load_workbook(filepath, data_only=True)
ws = wb.worksheets[0]
start_row = ''
for i, row in enumerate(ws.iter_rows(min_row=1), start=1):
if row[0].value == '水準No':
start_row = i
break
end_row = ws.max_row
end_col = ''
for j in reversed(range(1, ws.max_column)):
if ws.cell(row=start_row, column=j).value != None:
end_col = j
break
data_rows = []
for rows in ws.iter_rows(min_row = start_row, min_col = 1,
max_row = end_row, max_col = end_col+1):
data_cols = []
for cell in rows:
data_cols.append(cell.value)
data_rows.append(data_cols)
df = pd.DataFrame(data_rows)
column_names = df.iloc[0]
df.columns = column_names
df2 = df.drop(0)
my_label = 'category'
df2[my_label] = k
df_list.append(df2)
DF = pd.concat(df_list)
DF.to_csv('df_con.csv', index=False, encoding='cp932')
DF
import matplotlib.pyplot as plt
import japanize_matplotlib
import matplotlib.cm as cm
plt.rcParams['font.size'] = 16
my_columns = ("x", "積")
colors = cm.rainbow(np.linspace(0, 1, len(DF[my_label].unique())))
for i, p in enumerate(DF[my_label].unique()):
plt.scatter(DF.loc[DF[my_label] == p, my_columns[0]],
DF.loc[DF[my_label] == p, my_columns[1]],
color = colors[i],
label = 'label ' + str(p),
)
plt.grid(which='both')
plt.title('test')
plt.xlabel(my_columns[0])
plt.ylabel(my_columns[1])
plt.legend(bbox_to_anchor=(1, 0.95))
plt.tick_params()
plt.savefig("graph.jpg")
以上
<広告>
リンク