import pandas as pd
import matplotlib.cm as cm
import plotly
import plotly.express as px
import plotly.io as pio
# ファイル保存用の接頭辞
prefix = 'tws-compare'
print('------------------------------------------------------------')
'Jabra [Elite 75t]'
'Klipsch [T5]'
'Galaxy [Galaxy Buds Pro]'
'AVIOT [TE-D01t]'
'Nothing [Ear(1)]'
'SONY [WF-1000XM4]'
'Jabra [Elite 85t]'
'Jabra [Elite 7 Active]'
'XROUND [FORGE NC]'
data = {
'Jabra [Elite 75t]': {
'本体再生時間(ANCあり)': 5.5,
'本体再生時間(ANCなし)': 7.5,
'ノイキャン低音': 6,
'ノイキャン高音': 4,
'外音取り込み': 8,
'ドライバーサイズ': 6,
'音質低音': 7,
'音質高音': 5,
'操作性': 8,
'アプリの使いやすさ': 8,
'付加機能': 5,
'防水(IPX○)': 5,
'防塵(IP○X)': 5,
'デザイン': 6,
},
'Galaxy [Galaxy Buds Pro]': {
'本体再生時間(ANCあり)': 5,
'本体再生時間(ANCなし)': 8,
'ノイキャン低音': 7,
'ノイキャン高音': 5,
'外音取り込み': 5,
'ドライバーサイズ': 11,
'音質低音': 7,
'音質高音': 7,
'操作性': 5,
'アプリの使いやすさ': 5,
'付加機能': 5,
'防水(IPX○)': 7,
'防塵(IP○X)': 0,
'デザイン': 7,
},
'AVIOT [TE-D01t]': {
'本体再生時間(ANCあり)': 12.6,
'本体再生時間(ANCなし)': 18,
'ノイキャン低音': 5,
'ノイキャン高音': 4,
'外音取り込み': 4,
'ドライバーサイズ': 10,
'音質低音': 6,
'音質高音': 5,
'操作性': 7,
'アプリの使いやすさ': 4,
'付加機能': 5,
'防水(IPX○)': 4,
'防塵(IP○X)': 0,
'デザイン': 4,
},
'Nothing [Ear(1)]': {
'本体再生時間(ANCあり)': 4,
'本体再生時間(ANCなし)': 5.7,
'ノイキャン低音': 4,
'ノイキャン高音': 4,
'外音取り込み': 4,
'ドライバーサイズ': 11.6,
'音質低音': 6,
'音質高音': 4,
'操作性': 3,
'アプリの使いやすさ': 3,
'付加機能': 4,
'防水(IPX○)': 4,
'防塵(IP○X)': 0,
'デザイン': 8,
},
'SONY [WF-1000XM4]': {
'本体再生時間(ANCあり)': 8,
'本体再生時間(ANCなし)': 12,
'ノイキャン低音': 10,
'ノイキャン高音': 8,
'外音取り込み': 7,
'ドライバーサイズ': 6,
'音質低音': 7,
'音質高音': 7,
'操作性': 2,
'アプリの使いやすさ': 6,
'付加機能': 8,
'防水(IPX○)': 4,
'防塵(IP○X)': 0,
'デザイン': 7,
},
'Jabra [Elite 85t]': {
'本体再生時間(ANCあり)': 5.5,
'本体再生時間(ANCなし)': 7,
'ノイキャン低音': 9,
'ノイキャン高音': 6,
'外音取り込み': 8,
'ドライバーサイズ': 12,
'音質低音': 8,
'音質高音': 7,
'操作性': 8,
'アプリの使いやすさ': 8,
'付加機能': 6,
'防水(IPX○)': 4,
'防塵(IP○X)': 0,
'デザイン': 6,
},
'Jabra [Elite 7 Active]': {
'本体再生時間(ANCあり)': 8,
'本体再生時間(ANCなし)': 10,
'ノイキャン低音': 8,
'ノイキャン高音': 7,
'外音取り込み': 8,
'ドライバーサイズ': 6,
'音質低音': 7,
'音質高音': 6,
'操作性': 7,
'アプリの使いやすさ': 7,
'付加機能': 5,
'防水(IPX○)': 5,
'防塵(IP○X)': 7,
'デザイン': 7,
},
'XROUND [FORGE NC]': {
'本体再生時間(ANCあり)': 9,
'本体再生時間(ANCなし)': 11.7,
'ノイキャン低音': 6,
'ノイキャン高音': 4,
'外音取り込み': 5,
'ドライバーサイズ': 7,
'音質低音': 6,
'音質高音': 6,
'操作性': 6,
'アプリの使いやすさ': 6,
'付加機能': 8,
'防水(IPX○)': 7,
'防塵(IP○X)': 6,
'デザイン': 7,
},
}
print('------------------------------------------------------------')
# 評価をデータフレームに落とし込む
df = pd.DataFrame()
for name in data:
for item, val in data[name].items():
dct = {'項目': item, '点数': val, 'TWS': name}
df = df.append(dct, ignore_index=True)
print(df)
# 項目 点数 TWS
# 0 本体再生時間(ANCあり) 5.5 Jabra [Elite 75t]
# 1 本体再生時間(ANCなし) 7.5 Jabra [Elite 75t]
# 2 ノイキャン低音 6.0 Jabra [Elite 75t]
# 3 ノイキャン高音 4.0 Jabra [Elite 75t]
# 4 外音取り込み 8.0 Jabra [Elite 75t]
# .. ... ... ...
# 107 アプリの使いやすさ 6.0 XROUND [FORGE NC]
# 108 付加機能 8.0 XROUND [FORGE NC]
# 109 防水(IPX○) 7.0 XROUND [FORGE NC]
# 110 防塵(IP○X) 6.0 XROUND [FORGE NC]
# 111 デザイン 7.0 XROUND [FORGE NC]
# [112 rows x 3 columns]
print('------------------------------------------------------------')
# ボタン作成
def set_menus():
# ボタンの内容を作成
menu = dict(
label='line or fill', method='update',
args=[dict(fill='toself'), dict()], # 塗りつぶしを追加
args2=[dict(fill=None), dict()], # 線だけ
)
menus = [menu]
return menus
# 色付け用の関数
def set_color(data, alpha=1):
rgbas = []
for num, _ in enumerate(data):
cmap = cm.jet(num / len(data))
color = plotly.colors.convert_to_RGB_255(cmap) + (alpha,)
rgba = f"rgba{color}"
rgbas.append(rgba)
return rgbas
# グラフ保存用の関数
def save(fig, config, save_name):
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html", config=config,)
pio.write_image(fig, f"{save_name}.png")
# 作成したグラフにHTMLコードを保存
html_code = fig.to_html(
include_plotlyjs='cdn', full_html=False, config=config,
)
with open(f"{save_name}.txt", mode='w') as f:
f.write(html_code)
print('------------------------------------------------------------')
# レーダーチャート
updatemenus = [
dict(
active=0, buttons=set_menus(), type='buttons', direction="right",
x=0.3, y=1.01, xanchor='center', yanchor='bottom',
)
]
fig = px.line_polar(
df, r='点数', theta='項目',
line_close=True, color='TWS', hover_data=df,
color_discrete_sequence=set_color(data=data)
)
fig.update_traces(fill='toself') # 初期表示は塗りつぶし
# 各点のホバーと塗りつぶし部分の許可
fig.for_each_trace(lambda t: t.update(hoveron='points+fills'))
fig.update_layout(
updatemenus=updatemenus, # 塗りつぶしか線かのボタン
height=1000, # グラフの高さ
# 凡例はグラフの下に配置
legend=dict(x=0, y=0, xanchor='left', yanchor='top', orientation='h'),
# polar=dict(radialaxis=dict(range=(0, 10),)) # レーダーチャートの表示範囲
# グラフ全体とホバーのフォントサイズ変更
font_size=20, hoverlabel_font_size=20
)
fig.show()
save(fig=fig, config=None, save_name=f"{prefix}_line_polar")
print('------------------------------------------------------------')
# 棒グラフ
fig = px.bar(
df, x='項目', y='点数', barmode='group',
color='TWS', hover_data=df,
color_discrete_sequence=set_color(data=data, alpha=0.8),
range_y=(0, 10),
)
fig.update_layout(
height=500,
legend=dict(x=0, y=-0.4, xanchor='left', yanchor='top', orientation='h'),
# グラフ全体とホバーのフォントサイズ変更
font_size=20, hoverlabel_font_size=20
)
fig.show()
save(fig=fig, config=None, save_name=f"{prefix}_bar")