我在matplotlib中看到过关于绘制两个六进制 map 之间差异的帖子.我找不到任何东西执行相同的过程,除了Plotly的六进制 map 盒子图.如果我有两个独立的六进制子图(t, y),是否有可能产生一个减go ty之间的差异的图?

import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import plotly.figure_factory as ff
from plotly.subplots import make_subplots

data = pd.DataFrame({
   'Cat': ['t','y','y','t','t','t','t','y','y','y','t','y'],
   'LAT': [5,6,7,5,6,7,5,6,7,5,6,7],
   'LON': [10,11,12,10,11,12,10,11,12,10,11,12],
   })

data = pd.concat([data]*5)

df_t = data[data['Cat'] == 't']
df_y = data[data['Cat'] == 'y']

fig = make_subplots(
    rows = 2, 
    cols = 1, 
    subplot_titles = ('t', 'y'),
    specs = [[{"type": "choroplethmapbox"}], [{"type": "choroplethmapbox"}]],
    vertical_spacing = 0.05,
    horizontal_spacing = 0.05
    )

fig2 = ff.create_hexbin_mapbox(data_frame=df_t,
                           lat="LAT", lon="LON",
                           nx_hexagon=5,
                           opacity=0.5,
                           labels={"color": "Point Count"},
                           mapbox_style='carto-positron',
                          )

fig3 = ff.create_hexbin_mapbox(data_frame=df_y,
                           lat="LAT", lon="LON",
                           nx_hexagon=5,
                           opacity=0.5,
                           labels={"color": "Point Count"},
                           mapbox_style='carto-positron',
                          )


fig.add_trace(fig2.data[0], row=1,col=1)
fig.update_mapboxes(zoom=4, style='carto-positron')
fig.add_trace(fig3.data[0], row=2,col=1)
fig.update_mapboxes(zoom=4, style='carto-positron')

fig.update_layout(height=600, margin=dict(t=20,b=0,l=0,r=0))
fig.show()

预期输出:

t的左下框有15分,y有5分.所以总分是10.中间的框都有10分,所以结果是0.右上角t赔5,y赔15,得-10.但我会将vmin设置为0,以确保没有负值.

enter image description here

编辑2:

如果我使用不同大小的数组更改输入数据,并将MIN_COUNT=1作为参数,则会返回错误.

data = pd.DataFrame({
       'Cat': ['t','y','y','t','t','t','t','y','y','y','t','y','y'],
       'LAT': [5,6,7,5,6,7,5,6,7,5,6,7,8],
       'LON': [10,11,12,10,11,12,10,11,12,10,11,12,8],
       })

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last) /var/folders/bf/09nyl3td65j2lty5m7138ndw0000gn/T/ipykernel_78237/2142200526.py in <module>
     47 
     48 fig = go.Figure(fig2)
---> 49 fig.data[0]['z'] = (fig2.data[0]['z'] - fig3.data[0]['z']).clip(min=0)
     50 cmax, cmin = max(fig.data[0]['z']), min(fig.data[0]['z'])
     51 

ValueError: operands could not be broadcast together with shapes (3,) (4,) 

推荐答案

由于在创建图形时以绘图方式确定每个十六进制数,因此您需要访问fig2fig3中的计数数据.

下面是存储在fig2.data[0]['z']内的数组:

array([15.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  5.,  0.,  0.,
        0.,  0.,  0.,  0.,  0., 10.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

我们可以将fig设置为图2的副本,通过获取图2和图3中的计数数组之间的差值(并将其剪裁为0)来创建新数组,并将fig.data[0]['z']设置为该新array.您还需要相应地更新colorbar的最小值和最大值.

import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import plotly.figure_factory as ff
from plotly.subplots import make_subplots

data = pd.DataFrame({
   'Cat': ['t','y','y','t','t','t','t','y','y','y','t','y'],
   'LAT': [5,6,7,5,6,7,5,6,7,5,6,7],
   'LON': [10,11,12,10,11,12,10,11,12,10,11,12],
   })

data = pd.concat([data]*5)

df_t = data[data['Cat'] == 't']
df_y = data[data['Cat'] == 'y']

# fig = make_subplots(
#     rows = 2, 
#     cols = 1, 
#     subplot_titles = ('t', 'y'),
#     specs = [[{"type": "choroplethmapbox"}], [{"type": "choroplethmapbox"}]],
#     vertical_spacing = 0.05,
#     horizontal_spacing = 0.05
#     )

fig2 = ff.create_hexbin_mapbox(data_frame=df_t,
                           lat="LAT", lon="LON",
                           nx_hexagon=5,
                           opacity=0.5,
                           labels={"color": "Point Count"},
                           mapbox_style='carto-positron',
                          )

fig3 = ff.create_hexbin_mapbox(data_frame=df_y,
                           lat="LAT", lon="LON",
                           nx_hexagon=5,
                           opacity=0.5,
                           labels={"color": "Point Count"},
                           mapbox_style='carto-positron',
                          )

fig = go.Figure(fig2)
fig.data[0]['z'] = (fig2.data[0]['z'] - fig3.data[0]['z']).clip(min=0)
cmax, cmin = max(fig.data[0]['z']), min(fig.data[0]['z'])

fig.update_mapboxes(zoom=6, style='carto-positron')
fig.update_layout(height=600, margin=dict(t=20,b=0,l=0,r=0))
fig.update_coloraxes(cmax=cmax, cmin=cmin)
fig.show()

enter image description here

更新:在fig2.data[0]['z']fig3.data[0]['z']是不同长度的数组的情况下,您需要填充较短的array.我假设填充值为零,并且我们将以相同的方式计算差异.

使用您编辑的样本数据,我们得到图2.data[0][‘z’]是array([15., 5., 10.]),而图3.data[0][‘z’]是array([10., 15., 5., 5.]).因此,我们用0填充数组([15.,5.,10.])以匹配另一个数组的长度,这意味着我们使用array([15., 5., 10., 0.]).我添加了一些代码来填充较短的数组,然后以与前面相同的方式计算差值和剪裁负值.

import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import plotly.figure_factory as ff
from plotly.subplots import make_subplots

# data = pd.DataFrame({
#    'Cat': ['t','y','y','t','t','t','t','y','y','y','t','y'],
#    'LAT': [5,6,7,5,6,7,5,6,7,5,6,7],
#    'LON': [10,11,12,10,11,12,10,11,12,10,11,12],
#    })

data = pd.DataFrame({
       'Cat': ['t','y','y','t','t','t','t','y','y','y','t','y','y'],
       'LAT': [5,6,7,5,6,7,5,6,7,5,6,7,8],
       'LON': [10,11,12,10,11,12,10,11,12,10,11,12,8],
       })

data = pd.concat([data]*5)

df_t = data[data['Cat'] == 't']
df_y = data[data['Cat'] == 'y']

fig2 = ff.create_hexbin_mapbox(data_frame=df_t,
                           lat="LAT", lon="LON",
                           nx_hexagon=5,
                           opacity=0.5,
                           labels={"color": "Point Count"},
                           mapbox_style='carto-positron',
                           min_count=1
                          )

fig3 = ff.create_hexbin_mapbox(data_frame=df_y,
                           lat="LAT", lon="LON",
                           nx_hexagon=5,
                           opacity=0.5,
                           labels={"color": "Point Count"},
                           mapbox_style='carto-positron',
                           min_count=1,
                          )

fig = go.Figure(fig2)
fig2_values, fig3_values = fig2.data[0]['z'], fig3.data[0]['z']

## we pad whichever figure has fewer z values
if len(fig2_values) < len(fig3_values):
   pad_length = len(fig3_values) - len(fig2_values)
   fig2_values = np.pad(fig2_values, (0, pad_length), 'constant')
elif len(fig2_values) > len(fig3_values):
   pad_length = len(fig2_values) - len(fig3_values)
   fig3_values = np.pad(fig3_values, (0, pad_length), 'constant')
else:
   pass

fig.data[0]['z'] = (fig2_values - fig3_values).clip(min=0)
cmax, cmin = max(fig.data[0]['z']), min(fig.data[0]['z'])

fig.update_mapboxes(zoom=6, style='carto-positron')
fig.update_layout(height=600, margin=dict(t=20,b=0,l=0,r=0))
fig.update_coloraxes(cmax=cmax, cmin=cmin)
fig.show()

enter image description here

Python相关问答推荐

调试回归无法解决我的问题

我可以使用极点优化这个面向cpu的pandas代码吗?

Pandas read_jsonfuture 警告:解析字符串时,to_datetime与单位的行为已被反对

Plotly:如何更改Heatmap中彩色条的勾选文本

Tkinter滑动条标签.我不确定如何删除滑动块标签或更改其文本

强制venv在bin而不是收件箱文件夹中创建虚拟环境

Python无法在已导入的目录中看到新模块

理解Python的二分库:澄清bisect_left的使用

try 在树叶 map 上应用覆盖磁贴

如何使用html从excel中提取条件格式规则列表?

Pandas - groupby字符串字段并按时间范围 Select

无法使用requests或Selenium抓取一个href链接

实现自定义QWidgets作为QTimeEdit的弹出窗口

形状弃用警告与组合多边形和多边形如何解决

如何使regex代码只适用于空的目标单元格

在极中解析带有数字和SI前缀的字符串

如何创建引用列表并分配值的Systemrame列

为什么Python内存中的列表大小与文档不匹配?

pandas fill和bfill基于另一列中的条件

统计numpy. ndarray中的项目列表出现次数的最快方法