如何在Plotly中基于Litho Code条件绘制测井图填充区间
问题:在Plotly测井图中实现基于岩性代码的区间填充效果
我正尝试使用Plotly绘制测井图,但发现Plotly没有Matplotlib中的fill-in-between功能。我希望基于数据框的Litho Code列(值8对应黄色),在特定深度区间添加填充效果,目标效果如图所示。
样本数据
| 井(Well) | 深度(Depth) | 自然伽马(GR) | 岩性代码(Litho Code) |
|---|---|---|---|
| A | 146.6088 | 63.1578 | |
| A | 146.7612 | 59.0457 | 8 |
| A | 146.9136 | 57.9425 | 8 |
| A | 147.2184 | 60.1089 | |
| A | 147.3708 | 59.1862 | 8 |
| A | 147.5232 | 57.9626 | 8 |
现有代码
logplot = make_subplots(rows=1, cols=8, shared_yaxes = True) logplot.add_trace(go.Scatter(x=df['GR'], y=df['DEPTH'], name='GR', line_color='green'), row=1, col=1) logplot.update_xaxes(col=1, title_text='GR', linecolor='#585858') logplot.update_xaxes(showline=True, linewidth=2, linecolor='black', mirror=True, ticks='inside', tickangle=0) logplot.update_yaxes(tickmode='linear', tick0=0, dtick=250, showline=True, linewidth=2, ticks='outside', mirror=True, linecolor='black') logplot.update_yaxes(row=1, col=1, autorange='reversed') logplot.update_layout(height=750, width=650, showlegend=False, template = 'plotly', margin={'r':0,'t':50,'l':0,'b':0})
解决方案
Plotly中可以通过add_shape添加矩形的方式实现区间填充,具体步骤如下:
1. 预处理数据,提取连续岩性区间
先识别出所有岩性代码(Litho Code)为8的连续深度段:
# 转换空值为NaN,方便后续处理 df['岩性代码(Litho Code)'] = pd.to_numeric(df['岩性代码(Litho Code)'], errors='coerce') # 标记连续的岩性区间 df['litho_group'] = (df['岩性代码(Litho Code)'] != df['岩性代码(Litho Code)'].shift()).cumsum() # 筛选出岩性代码为8的区间,计算每个区间的深度上下限 litho_intervals = df[df['岩性代码(Litho Code)'] == 8].groupby('litho_group').agg( min_depth=('深度(Depth)', 'min'), max_depth=('深度(Depth)', 'max') ).reset_index(drop=True)
2. 在Plotly图中添加黄色填充矩形
遍历每个岩性区间,用add_shape绘制覆盖GR轴范围的黄色半透明矩形:
# 获取GR轴的数值范围,也可以手动设置固定值(比如0-150) gr_min = df['自然伽马(GR)'].min() gr_max = df['自然伽马(GR)'].max() # 为每个区间添加填充 for idx, row in litho_intervals.iterrows(): logplot.add_shape( type="rect", x0=gr_min, x1=gr_max, y0=row['min_depth'], y1=row['max_depth'], fillcolor="yellow", opacity=0.3, # 调整透明度避免遮挡曲线 line_width=0, # 隐藏矩形边框 row=1, col=1 # 指定填充在GR所在的子图 )
3. 完整整合代码
import plotly.graph_objects as go from plotly.subplots import make_subplots import pandas as pd # 构造样本数据 data = { '井(Well)': ['A']*6, '深度(Depth)': [146.6088, 146.7612, 146.9136, 147.2184, 147.3708, 147.5232], '自然伽马(GR)': [63.1578, 59.0457, 57.9425, 60.1089, 59.1862, 57.9626], '岩性代码(Litho Code)': ['', 8, 8, '', 8, 8] } df = pd.DataFrame(data) # 预处理数据,提取连续岩性区间 df['岩性代码(Litho Code)'] = pd.to_numeric(df['岩性代码(Litho Code)'], errors='coerce') df['litho_group'] = (df['岩性代码(Litho Code)'] != df['岩性代码(Litho Code)'].shift()).cumsum() litho_intervals = df[df['岩性代码(Litho Code)'] == 8].groupby('litho_group').agg( min_depth=('深度(Depth)', 'min'), max_depth=('深度(Depth)', 'max') ).reset_index(drop=True) # 创建测井图 logplot = make_subplots(rows=1, cols=8, shared_yaxes=True) logplot.add_trace(go.Scatter(x=df['自然伽马(GR)'], y=df['深度(Depth)'], name='GR', line_color='green'), row=1, col=1) logplot.update_xaxes(col=1, title_text='GR', linecolor='#585858') # 添加岩性填充 gr_min = df['自然伽马(GR)'].min() gr_max = df['自然伽马(GR)'].max() for idx, row in litho_intervals.iterrows(): logplot.add_shape( type="rect", x0=gr_min, x1=gr_max, y0=row['min_depth'], y1=row['max_depth'], fillcolor="yellow", opacity=0.3, line_width=0, row=1, col=1 ) # 布局设置 logplot.update_xaxes(showline=True, linewidth=2, linecolor='black', mirror=True, ticks='inside', tickangle=0) logplot.update_yaxes(tickmode='linear', tick0=0, dtick=250, showline=True, linewidth=2, ticks='outside', mirror=True, linecolor='black') logplot.update_yaxes(row=1, col=1, autorange='reversed') logplot.update_layout(height=750, width=650, showlegend=False, template='plotly', margin={'r':0,'t':50,'l':0,'b':0}) # 显示图形 logplot.show()
说明:
- 若需要固定GR轴范围,直接将
gr_min和gr_max设为目标数值即可(如gr_min=0, gr_max=150) - 调整
opacity参数可以控制填充的透明度,平衡填充效果与曲线可读性
内容的提问来源于stack exchange,提问作者naranara
相关产品推荐
相关产品推荐

