【问题标题】:Adding GeoJSON contours as layers on Plotly Density_Mapbox在 Plotly Density_Mapbox 上添加 GeoJSON 等高线作为图层
【发布时间】:2021-11-25 08:13:58
【问题描述】:

我想在plotly density_mapbox 地图上添加天气等高线,但不确定必要的步骤。

首先,我创建了一个matplotlib 等高线图来可视化数据。

然后,我使用geojsoncontour 从上述matplotlib 等高线图创建一个geojson 文件。

我现在想做的是在与density_mapbox 相同的地图中绘制等高线。

geojson和包含数据的.csv文件可以在here找到。

关于 .csv 文件,“Rand_Data”是进入density_mapbox 图的数据,“Rain_in”是用于生成等高线的数据。

数据链接:https://github.com/jkiefn1/Contours_and_plotly

创建 Mapbox:

# Create the static figure
fig = px.density_mapbox(df
                        ,lat='lat'
                        ,lon='long'
                        ,z='Rand_Data'
                        ,hover_data={
                                     'lat':True # remove from hover data
                                     ,'long':True # remove from hover data
                                     ,col:True
                                    }
                        ,center=dict(lat=38.5, lon=-96)
                        ,zoom=3
                        ,radius=30
                        ,opacity=0.5
                        ,mapbox_style='open-street-map'
                        ,color_continuous_scale='inferno'
                       )

fig.show()

创建matplotlib等高线图并生成geojson文件

# Load in the DataFrame
path = r'/Users/joe_kiefner/Desktop/Sample_Data.csv'
df = pd.read_csv(path, index_col=[0])
data = []

# Define rain levels to be contours in geojson
levels = [0.25,0.5,1,2.5,5,10]

colors = ['royalblue',  'cyan',  'lime',  'yellow', 'red']
vmin   = 0
vmax   = 1
cm     = branca.colormap.LinearColormap(colors, vmin=vmin, vmax=vmax).to_step(len(levels))


x_orig = (df.long.values.tolist())
y_orig = (df.lat.values.tolist())
z_orig = np.asarray(df['Rain_in'].values.tolist())


x_arr          = np.linspace(np.min(x_orig), np.max(x_orig), 500)
y_arr          = np.linspace(np.min(y_orig), np.max(y_orig), 500)
x_mesh, y_mesh = np.meshgrid(x_arr, y_arr)

xscale = df.long.max() - df.long.min()
yscale = df.lat.max() - df.lat.min()

scale = np.array([xscale, yscale])


z_mesh = griddata((x_orig, y_orig), z_orig, (x_mesh, y_mesh), method='linear')


sigma = [5, 5]
z_mesh = sp.ndimage.filters.gaussian_filter(z_mesh, sigma, mode='nearest')

# Create the contour
contourf = plt.contourf(x_mesh, y_mesh, z_mesh, levels, alpha=0.9, colors=colors, 
                        linestyles='none', vmin=vmin, vmax=vmax)

# Convert matplotlib contourf to geojson
geojson = geojsoncontour.contourf_to_geojson(
    contourf=contourf,
    min_angle_deg=3,
    ndigits=2,
    unit='in',
    stroke_width=1,
    fill_opacity=0.3)
d = json.loads(geojson)
len_features=len(d['features'])
if not data:
    data.append(d)
else:
    for i in range(len(d['features'])):
         data[0]['features'].append(d['features'][i])
            
with open('/path/to/Sample.geojson', 'w') as f:
   dump(geojson, f)

【问题讨论】:

    标签: python matplotlib plotly geojson contour


    【解决方案1】:
    • 有两个核心选项
      1. 添加为图层https://plotly.com/python/mapbox-layers/
      2. 添加为等值线轨迹https://plotly.com/python/mapbox-county-choropleth/
      3. layers-legend - 与 layers 选项相同,通过向图形添加额外的轨迹来创建图例
    • 这两个选项都在下面进行了编码。更改OPTION 的值以在它们之间切换
    • 图层表示没有图例或悬停文本
    • choropleth 这些是存在的,移动了 colorbar,因此它不会与图例重叠。更多的图例和悬停文本需要...
    import json, requests
    import pandas as pd
    import geopandas as gpd
    import plotly.express as px
    
    txt = requests.get(
        "https://raw.githubusercontent.com/jkiefn1/Contours_and_plotly/main/Sample.geojson"
    ).text
    js = json.loads(json.loads(txt))
    
    df = pd.read_csv(
        "https://raw.githubusercontent.com/jkiefn1/Contours_and_plotly/main/Sample_Data.csv"
    )
    
    col = "Rand_Data"
    fig = px.density_mapbox(
        df,
        lat="lat",
        lon="long",
        z="Rand_Data",
        hover_data={
            "lat": True,  # remove from hover data
            "long": True,  # remove from hover data
            col: True,
        },
        center=dict(lat=38.5, lon=-96),
        zoom=3,
        radius=30,
        opacity=0.5,
        mapbox_style="open-street-map",
        color_continuous_scale="inferno",
    )
    
    OPTION = "layers-legend"
    if OPTION[0:6]=="layers":
        fig.update_traces(legendgroup="weather").update_layout(
            mapbox={
                "layers": [
                    {
                        "source": f,
                        "type": "fill",
                        "color": f["properties"]["fill"],
                        "opacity": f["properties"]["fill-opacity"],
                    }
                    for f in js["features"]
                ],
            }
        )
        
        if OPTION=="layers-legend":
            # create a dummy figure to create a legend for the geojson
            dfl = pd.DataFrame(js["features"])
            dfl = pd.merge(
                dfl["properties"].apply(pd.Series),
                dfl["geometry"].apply(pd.Series)["coordinates"].apply(len).rename("len"),
                left_index=True,
                right_index=True,
            )
            figl = px.bar(
                dfl.loc[dfl["len"].gt(0)],
                color="title",
                x="fill",
                y="fill-opacity",
                color_discrete_map={cm[0]: cm[1] for cm in dfl.loc[:, ["title", "fill"]].values},
            ).update_traces(visible="legendonly")
    
            fig.add_traces(figl.data).update_layout(
                xaxis={"visible": False}, yaxis={"visible": False}, coloraxis={"colorbar":{"y":.25}}
            )
    else:
        gdf = gpd.GeoDataFrame.from_features(js)
        gdf = gdf.loc[~gdf.geometry.is_empty]
        cmap = {
            list(d.values())[0]: list(d.values())[1]
            for d in gdf.loc[:, ["title", "fill"]].apply(dict, axis=1).tolist()
        }
        fig2 = px.choropleth_mapbox(
            gdf,
            geojson=gdf.geometry,
            locations=gdf.index,
            color="title",
            color_discrete_map=cmap,
            opacity=.3
        )
        fig.add_traces(fig2.data).update_layout(coloraxis={"colorbar":{"y":.25}})
        
        
    fig
    

    痕迹

    【讨论】:

    • Rob,有没有使用图层方法添加某种图例?我发现使用上面的“图层”方法将“类型”设置为“线”,覆盖数据可以使可视化更加清晰。
    • 已更新 - 在情节图例中是从跟踪自动生成的。已合成额外的痕迹,以便将降雨项目插入图例中
    猜你喜欢
    • 2018-11-19
    • 2018-08-31
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 2020-05-22
    • 2021-11-30
    相关资源
    最近更新 更多