質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
openpyxl

openpyxlは、Excel2007以降のファイル(xlsx/xlsm/xltx/xltm)を読み書きするためのPythonライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

1187閲覧

openpyxlを用いてexcelにエラーバー付きのグラフを描きたい

Kodanosuke

総合スコア42

openpyxl

openpyxlは、Excel2007以降のファイル(xlsx/xlsm/xltx/xltm)を読み書きするためのPythonライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2023/04/03 03:21

実現したいこと

openpyxlを用いてexcelにエラーバー付きのグラフを描きたいと考えています.
項目ごとにデータをグラフにするところはできましたが,それにエラーバーをつけるとことで困っています.chatgptなどにエラーバーに関するattributeなどを聞いてみましたが,実際にコードを走らせてみるとno attributeなどのエラーで進めることができていません.どのようにしたらよい過去教示いただけないでしょうか.

前提

python 3.10
openpyxl
Excel2021

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

python

1# -*- coding: utf-8 -*- 2 3 4import numpy as np 5import openpyxl 6from openpyxl.chart import ScatterChart, Reference, Series, error_bar 7import pandas as pd 8from openpyxl.chart.shapes import GraphicalProperties, LineProperties 9import glob 10import datetime as dt 11import re 12from tqdm import tqdm 13 14notime = dt.date(2023, 2, 15).strftime('%Y%m%d') # dt.datetime.now().strftime('%Y%m%d')# 15file_list = glob.glob(r"E:\Res\*.xlsx") 16 17file_list = [ll for ll in file_list if notime in ll and "static" not in ll] 18# プロットラインのカラー: HEXカラーで指定,#は不要 19line_col = [["f5e502", "0d0d0d"] , ["CC00", "CC01"]] 20 21# 既存のシートを削除する(1) or Not(0) 22sheet_inplace = 1 23 24# file_list = file_list[: 2] 25nfiles = len(file_list) 26# ファイルのループ↓ 27for ii, iFile in tqdm(enumerate(file_list), postfix="postfix"): 28 29 #workbook and worksheet 30 tgt_file = file_list[ii] 31 ub = [m.start() for m in re.finditer('_', tgt_file)] 32 sub = tgt_file[ub[-2]+1: ub[-1]] 33 peri = [m.start() for m in re.finditer('.xlsx', tgt_file)] 34 side = tgt_file[peri[0]-1].lower() 35 # print(iFile) 36 wb = openpyxl.load_workbook(tgt_file) 37 wsData = wb["Mean"] 38 39 40 wsData_data = pd.DataFrame(wsData.values) 41 wsData_dataT = pd.DataFrame(wsData.values).T.rename(columns={0: "Sub", 1: "Action", 2: "Shoes", 3: "Var", 4: "Compo", 5: "Ctime"}) 42 43 wsData_dataT_time = wsData_dataT[wsData_dataT["Var"] =="ContactTime"].sort_values(['Sub', 'Var', 'Compo']) 44 rT, cT = wsData_dataT_time.T.shape 45 46 47 48 var_pickup = np.array([["Var1", "Y"]])#, 49 50 qqqq = [] 51 52 qq1 = [wsData_dataT[(wsData_dataT["Var"] =="r"+str(var_pickup[l,0])) & (wsData_dataT["Compo"] ==str(var_pickup[l,1])) ].values.tolist() for l in range(len(var_pickup)) if wsData_dataT[(wsData_dataT["Var"] =="r"+str(var_pickup[l,0])) & (wsData_dataT["Compo"] ==str(var_pickup[l,1]))].values.tolist()] 53 qq2 = [wsData_dataT[(wsData_dataT["Var"] =="l"+str(var_pickup[l,0])) & (wsData_dataT["Compo"] ==str(var_pickup[l,1])) ].values.tolist() for l in range(len(var_pickup)) if wsData_dataT[(wsData_dataT["Var"] =="l"+str(var_pickup[l,0])) & (wsData_dataT["Compo"] ==str(var_pickup[l,1]))].values.tolist()] 54 qq3 = [wsData_dataT[(wsData_dataT["Var"] ==str(var_pickup[l,0])) & (wsData_dataT["Compo"] ==str(var_pickup[l,1])) ].values.tolist() for l in range(len(var_pickup)) if wsData_dataT[(wsData_dataT["Var"] ==str(var_pickup[l,0])) & (wsData_dataT["Compo"] ==str(var_pickup[l,1])) ].values.tolist()] 55 56 qqqq = qq1 + qq2 + qq3 57 58 blank = pd.DataFrame() 59 # 60 for l in range(len(qqqq)): 61 tt = pd.DataFrame(qqqq[l]).rename(columns={0: "Sub", 1: "Action", 2: "Shoes", 3: "Var", 4: "Compo", 5: "Ctime"}) 62 blank = pd.concat([blank, tt] , axis=0) 63 # # q = [wsData_dataT[wsData_dataT["Var"].str.endswith(tuple(var_pickup[i,0])) & wsData_dataT["Compo"].str.endswith(tuple(var_pickup[i,1]))] for i in range(len(var_pickup[: ,1]))] 64 65 blank = blank.sort_values(['Sub', 'Var', 'Compo']) 66 wsData_data = pd.concat([wsData_dataT_time, blank]).T.reset_index(drop=True) 67 sh = wsData_data.shape 68 wsData_data.columns = range(sh[1]) 69 wsData_dataTT = wsData_data.T.rename(columns={0: "Sub", 1: "Action", 2: "Shoes", 3: "Var", 4: "Compo", 5: "Ctime"}) 70 # t = wsData_dataT[wsData_dataT["Var"].isin([])]#wsData_dataT.filter(items = var_pickup[: ,0]) 71 var_list = wsData_dataTT[~(wsData_dataTT.iloc[: ,3] =="ContactTime")][['Var', 'Compo']].reset_index(drop=True).drop_duplicates().values 72 # var_list = np.unique(var_list, axis=0) 73 sub_list = sorted(list(set(wsData_dataTT[~(wsData_dataTT.iloc[: ,0] =="ContactTime")].T.iloc[0,: ]))) 74 shoes_list = list(set(wsData_dataTT[~(wsData_dataTT.iloc[: ,2] =="ContactTime")].T.iloc[2,: ])) 75 compo_list = list(set(wsData_dataTT[~(wsData_dataTT.iloc[: ,2] =="ContactTime")].T.iloc[4,: ])) 76 77 var_n = len(var_list) 78 sub_n = len(sub_list) 79 shoes_n = len(shoes_list) 80 81 ttt = [] 82 tt1 = [] 83 tt2=[] 84 85 cntcnt = 1 86 87 checkbox = [] 88 89 #被験者ごとのループ 90 for ij, iSub in enumerate(sub_list): 91 snames = wb.sheetnames 92 if sheet_inplace == 1: 93 for jj in snames: 94 # print("chart" in jj) 95 if "Chart"+iSub in jj: 96 wb.remove(wb[jj]) 97 wsRes = wb.create_sheet("Chart"+iSub) 98 wsSD = wb.create_sheet("SD"+iSub) 99 wsRes_data = pd.DataFrame(wsRes.values) 100 101 102 X = np.array(wsData_dataTT[(wsData_dataTT["Var"] =="ContactTime") & (wsData_dataTT["Sub"] ==iSub)&(wsData_dataTT.Shoes.str.contains("|".join(tgt_shoes)))].T.iloc[6: ,: ])#np.array(wsData_data.iloc[6: ,0: 8]) 103 X_head = wsData_dataTT[(wsData_dataTT["Var"] =="ContactTime") & (wsData_dataTT["Sub"] ==iSub)&(wsData_dataTT.Shoes.str.contains("|".join(tgt_shoes)))].T.iloc[: 4,: ]#wsData_data.iloc[: 4,0: 8] 104 105 106 rT, cT = X.shape 107 for iFr in range(rT): 108 for iShoes in range(cT): 109 a = X_head.iloc[0, iShoes]+X_head.iloc[1, iShoes]+X_head.iloc[2, iShoes]+X_head.iloc[3, iShoes] 110 aa = "Time" 111 wsRes.cell(row = 2, column = iShoes+1, value=a) 112 wsRes.cell(row = 1, column = iShoes+1, value=aa) 113 wsRes.cell(row = 3+iFr, column= iShoes+1, value=X[iFr, iShoes]) 114 # wsRes.cell(row = 1, column = iShoes+1, value=a) 115 # wsRes.cell(row = 2+iFr, column= +iShoes+1, value=X[iFr, iShoes]) 116 117 timeCheck = pd.DataFrame(wsRes.values) 118 119 cnt = 0 120 var_check = [] 121 #変数ごとのループ 122 for n, iVar in enumerate(var_list): 123 124 Y = np.array(wsData_dataTT[~(wsData_dataTT["Var"] =="ContactTime") & (wsData_dataTT["Sub"] ==iSub) &(wsData_dataTT["Var"] ==iVar[0]) &(wsData_dataTT["Compo"] ==iVar[1]) &(wsData_dataTT.Shoes.str.contains("|".join(tgt_shoes)))].T.iloc[6: ,: ])#np.array(wsData_data.iloc[6: ,0: 8]) 125 Y_head = wsData_dataTT[~(wsData_dataTT["Var"] =="ContactTime") & (wsData_dataTT["Sub"] ==iSub) &(wsData_dataTT["Var"] ==iVar[0]) &(wsData_dataTT["Compo"] ==iVar[1])&(wsData_dataTT.Shoes.str.contains("|".join(tgt_shoes)))].T.iloc[: 5,: ]#wsData_data.iloc[: 4,0: 8] 126 127 128 var_check.append(str(iVar)+iSub) 129 rD, cD = Y.shape 130 #ScatterChartオブジェクト作成 131 chart = ScatterChart() 132 cntcnt = 0 133 134 #シューズごとのループ 135 rD, cD = Y.shape 136 pre_sd = np.zeros((rD, cD)) 137 for iShoes in range(cD): 138 139 b = Y_head.iloc[2, iShoes]#Y_head.iloc[0, iShoes]+Y_head.iloc[1, iShoes]+Y_head.iloc[2, iShoes]+Y_head.iloc[3, iShoes]+Y_head.iloc[4, iShoes] 140 bb = Y_head.iloc[0, iShoes]+Y_head.iloc[1, iShoes]+Y_head.iloc[2, iShoes]+Y_head.iloc[3, iShoes]+Y_head.iloc[4, iShoes] 141 shoesname = Y_head.iloc[2, iShoes] 142 cnt = cnt+1 143 tgtC = shoes_n+cnt 144 145 cntcnt = cntcnt+1 146 if cntcnt > shoes_n: 147 break 148 for iFr in range(rD): 149 nFr = len(Y[:, iShoes]) 150 wsRes.cell(row=1, column =tgtC, value=bb) 151 wsRes.cell(row=2, column =tgtC, value=b) 152 wsRes.cell(row=3+iFr, column =tgtC, value = Y[iFr,iShoes]) 153 pre_sd[iFr, iShoes] = Y[iFr,iShoes] 154 155 156 sd = np.std(pre_sd, axis=1) 157 for iFr in range(rD): 158 wsSD.cell(row=1, column =tgtC-shoes_n, value=bb) 159 wsSD.cell(row=2, column =tgtC-shoes_n, value=b) 160 wsSD.cell(row=3+iFr, column =tgtC-shoes_n, value = sd[iFr]) 161 162 #xの範囲を設定 163 min_row = 2 164 max_row = min_row + rT - 1 165 x_values = Reference(wsRes, min_col = iShoes+1, min_row = min_row+1, max_row = max_row+1) 166 167 #yの範囲を設定 168 min_row = 2 169 max_row = min_row + rD - 1 170 y_values = Reference(wsRes, min_col = tgtC, min_row = min_row, max_row = max_row+1) 171 y_sd = Reference(wsSD, min_col = tgtC-shoes_n, min_row = min_row, max_row = max_row+1) 172 173 174 #グラフの追加 175 series = Series(y_values, x_values, title="ScatterChart", title_from_data=True) 176 chart.y_error_bars(type='custom', value=sd, plus=sd, minus=sd) 177 chart.series.append(series) 178 series.spPr.ln.solidFill = line_col[0][line_col[1].index(shoesname)] 179 # #標準偏差の追加 180 # stdev_line = Reference(wsRes, min_col=2, min_row=1, max_row=1) 181 # stdev_series = Series(values=stdev_line, title='Stdev') 182 # chart.series.append(stdev_series) 183 184 posi = wsRes.cell(row=20+10*(n%2), column= 15+5*(n-1)).coordinate 185 wsRes.add_chart(chart, posi) 186 187 188 #保存 189 190 tgt_file = tgt_file.replace(".xlsx", "_"+"".join(tgt_shoes)+"_"+".xlsx") 191 192 wb.save(tgt_file) 193 wb.close() 194 195

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

CHERRY

2023/04/03 03:31

試したコードとエラー内容をそのまま正確に記載していただくことは可能でしょうか。
Kodanosuke

2023/04/03 04:33

質問ありがとうございます. 大変恐縮ですが,これ以上のコードは文字数などの関係もあり載せられないです. エラーとしては以下の内容になります. 「Exception has occurred: AttributeError 'ScatterChart' object has no attribute 'y_error_bars' File "C:\XXXXX\XXXX\XXX.py", line 229, in <module> chart.y_error_bars(type='custom', value=sd, plus=sd, minus=sd)」 こちらでお分かりになりますでしょうか.よろしくお願いいたします.
Kodanosuke

2023/04/03 09:00

ありがとうございます. ご教示いただいたサイトを参考にしたら完成できました! 大変お世話になりました!
guest

回答1

0

自己解決

https://openpyxl.readthedocs.io/en/latest/api/openpyxl.chart.error_bar.html
https://github.com/uskysd/openpyxl-errorbar
上記のサイト,コードを参考にしたら完成できました.ありがとうございました.

投稿2023/04/03 09:01

Kodanosuke

総合スコア42

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問