Wen1201 commited on
Commit
d09e48e
·
verified ·
1 Parent(s): 79788bd

Upload mcnemar_utils.py

Browse files
Files changed (1) hide show
  1. mcnemar_utils.py +57 -26
mcnemar_utils.py CHANGED
@@ -56,7 +56,7 @@ def plot_contingency_table_heatmap(ct_labeled, feature_label, title="列聯表
56
 
57
  def plot_odds_ratio_forest(or_value, ci_low, ci_high, feature_label):
58
  """
59
- 繪製勝算比森林圖
60
 
61
  Args:
62
  or_value: 勝算比
@@ -69,76 +69,107 @@ def plot_odds_ratio_forest(or_value, ci_low, ci_high, feature_label):
69
  """
70
  fig = go.Figure()
71
 
 
 
 
 
72
  # 參考線 (OR = 1)
73
  fig.add_shape(
74
  type="line",
75
  x0=1, x1=1,
76
- y0=-0.5, y1=0.5,
77
  line=dict(color="red", width=2, dash="dash"),
78
  )
79
 
80
- # 信賴區間
81
  fig.add_trace(go.Scatter(
82
  x=[ci_low, ci_high],
83
  y=[0, 0],
84
  mode='lines',
85
- line=dict(color='#2d6ca2', width=3),
86
  showlegend=False,
87
- hovertemplate='95% CI: [%{x:.3f}]<extra></extra>'
88
  ))
89
 
90
- # 點估計
 
 
 
 
 
 
 
 
 
91
  fig.add_trace(go.Scatter(
92
  x=[or_value],
93
  y=[0],
94
  mode='markers',
95
  marker=dict(
96
- size=15,
97
- color='#d62728',
98
- line=dict(color='white', width=2)
99
  ),
100
  showlegend=False,
101
- hovertemplate=f'OR: {or_value:.3f}<extra></extra>'
102
  ))
103
 
104
- # 添加數值標註
105
  fig.add_annotation(
106
- x=or_value,
107
- y=0.15,
108
  text=f"OR = {or_value:.3f}<br>95% CI [{ci_low:.3f}, {ci_high:.3f}]",
109
- showarrow=False,
110
- font=dict(size=12, color='#1b4f72'),
111
- bgcolor='rgba(255,255,255,0.8)',
 
 
 
 
 
 
112
  bordercolor='#2d6ca2',
113
- borderwidth=1,
114
- borderpad=4
115
  )
116
 
117
  fig.update_layout(
118
- title=f'勝算比 (Odds Ratio)<br><sub>{feature_label}</sub>',
 
 
 
 
119
  xaxis_title='Odds Ratio',
120
  yaxis=dict(
121
  showticklabels=False,
122
  showgrid=False,
123
- zeroline=False
 
124
  ),
125
- width=700,
126
- height=300,
127
  template='plotly_white',
128
- #xaxis=dict(type='log', showgrid=True),
129
  xaxis=dict(
130
- type='linear', # 改線性
131
  showgrid=True,
 
132
  tickmode='linear',
133
  tick0=0,
134
  dtick=0.5, # 每 0.5 一個刻度
135
- range=[0, max(ci_high * 1.2, 5)] # 動態範圍
 
 
 
 
136
  ),
137
- hovermode='closest'
 
 
138
  )
139
 
140
  return fig
141
 
 
142
  def plot_discordant_pairs(b, c, label_pos, label_neg):
143
  """
144
  繪製不一致配對比較圖
 
56
 
57
  def plot_odds_ratio_forest(or_value, ci_low, ci_high, feature_label):
58
  """
59
+ 繪製勝算比森林圖(線性刻度版本)
60
 
61
  Args:
62
  or_value: 勝算比
 
69
  """
70
  fig = go.Figure()
71
 
72
+ # 動態計算 x 軸範圍
73
+ x_max = max(ci_high * 1.2, 3.5) # 至少到 3.5
74
+ x_min = 0
75
+
76
  # 參考線 (OR = 1)
77
  fig.add_shape(
78
  type="line",
79
  x0=1, x1=1,
80
+ y0=-0.3, y1=0.3,
81
  line=dict(color="red", width=2, dash="dash"),
82
  )
83
 
84
+ # 信賴區間(水平線)
85
  fig.add_trace(go.Scatter(
86
  x=[ci_low, ci_high],
87
  y=[0, 0],
88
  mode='lines',
89
+ line=dict(color='#2d6ca2', width=2),
90
  showlegend=False,
91
+ hoverinfo='skip'
92
  ))
93
 
94
+ # 信賴區間端(小豎線)
95
+ for x_pos in [ci_low, ci_high]:
96
+ fig.add_shape(
97
+ type="line",
98
+ x0=x_pos, x1=x_pos,
99
+ y0=-0.05, y1=0.05,
100
+ line=dict(color='#2d6ca2', width=2)
101
+ )
102
+
103
+ # 點估計(藍色圓點)
104
  fig.add_trace(go.Scatter(
105
  x=[or_value],
106
  y=[0],
107
  mode='markers',
108
  marker=dict(
109
+ size=12,
110
+ color='#1f77b4',
111
+ line=dict(color='white', width=1.5)
112
  ),
113
  showlegend=False,
114
+ hovertemplate=f'<b>OR: {or_value:.3f}</b><br>95% CI: [{ci_low:.3f}, {ci_high:.3f}]<extra></extra>'
115
  ))
116
 
117
+ # 添加數值標註框(右上角)
118
  fig.add_annotation(
119
+ x=ci_high + (x_max - ci_high) * 0.3,
120
+ y=0,
121
  text=f"OR = {or_value:.3f}<br>95% CI [{ci_low:.3f}, {ci_high:.3f}]",
122
+ showarrow=True,
123
+ arrowhead=2,
124
+ arrowsize=1,
125
+ arrowwidth=1.5,
126
+ arrowcolor='#2d6ca2',
127
+ ax=50,
128
+ ay=0,
129
+ font=dict(size=11, color='#1b4f72'),
130
+ bgcolor='rgba(255,255,255,0.95)',
131
  bordercolor='#2d6ca2',
132
+ borderwidth=1.5,
133
+ borderpad=6
134
  )
135
 
136
  fig.update_layout(
137
+ title=dict(
138
+ text=f'勝算比 (Odds Ratio)<br><sub style="font-size:11px;">{feature_label}</sub>',
139
+ x=0.5,
140
+ xanchor='center'
141
+ ),
142
  xaxis_title='Odds Ratio',
143
  yaxis=dict(
144
  showticklabels=False,
145
  showgrid=False,
146
+ zeroline=False,
147
+ range=[-0.35, 0.35]
148
  ),
149
+ width=800,
150
+ height=280,
151
  template='plotly_white',
 
152
  xaxis=dict(
153
+ type='linear', # 改線性刻度
154
  showgrid=True,
155
+ gridcolor='rgba(200,200,200,0.3)',
156
  tickmode='linear',
157
  tick0=0,
158
  dtick=0.5, # 每 0.5 一個刻度
159
+ range=[x_min, x_max],
160
+ showline=True,
161
+ linewidth=1,
162
+ linecolor='black',
163
+ mirror=True
164
  ),
165
+ hovermode='closest',
166
+ plot_bgcolor='white',
167
+ margin=dict(l=60, r=60, t=80, b=60)
168
  )
169
 
170
  return fig
171
 
172
+
173
  def plot_discordant_pairs(b, c, label_pos, label_neg):
174
  """
175
  繪製不一致配對比較圖