Plotly和Python:为岩石物理和地质数据创建交互式热力图

在亚表面内可视化井测量值的地理空间变化

使用Plotly热图探索挪威大陆架上的井测量值的地理空间变化。作者提供的图像。

解释亚表面需要理解地质和岩石物理数据在区域间的变化。这通常涉及处理散布在该区域内的井测量值和解释属性,这导致了在这些测量值之间估计值的挑战。

一个可以估计值(或填充间隙)的方法是使用一种称为克里格法的地统计学方法。该方法估计并外推观测测量值之间的数据,并预测未测量位置的值。

在我的上一篇文章中,我们专注于使用pykrigematplotlib来映射和可视化挪威大陆架上的地理变化。本文将进一步将该可视化呈现为交互式图。

利用pykrige和matplotlib进行地质变化的空间可视化

从井测量值探索空间地质变化

towardsdatascience.com

回顾使用Pykrige

在使用Plotly之前,我们将快速回顾前一篇文章中使用的代码,以便您了解该过程。

第一步是导入所需的库。在这种情况下,我们需要pandas来加载我们的csv数据,pykrige用于在数据点之间进行插值,numpy用于进行一些数学操作。

import pandas as pdfrom pykrige import OrdinaryKrigingimport numpy as npdf = pd.read_csv('Data/Xeek Force 2020/Xeek_2020_Balder_DTC_AVG.csv')

加载数据后,我们可以通过调用pykrige的OrdinaryKriging方法来执行克里金过程。

在此调用中,我们传递我们的x和y数据,表示我们数据的纬度和经度。我们还需要传递我们想要外推的变量。在这种情况下,我们使用Balder组的平均声波压缩慢度(DTC)值。

生成模型后,我们可以将其应用于覆盖井位置的自定义经纬度范围。

OK = OrdinaryKriging(x=df['LON'],                       y=df['LAT'],                       z=df['DTC_MEAN'],                      variogram_model='exponential',                      verbose=True, enable_plotting=True,                      coordinates_type='geographic')grid_lat = np.arange(57.5, 62, 0.01, dtype='float64')grid_long = np.arange(1.5, 4.5, 0.01,dtype='float64')zstar, ss = OK.execute('grid', grid_long, grid_lat)zstar

然后,我们将我们的两个位置数组grid_latgrid_long以及我们的网格数据传递到matplotlib的imshow绘图中。这将生成类似下面的图。

使用pykrige进行普通克里金的数据的Matplotlib imshow图表。作者提供的图像。

尽管我们返回的图表讲述了数据趋势的故事,但很难识别特定的井和测量点之间的任何值。

使用Plotly使我们的图表交互式

即时改变这种情况的一种方式是使用Plotly库。 Plotly是一个创建高度交互式的图表非常容易的库。

Plotly有两种主要构建图表的方式:Plotly Express和Plotly Graph Objects。

Plotly Express为Plotly提供了高级接口,并利用简单的语法创建功能强大的交互式图表。但是,定制图表的某些方面可能需要大量的工作并且可能难以完成。这就是库的Graph Objects部分发挥作用的地方。它提供了一个低级接口,可以完全控制您的图形;但是,这意味着组合图形会稍微复杂一些。

对于这个例子,我们将使用Graph Objects,可以按如下方式导入:

import plotly.graph_objects as go

接下来,我们可以使用numpy的linspace函数定义我们的xy数组。

这将创建两个与我们之前创建的数据网格大小相同的数组。

我们还将创建两个列表,用于经度和纬度。这些值超出了数据的经度和纬度值,并允许我们在数据点周围有填充。

longitude = [1.5, 4.5]latitude = [57.5, 62]x = np.linspace(longitude[0], longitude[1], zstar.shape[1])y = np.linspace(latitude[0], latitude[1], zstar.shape[0])

当使用matplotlib时,我们可以使用imshow显示此类数据。

即使Plotly也有一个imshow图,但我们无法(据我所知,截至撰写本文的时候)控制图表的范围。这意味着我们无法指定轴的起始点的值。

因此,为了显示我们的数据网格,我们可以切换到使用Plotly的热力图

热力图基于其值对我们网格中的每个数据单元格进行着色。您可以在我的Seaborn文章中了解更多关于热力图的信息。

我们可以使用以下代码使用Plotly Graph Objects创建我们的热力图。

fig = go.Figure()fig.add_trace(go.Heatmap(z=zstar, x=x, y=y))fig.update_xaxes(range=(longitude[0], longitude[1]))fig.update_yaxes(range=(latitude[0], latitude[1]))fig.update_layout(autosize=False, width=800, height=800)fig.show()

首先,我们创建一个图形对象,然后向其中添加一个trace。这个trace包含我们的xy位置数据,以及由kriging创建的网格(zstar)。

我们还将图形的大小设置为800 x 800,这将为我们在Jupyter笔记本中使用足够大的绘图。

运行上述代码后,我们获得了带有所有数据值和正确范围内的轴的热力图。

Plotly Graph Objects heatmap showing variations within our Acoustic Compressional Slowness measurement across the Norwegian Continental Shelf. Image by the author.

这个图的好处是我们可以在上面悬停并查看任何点的值。此外,Plotly允许我们放大某些地方以更仔细地查看。

即使上面的图很棒,我们也缺少一些会帮助读者的其他信息,例如我们的井位置以及我们的轴标签。

要添加我们的井位置,我们需要添加第二个trace。这次使用go.scatter()并传递我们数据框架的纬度和经度值。我们也可以通过为我们的标记添加一个字典来控制这些点的外观。在这个例子中,我们将它们设置为黑色。

fig = go.Figure()fig.add_trace(go.Heatmap(z=zstar, x=x, y=y))# 添加井位信息fig.add_trace(go.Scatter(x=df['LON'], y=df['LAT'],                         mode='markers', marker=dict(color='black')))fig.update_xaxes(range=(longitude[0], longitude[1]))fig.update_yaxes(range=(latitude[0], latitude[1]))fig.update_layout(autosize=False, width=800, height=800)fig.show()
Plotly Graph Objects 热力图显示挪威大陆架上声波压缩慢度测量中的测量位置(井口)和变化。作者提供的图片。

现在,我们可以看到井位信息,但是,如果我们悬停在标记上,我们只会得到纬度和经度值。这在一定程度上是有用的,但是我们想知道标记代表哪个井,以及为该井测量了多少DTC值。

为了解决这个问题,我们可以在数据框中直接创建我们的悬停文本作为新列。如果我们以后要在其他图表中使用它,这会很有用。

fig = go.Figure()fig.add_trace(go.Heatmap(z=zstar, x=x, y=y,                          colorbar=dict(title='DTC (us/ft)',                                       title_font=dict(size=18))))df['hover_text'] = df.apply(lambda row: f"""<b>{row['WELL']}</b>                            <br>Latitude: {row['LAT']}                            <br>Longitude: {row['LON']}                            <br>Log Value: {round(row['DTC_MEAN'], 2)}""",                             axis=1)fig.add_trace(go.Scatter(x=df['LON'], y=df['LAT'],                         mode='markers', marker=dict(color='black'),                        name='Wells', text=df['hover_text'], hoverinfo='text', showlegend=True))fig.update_xaxes(range=(longitude[0], longitude[1]),                  title='Longitude')fig.update_yaxes(range=(latitude[0], latitude[1]),                  title='Latitude')fig.update_layout(autosize=False, width=800, height=800,                   legend=dict(x=1, y=0, xanchor='auto', yanchor='auto',                               bgcolor='rgba(255, 255, 255, 0.5)'))fig.show()

当我们运行上面的代码时,我们得到以下图表。

Plotly Graph Objects 带有附加交互性的热力图。这个图表显示了挪威大陆架上声波压缩慢度的测量位置(井口)和变化。作者提供的图片。

现在,当我们悬停在任何一个井口上时,我们将得到井名,然后是纬度和经度,以及记录值。在这种情况下,我们显示了声波压缩慢度。

摘要

在这个简短的教程中,我们看到了如何超越简单和静态的matplotlib图表,展示我们测量变化的状态。Plotly提供的额外功能和交互性,使其成为可视化井测量空间变化的绝佳选择。

额外的交互性使我们能够确定每个点所代表的井,该位置测量的值是多少,并解释没有直接测量的网格的值。

使用的数据集

本文中使用的数据集是Xeek和FORCE 2020(Bormann等人,2020)举办的机器学习比赛的训练数据集的子集。它根据挪威政府的NOLD 2.0许可证发布,在此处可以找到有关许可证的详细信息:挪威政府开放数据许可证(NLOD)2.0。完整的数据集可以在此处访问。

该数据集的完整参考文献如下:

Bormann, Peter, Aursand, Peder, Dilib, Fahad, Manral, Surrender, & Dischington, Peter. (2020). FORCE 2020井壁测井和岩相数据集用于机器学习比赛[数据集]. Zenodo. http://doi.org/10.5281/zenodo.4351156

感谢您的阅读。在您离开之前,您应该订阅我的内容并在收件箱中获取我的文章。您可以在这里进行订阅!

其次,您可以通过注册会员来获得完整的小猪AI体验,支持数千名其他作家和我。它每月只需花费您5美元,您就可以完全访问所有fantastic小猪AI文章,以及赚钱的机会。

如果您使用我的链接您将直接支持我一部分费用,而不会增加您的费用。如果您这样做,非常感谢您的支持。