medical-kiban commited on
Commit
d48dc67
·
1 Parent(s): 8f3ff15

視覚化サンプル追加

Browse files
Files changed (3) hide show
  1. address.csv +0 -62
  2. app.py +246 -11
  3. requirements.txt +3 -0
address.csv CHANGED
@@ -1,9 +1,4 @@
1
  name,address
2
- 仙台駅前院,宮城県仙台市青葉区中央3-6-1 仙台TRビル東館 7F
3
- 福島院,福島県福島市置賜町1-29 佐平ビル 1F
4
- 郡山院,福島県郡山市駅前2丁目3番7号エリート30ビル7F・8F
5
- 宇都宮院,栃木県宇都宮市駅前通り1-4-6 トナリエ宇都宮 5F
6
- 水戸院,茨城県水戸市宮町1-7-33 水戸サウスタワー 6F(水戸オーパ内)
7
  川口院,埼玉県川口市栄町3-8-15 近代グループBLD.23号館 8F
8
  大宮東口院,埼玉県さいたま市大宮区仲町1-15 VORT大宮 7F
9
  新宿東口院,東京都新宿区歌舞伎町1-27-5 歌舞伎町APMビル 7F
@@ -24,8 +19,6 @@ name,address
24
  千葉駅前院,千葉県中央区新千葉2-2-1 新日本EXビル 3F
25
  横浜院,神奈川県横浜市西区北幸1-8-2 犬山西口ビルヂング 3F
26
  新横浜院,神奈川県横浜市港北区新横浜2丁目5-14 WISENEXT新横浜 7F
27
- 名古屋栄院,愛知県名古屋市中区栄3-28-11 名古屋ゼロゲート 2F
28
- 名古屋駅前院,愛知県名古屋市中村区名駅3-26-6 ThirdKHビル 5F
29
  京都駅前院,京都府京都市下京区七条通烏丸東入真苧屋町195番地 福井ビル3F
30
  江坂院,大阪府吹田市江坂町1-21-17 ESAKA松尾ビル 3F
31
  堺院,大阪府堺市堺区北瓦町2-4-12 岡本ビル 5F
@@ -33,86 +26,31 @@ name,address
33
  心斎橋院,大阪府大阪市中央区南船場4-4-10 辰野心斎橋ビル 4F
34
  梅田大阪駅前院,大阪府大阪市北区曽根崎2-8-15 K'sスクエアビル 3F
35
  梅田茶屋町院,大阪府大阪市北区茶屋町2-28 セントラル茶屋町 3・4F
36
- 神戸院,兵庫県神戸市中央区琴ノ緒町5-3-2 三宮駅前平和ビル 7F
37
- 福岡天神院,福岡県福岡市中央区天神2-7-6 DADAビル 6F
38
- 福岡博多院,福岡県福岡市博多区博多駅東2-4-6 ハカタベビル 3F
39
- 小倉院,福岡県北九州市小倉北区米町1-1-1 小倉駅前ひびきビル 4F
40
- 広島院,広島県広島市中区本通9-30 ランドマークビル 3F
41
- 岡山院,岡山県岡山市北区駅前町1-1-21 成通ハリービル 4F
42
  八王子院,東京都八王子市旭町2-5 八王子ツインタワーA館 4F
43
  横浜駅前院,神奈川県横浜市西区北幸1-1-8 エキニア横浜 7F
44
- 姫路院,兵庫県姫路市駅前町247番地 御幸苑ビル 2F
45
  品川院,東京都港区高輪3-23-17 品川センタービルディング 201
46
- 静岡院,静岡県静岡市葵区紺屋町17-1 葵タワー 2F 201
47
  柏院,千葉県柏市柏1-2-37 柏ちば興銀ビル 6F
48
  川越院,埼玉県川越市脇田本町1-2 山崎ビル 4F
49
- 札幌駅前院,北海道札幌市中央区北4条西2-1-2 キタコートレードビル 6F
50
  川崎院,神奈川県川崎市川崎区駅前本町12-1 川崎駅前タワー・リバーク B2F
51
  ブレインクリニック新宿,東京都新宿区新宿4-2-23 新四curumuビル 8F
52
  ブレインクリニック東京,東京都中央区日本橋2-2-2 マルヒロ日本橋ビル 8F
53
- ブレインクリニック名古屋,愛知県名古屋市中村区名駅3-26-6 ThirdKHビル 3F
54
  ブレインクリニック大阪,大阪府大阪市北区曽根崎新地2-4-1 ホテルマイステイズプレミア堂島 地下1F
55
- 熊本院,熊本県熊本市中央区上通町1-26 auneKUMAMOTO 8F
56
- 鹿児島院,鹿児島県鹿児島市中央町11番地 鹿児島中央ターミナルビル 2F
57
- 高崎院,群馬県高崎市八島町46-1 高崎オーパ 8F
58
  天王寺院,大阪府大阪市阿倍野区阿倍野筋1-5-36 アベノセンタービル 2F
59
  TCBスキンクリニック大阪駅前院,大阪府大阪市北区梅田2-1-21 レイズ ウメダビル 8F
60
  ブレインクリニック浜松町,東京都港区浜松町2-7-17 イーグル浜松町ビル 5F
61
- 仙台広瀬通院,宮城県仙台市青葉区中央1-6-27 仙信ビル 4F
62
- 宮崎院,宮崎県宮崎市高千穂通2-6-18 NMビル 7F
63
- 岐阜院,岐阜県岐阜市神田町8-9-2 白木ビル 4F
64
- 長野院,長野県長野市南千歳1-1-1 ながの東急百貨店 別館シェルシェ 5F
65
- 金沢院,石川県金沢市堀川町4-1 セントラルビル 5F
66
- 新潟院,新潟県新潟市中央区花園1-2-2 コープシティ花園ガレッソ 2F
67
  奈良院,奈良県奈良市小西町21-1 小西町商業ビル(な・ら・ら) 2F
68
  北千住院,東京都足立区千住2-26-2 EXCEL33 3F
69
  六本木院,東京都港区六本木5-1-3 ゴトウビルディング1st 8F
70
  新宿西口院,東京都新宿区西新宿1-17-1 日本生命新宿西口ビル 2F
71
- 大宮西口院,埼玉県さいたま市大宮区桜木町2-3 ダイエー大宮店 3F
72
- 金山院,愛知県名古屋市熱田区金山町1-4-6 アルティメイト金山 7F・8F
73
  自由が丘院,東京都目黒区自由が丘2-11-23 南風ビル 5F
74
  なんば院,大阪府大阪市中央区難波4-2-1 難波御堂筋ビルディング 9F
75
  京都四条院,京都府京都市下京区四条通東洞院東入立売西町66番地 京都証券ビル 5F
76
- 浜松院,静岡県浜松市中央区鍛冶町140 浜松Cビル 3F
77
  枚方院,大阪府枚方市岡東町8-9 枚方SGビル 5F
78
- 和歌山院,和歌山県和歌山市美園町4-81-1 SOPHIA和歌山イーストプラザⅠ号館 3F
79
- 高松院,香川県高松市兵庫町11-6 カーニープレイス高松兵庫町ビル 3F
80
- 四日市院,三重県四日市市諏訪栄町10-7 ことぶきビル 2F
81
- 長崎院,長崎県長崎市大黒町14-5 ニュー長崎ビルディング 2F
82
- 那覇院,沖縄県那覇市久茂地1-1-1 パレットくもじ 9F
83
  船橋院,千葉県船橋市本町1-7-6 ドリーム船橋ビル 5F
84
- 松山院,愛媛県松山市湊町5-4-25 日切ビル 5F
85
  越谷院,埼玉県越谷市南越谷1-15-1 南越谷ラクーン 4F
86
- 高知院,高知県高知市はりまや町2-3-3 はりまやビル 1F・2F
87
- 倉敷院,岡山県倉敷市阿知1-7-1 天満屋倉敷店 5F
88
- 福井院,福井県福井市中央1-3-3 KIビル 3F
89
- 札幌大通院,北海道札幌市中央区南1条西2-18 IKEUCHI GATE 5F
90
- 久留米院,福岡県久留米市東町39-8 第21上野ビル 3F
91
- 富山院,富山県富山市桜町1-1-1 電鉄富山駅ビル エスタ 3F
92
  藤沢院,神奈川県藤沢市南藤沢22-1 神中第二ビル 3F
93
  千葉東口院,千葉県千葉市中央区富士見2-5-15 塚本千葉第3ビルディング 5F
94
- 佐賀院,佐賀県佐賀市駅前中央1- 4-17 コムボックス佐賀駅前 2F
95
- つくば院,茨城県つくば市吾妻1-7-1 トナリエつくばスクエア トナリエクレオ 3F
96
- 豊田院,愛知県豊田市喜多町1-140 ギャザ 3F
97
  高槻院,大阪府高槻市城北町2-11-1 山木ビル 3F・4F
98
- 山形院,山形県山形市香澄町1-15-28 ホテルニュー最上屋 2F
99
- 青森院,青森県青森市新町1-7-1 THREE 4F
100
- 秋田院,秋田県秋田市中通4-12-7 川上第二ビル 3F
101
- 盛岡院,岩手県盛岡市菜園1-10-1 パルクアベニュー・カワトク 8F
102
- 大分院,大分県大分市府内町2-1-4 トキハ会館 2F
103
  本厚木院,神奈川県厚木市中町3-6-17 オーイズミホールディングス厚木ビル 5F
104
  大阪阪急梅田駅前院,大阪府大阪市北区芝田2-6-30 梅田清和ビル 2F
105
- 徳島院,徳島県徳島市寺島本町西1丁目 駅前ポッポ街 セントラルビル 2F
106
  松戸院,千葉県松戸市松戸1307-1 キテミテマツド 8F
107
- 前橋院,群馬県前橋市表町2-30-8 アクエル前橋 B1F
108
- 名古屋駅前桜通院,愛知県名古屋市中村区名駅3-25-3 大橋ビルディング 3F
109
- 豊橋院,愛知県豊橋市広小路1-18 ウェルプラザユメックスビル B1F
110
- 松江院,島根県松江市朝日町480-8 松江SKYビル 2F
111
- 周南徳山駅ビル院,山口県周南市銀座1-31 TOKUYAMA DECK 2F
112
- 福山院,広島県福山市東桜町1-1 アイネスフクヤマ2F
113
- 松本院,長野県松本市中央二丁目3-17知新堂ビル2F
114
- 三島院,静岡県三島市本町3-29 三島本町タワー3F 301
115
- 草津院,滋賀県草津市大路1-1-1 エルティ932ビル 3F
116
- 西鉄福岡天神駅前院,福岡県福岡市中央区天神1-4-1 西日本新聞会館15F
117
- 旭川駅前院,北海道旭川市一条通8-108 フィール旭川4F
118
- 山梨甲府駅前院,山梨県甲府市丸の内二丁目16番4号 丸栄ビル3F
 
1
  name,address
 
 
 
 
 
2
  川口院,埼玉県川口市栄町3-8-15 近代グループBLD.23号館 8F
3
  大宮東口院,埼玉県さいたま市大宮区仲町1-15 VORT大宮 7F
4
  新宿東口院,東京都新宿区歌舞伎町1-27-5 歌舞伎町APMビル 7F
 
19
  千葉駅前院,千葉県中央区新千葉2-2-1 新日本EXビル 3F
20
  横浜院,神奈川県横浜市西区北幸1-8-2 犬山西口ビルヂング 3F
21
  新横浜院,神奈川県横浜市港北区新横浜2丁目5-14 WISENEXT新横浜 7F
 
 
22
  京都駅前院,京都府京都市下京区七条通烏丸東入真苧屋町195番地 福井ビル3F
23
  江坂院,大阪府吹田市江坂町1-21-17 ESAKA松尾ビル 3F
24
  堺院,大阪府堺市堺区北瓦町2-4-12 岡本ビル 5F
 
26
  心斎橋院,大阪府大阪市中央区南船場4-4-10 辰野心斎橋ビル 4F
27
  梅田大阪駅前院,大阪府大阪市北区曽根崎2-8-15 K'sスクエアビル 3F
28
  梅田茶屋町院,大阪府大阪市北区茶屋町2-28 セントラル茶屋町 3・4F
 
 
 
 
 
 
29
  八王子院,東京都八王子市旭町2-5 八王子ツインタワーA館 4F
30
  横浜駅前院,神奈川県横浜市西区北幸1-1-8 エキニア横浜 7F
 
31
  品川院,東京都港区高輪3-23-17 品川センタービルディング 201
 
32
  柏院,千葉県柏市柏1-2-37 柏ちば興銀ビル 6F
33
  川越院,埼玉県川越市脇田本町1-2 山崎ビル 4F
 
34
  川崎院,神奈川県川崎市川崎区駅前本町12-1 川崎駅前タワー・リバーク B2F
35
  ブレインクリニック新宿,東京都新宿区新宿4-2-23 新四curumuビル 8F
36
  ブレインクリニック東京,東京都中央区日本橋2-2-2 マルヒロ日本橋ビル 8F
 
37
  ブレインクリニック大阪,大阪府大阪市北区曽根崎新地2-4-1 ホテルマイステイズプレミア堂島 地下1F
 
 
 
38
  天王寺院,大阪府大阪市阿倍野区阿倍野筋1-5-36 アベノセンタービル 2F
39
  TCBスキンクリニック大阪駅前院,大阪府大阪市北区梅田2-1-21 レイズ ウメダビル 8F
40
  ブレインクリニック浜松町,東京都港区浜松町2-7-17 イーグル浜松町ビル 5F
 
 
 
 
 
 
41
  奈良院,奈良県奈良市小西町21-1 小西町商業ビル(な・ら・ら) 2F
42
  北千住院,東京都足立区千住2-26-2 EXCEL33 3F
43
  六本木院,東京都港区六本木5-1-3 ゴトウビルディング1st 8F
44
  新宿西口院,東京都新宿区西新宿1-17-1 日本生命新宿西口ビル 2F
 
 
45
  自由が丘院,東京都目黒区自由が丘2-11-23 南風ビル 5F
46
  なんば院,大阪府大阪市中央区難波4-2-1 難波御堂筋ビルディング 9F
47
  京都四条院,京都府京都市下京区四条通東洞院東入立売西町66番地 京都証券ビル 5F
 
48
  枚方院,大阪府枚方市岡東町8-9 枚方SGビル 5F
 
 
 
 
 
49
  船橋院,千葉県船橋市本町1-7-6 ドリーム船橋ビル 5F
 
50
  越谷院,埼玉県越谷市南越谷1-15-1 南越谷ラクーン 4F
 
 
 
 
 
 
51
  藤沢院,神奈川県藤沢市南藤沢22-1 神中第二ビル 3F
52
  千葉東口院,千葉県千葉市中央区富士見2-5-15 塚本千葉第3ビルディング 5F
 
 
 
53
  高槻院,大阪府高槻市城北町2-11-1 山木ビル 3F・4F
 
 
 
 
 
54
  本厚木院,神奈川県厚木市中町3-6-17 オーイズミホールディングス厚木ビル 5F
55
  大阪阪急梅田駅前院,大阪府大阪市北区芝田2-6-30 梅田清和ビル 2F
 
56
  松戸院,千葉県松戸市松戸1307-1 キテミテマツド 8F
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -8,8 +8,7 @@ import numpy as np
8
 
9
  st.set_page_config(page_title="データ分析ダッシュボード", layout="wide")
10
 
11
- # 생성
12
- tab1, tab2, tab3, tab4, tab5 = st.tabs([" データ分析ダッシュボード", "visualization1", "visualization2", "ボックスプロット", "折れ線グラフ"])
13
 
14
  with tab1:
15
  st.title("📊 データ分析ダッシュボード")
@@ -166,12 +165,14 @@ with tab3:
166
  st.header("📊 ネットワークグラフ")
167
  from pyvis.network import Network
168
  import streamlit.components.v1 as components
169
-
 
 
170
  np.random.seed(42)
171
- nodes = [f"Node_{i}" for i in range(1, 21)] # 20개의 노드 생성
172
  edges = []
173
 
174
- for _ in range(50): # 50개의 랜덤 엣지 생성
175
  src = np.random.choice(nodes)
176
  dst = np.random.choice(nodes)
177
  if src != dst:
@@ -180,21 +181,255 @@ with tab3:
180
 
181
  df = pd.DataFrame(edges, columns=["Source", "Target", "Weight"])
182
 
183
- net = Network(height="700px", width="100%", bgcolor="#222222", font_color="white")
184
- net.force_atlas_2based(gravity=-300, central_gravity=0.01, spring_length=100, spring_strength=0.08)
 
185
 
186
  for node in nodes:
187
- net.add_node(node, label=node, title=f"{node} - Custom Tooltip", color="#009688")
188
 
189
  for src, dst, weight in edges:
190
- net.add_edge(src, dst, value=weight, title=f"Weight: {weight}")
191
 
192
  net.show_buttons(filter_=["physics", "nodes", "edges"])
193
  net.toggle_physics(True)
194
  net.set_edge_smooth('dynamic')
195
 
196
  net.save_graph('network.html')
197
-
198
  HtmlFile = open("network.html", 'r', encoding='utf-8')
199
  source_code = HtmlFile.read()
200
- components.html(source_code, height=800, scrolling=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  st.set_page_config(page_title="データ分析ダッシュボード", layout="wide")
10
 
11
+ tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs([" データ分析ダッシュボード", "Folium", "Network graph", "Ribbon graph", "Sankey diagram", "Waterfall Chart"])
 
12
 
13
  with tab1:
14
  st.title("📊 データ分析ダッシュボード")
 
165
  st.header("📊 ネットワークグラフ")
166
  from pyvis.network import Network
167
  import streamlit.components.v1 as components
168
+ import pandas as pd
169
+ import numpy as np
170
+
171
  np.random.seed(42)
172
+ nodes = [f"Node_{i}" for i in range(1, 21)]
173
  edges = []
174
 
175
+ for _ in range(50):
176
  src = np.random.choice(nodes)
177
  dst = np.random.choice(nodes)
178
  if src != dst:
 
181
 
182
  df = pd.DataFrame(edges, columns=["Source", "Target", "Weight"])
183
 
184
+ net = Network(height="800px", width="100%", bgcolor="#1e1e1e", font_color="white")
185
+
186
+ net.force_atlas_2based(gravity=-500, central_gravity=0.03, spring_length=120, spring_strength=0.1)
187
 
188
  for node in nodes:
189
+ net.add_node(node, label=node, title=f"{node} - Custom Tooltip", color="#29b6f6", font={'size': 20})
190
 
191
  for src, dst, weight in edges:
192
+ net.add_edge(src, dst, value=weight, title=f"Weight: {weight}", width=weight)
193
 
194
  net.show_buttons(filter_=["physics", "nodes", "edges"])
195
  net.toggle_physics(True)
196
  net.set_edge_smooth('dynamic')
197
 
198
  net.save_graph('network.html')
 
199
  HtmlFile = open("network.html", 'r', encoding='utf-8')
200
  source_code = HtmlFile.read()
201
+ components.html(source_code, height=850, scrolling=True)
202
+
203
+ with tab4:
204
+ import plotly.graph_objects as go
205
+ import pandas as pd
206
+ import streamlit as st
207
+
208
+ st.header("📊 リボングラフ")
209
+
210
+ data = {
211
+ "categories": ["Botox", "Filler", "Laser Treatment", "Skincare", "Hair Transplant", "Others"],
212
+ "q1_2021": [1500, 2500, 1000, 2000, 1800, 1600],
213
+ "q2_2021": [1800, 2300, 1400, 1900, 1600, 1700],
214
+ "q3_2021": [2200, 2400, 1600, 1800, 2000, 1500],
215
+ "q4_2021": [2600, 2100, 1800, 1700, 2200, 1400],
216
+ "q1_2022": [2400, 2500, 1900, 2100, 2300, 1200],
217
+ "q2_2022": [2700, 2600, 1700, 2300, 2100, 1000],
218
+ "q3_2022": [2800, 2800, 2000, 2400, 2500, 900],
219
+ "q4_2022": [2900, 2900, 2100, 2400, 2700, 1100],
220
+ "q1_2023": [3100, 3000, 2200, 2500, 2900, 1200],
221
+ "q2_2023": [3300, 3100, 2400, 2600, 3000, 1300],
222
+ "q3_2023": [3400, 3200, 2500, 2700, 3200, 1400],
223
+ "q4_2023": [3500, 3300, 2600, 2800, 3300, 1500],
224
+ }
225
+ df = pd.DataFrame(data)
226
+
227
+ final = pd.DataFrame(df["categories"])
228
+ quarters = [
229
+ "q1_2021", "q2_2021", "q3_2021", "q4_2021",
230
+ "q1_2022", "q2_2022", "q3_2022", "q4_2022",
231
+ "q1_2023", "q2_2023", "q3_2023", "q4_2023"
232
+ ]
233
+
234
+ for i, col in enumerate(quarters):
235
+ ch1 = df.loc[:, ["categories", col]]
236
+ ch1.sort_values(col, inplace=True)
237
+ ch1[f"y{i}_upper"] = ch1[col].cumsum()
238
+ ch1[f"y{i}_lower"] = ch1[f"y{i}_upper"].shift(1).fillna(0)
239
+ ch1[f"y{i}"] = ch1.apply(lambda x: (x[f"y{i}_upper"] + x[f"y{i}_lower"]) / 2, axis=1)
240
+ final = final.merge(
241
+ ch1[["categories", f"y{i}_upper", f"y{i}_lower", f"y{i}"]], on="categories"
242
+ )
243
+
244
+ colors = {
245
+ "Botox": "#72c6e8",
246
+ "Filler": "#E41A37",
247
+ "Laser Treatment": "#5c606d",
248
+ "Skincare": "#12618F",
249
+ "Hair Transplant": "#d9871b",
250
+ "Others": "rgba(0,0,0,0.3)",
251
+ }
252
+
253
+ st.sidebar.header("🔍 施術フィルター")
254
+ selected_categories = st.sidebar.multiselect(
255
+ "表示する施術を選んでください:",
256
+ options=df["categories"],
257
+ default=df["categories"]
258
+ )
259
+
260
+ fig = go.Figure()
261
+ x = list(range(1, len(quarters) + 1))
262
+ x_rev = x[::-1]
263
+
264
+ for category in selected_categories:
265
+ ch1 = final.query("categories == @category")
266
+ upper_col = [col for col in ch1.columns if "upper" in col]
267
+ lower_col = [col for col in ch1.columns if "lower" in col]
268
+ upper_data = ch1[upper_col].values.tolist()[0]
269
+ lower_data = ch1[lower_col].values.tolist()[0]
270
+
271
+ smooth_upper = pd.Series(upper_data).rolling(window=2, min_periods=1).mean().tolist()
272
+ smooth_lower = pd.Series(lower_data).rolling(window=2, min_periods=1).mean().tolist()
273
+
274
+ fig.add_trace(
275
+ go.Scatter(
276
+ x=x + x_rev,
277
+ y=smooth_upper + smooth_lower[::-1],
278
+ fill="toself",
279
+ fillcolor=colors[category],
280
+ opacity=0.7,
281
+ line_color="rgba(0,0,0,0.2)",
282
+ hoverinfo="none",
283
+ showlegend=True,
284
+ name=category
285
+ )
286
+ )
287
+
288
+ fig.update_layout(
289
+ xaxis_title="Quarter",
290
+ yaxis_title="累積データ (人数)",
291
+ xaxis=dict(
292
+ tickmode="array",
293
+ tickvals=x,
294
+ ticktext=quarters
295
+ ),
296
+ plot_bgcolor="#f9f9f9",
297
+ hovermode="x unified",
298
+ height=600
299
+ )
300
+
301
+ st.title("各施術の累積データのリボングラフ")
302
+ st.plotly_chart(fig, use_container_width=True)
303
+
304
+ with tab5:
305
+ import matplotlib.pyplot as plt
306
+ import plotly.graph_objects as go
307
+
308
+
309
+ nodes = [
310
+ "カウンセリング", "二重まぶた手術", "鼻整形", "顎矯正", "脂肪吸引",
311
+ "フィラー施術", "ボトックス", "胸拡大", "リフティング", "ヘア移植",
312
+ "回復管理", "追加ケア", "再施術"
313
+ ]
314
+
315
+ links = {
316
+ 'source': [
317
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
318
+ 1, 2, 3, 4, 5, 6, 7, 8, 9,
319
+ 2, 4, 6,
320
+ 4, 7
321
+ ],
322
+ 'target': [
323
+ 1, 2, 3, 4, 5, 6, 7, 8, 9,
324
+ 10, 10, 10, 10, 10, 10, 10, 10, 10,
325
+ 11, 11, 11,
326
+ 12, 12
327
+ ],
328
+ 'value': [
329
+ 1200, 950, 800, 700, 1800, 2200, 500, 670, 430,
330
+ 1100, 900, 600, 700, 1700, 2100, 400, 600, 300,
331
+ 300, 200, 100,
332
+ 150, 100
333
+ ]
334
+ }
335
+
336
+ fig = go.Figure(go.Sankey(
337
+ arrangement="snap",
338
+ node=dict(
339
+ pad=20,
340
+ thickness=30,
341
+ line=dict(color="black", width=0.5),
342
+ label=nodes,
343
+ color=[
344
+ '#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99',
345
+ '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a',
346
+ '#ffff99', '#b15928', '#ffed6f'
347
+ ]
348
+ ),
349
+ link=dict(
350
+ source=links['source'],
351
+ target=links['target'],
352
+ value=links['value'],
353
+ color='rgba(44, 160, 44, 0.4)'
354
+ )
355
+ ))
356
+
357
+ fig.update_layout(
358
+ title_text="美容整形の施術プロセス Sankeyダイアグラム",
359
+ font=dict(size=14),
360
+ height=600
361
+ )
362
+
363
+ st.title("美容整形業界の主要な施術ルート(件数ベース)")
364
+ st.plotly_chart(fig)
365
+
366
+ with tab6:
367
+ import plotly.graph_objects as go
368
+
369
+ import plotly.graph_objects as go
370
+ import streamlit as st
371
+
372
+ # 🔹 データ定義
373
+ x = [
374
+ "2023年度 売上",
375
+ "ボトックスの売上増加",
376
+ "フィラー施術の売上減少",
377
+ "レーザー治療の売上増加",
378
+ "スキンケア商品の売上減少",
379
+ "ヘア移植の売上増加",
380
+ "その他の施術の影響",
381
+ "2024年度 予測売上",
382
+ ]
383
+ y = [32000, 4500, -3000, 6000, -2000, 3500, 800, 42800]
384
+ measure = [
385
+ "absolute",
386
+ "relative",
387
+ "relative",
388
+ "relative",
389
+ "relative",
390
+ "relative",
391
+ "relative",
392
+ "total",
393
+ ]
394
+
395
+ fig = go.Figure(
396
+ go.Waterfall(
397
+ x=x,
398
+ y=y,
399
+ measure=measure,
400
+ text=[f"{val:,}万円" for val in y],
401
+ textposition="outside",
402
+ decreasing={"marker": {"color": "#F44336"}},
403
+ increasing={"marker": {"color": "#4CAF50"}},
404
+ totals={"marker": {"color": "#2196F3"}},
405
+ connector={"line": {"color": "grey", "width": 2}},
406
+ constraintext="none"
407
+ )
408
+ )
409
+
410
+ fig.update_layout(
411
+ title={
412
+ "text": "📈 売上変動分析",
413
+ "x": 0.5,
414
+ "xanchor": "center",
415
+ "yanchor": "top",
416
+ "font": {"size": 24}
417
+ },
418
+ yaxis=dict(
419
+ title="売上 (万円)",
420
+ tickfont=dict(size=18)
421
+ ),
422
+ xaxis=dict(
423
+ tickfont=dict(size=16),
424
+ tickangle=-30
425
+ ),
426
+ height=800,
427
+ waterfallgap=0.3,
428
+ font=dict(size=18),
429
+ plot_bgcolor="rgba(0,0,0,0)",
430
+ margin=dict(l=40, r=40, t=60, b=80)
431
+ )
432
+
433
+
434
+ st.title("📊 売上変動分析")
435
+ st.plotly_chart(fig, use_container_width=True)
requirements.txt CHANGED
@@ -7,3 +7,6 @@ numpy
7
  pyvis
8
  streamlit_folium
9
  folium
 
 
 
 
7
  pyvis
8
  streamlit_folium
9
  folium
10
+ plotly
11
+ holoviews
12
+ bokeh