python - `line_mapbox` 和第二个图之间的交叉过滤

标签 python plotly plotly-dash

我是 plotly 新手,希望可视化正在运行的事件中的数据。假设我有一个包含以下列的数据框:

df = pd.DataFrame(
    {
        "time": time,
        "latitude": latitude,
        "longitude": longitude,
        "altitude": altitude,
        "heartrate": heartrate,
    }
)

我想要两个图,一个是绘制纬度与经度的 map ,另一个是绘制时间与心率(或海拔)的图。 但我希望这两个 plotly 能够联系起来。因此,如果我在第二个图中选择 y 范围,我只想在 map 上看到那些纬度-经度对,其中它们各自的时间值位于我在第二个图中选择的范围内。同样,如果我在 map 上选择点,我想查找该点选择中的最小和最大时间值,并希望仅在第二个图中绘制这些点。

这是带有一些虚拟数据的屏幕截图: enter image description here

我不知道如何链接这两个图,所以非常感谢您的帮助! 源码如下:

import dash
import dash_core_components as dcc
import dash_html_components as html
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objs as go

app = dash.Dash()
server = app.server

np.random.seed(0)
# Random dummy data
n = 100
time = np.linspace(0, 1, n)
latitude = 50 + 0.001 * np.cumsum(np.random.randn(n))
longitude = 2 + 0.001 * np.cumsum(np.random.randn(n))
altitude = (time - 0.5) ** 2
heartrate = 100 + np.cumsum(np.random.randn(n))
df = pd.DataFrame(
    {
        "time": time,
        "latitude": latitude,
        "longitude": longitude,
        "altitude": altitude,
        "heartrate": heartrate,
    }
)

fig = px.line_mapbox(df, lat="latitude", lon="longitude", zoom=12, height=800)
fig.update_layout(mapbox_style="stamen-terrain")


app.layout = html.Div(
    [
        html.Div(
            [
                dcc.Graph(id="mymap", figure=fig),
            ]
        ),
        html.Div(
            [
                dcc.Graph(id="time-series"),
                dcc.Dropdown(
                    id="column",
                    options=[
                        {"label": i, "value": i} for i in ["altitude", "heartrate"]
                    ],
                    value="altitude",
                ),
            ]
        ),
    ]
)


def lineplot(x, y, title="", axis_type="Linear"):
    return {
        "data": [go.Scatter(x=x, y=y, mode="lines")],
    }


@app.callback(
    dash.dependencies.Output("time-series", "figure"),
    [
        dash.dependencies.Input("column", "value"),
    ],
)
def update_timeseries(column):
    x = df["time"]
    y = df[column]
    return lineplot(x, y)


app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})


if __name__ == "__main__":
    app.run_server(debug=True)

最佳答案

这是一个选项,我将行 map 框更改为散点图框,以便您可以进行框选择

并查看 map 中所选数据的代码和折线图中的过滤器的代码

import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output, State
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objs as go

app = dash.Dash()
server = app.server

np.random.seed(0)
# Random dummy data
n = 100
time = np.linspace(0, 1, n)
latitude = 50 + 0.001 * np.cumsum(np.random.randn(n))
longitude = 2 + 0.001 * np.cumsum(np.random.randn(n))
altitude = (time - 0.5) ** 2
heartrate = 100 + np.cumsum(np.random.randn(n))
df = pd.DataFrame(
    {
        "time": time,
        "latitude": latitude,
        "longitude": longitude,
        "altitude": altitude,
        "heartrate": heartrate,
    }
)

fig = go.Figure(go.Scattermapbox(
    mode = "markers+lines",
    lon = df.longitude,
    lat = df.latitude,
    marker = {'size': 10}))
fig.update_layout(
    mapbox={
        'style': "stamen-terrain",
        'center' : dict(
            lat=50,
            lon=2
        ),
        'zoom': 12})


app.layout = html.Div(
    [
        html.Div(
            [
                dcc.Graph(id="mymap", figure=fig),
            ]
        ),
        html.Div(
            [
                dcc.Graph(id="time-series"),
                dcc.Dropdown(
                    id="column",
                    options=[
                        {"label": i, "value": i} for i in ["altitude", "heartrate"]
                    ],
                    value="altitude",
                ),
            ]
        ),
    ]
)


def lineplot(x, y, title="", axis_type="Linear"):
    return {
        "data": [go.Scatter(x=x, y=y, mode="lines")],
    }


@app.callback(
    Output("time-series", "figure"),
    [
        Input("column", "value"),
        Input("mymap", "selectedData")
    ],
)
def update_timeseries(column, selectedData):
    # add filter data by selectData points
    temp = df
    if selectedData is not None:
        sel_data = pd.DataFrame(selectedData['points'])
        temp = df.loc[(df.latitude.isin(sel_data.lat)) & (df.longitude.isin(sel_data.lon))]
    x = temp["time"]
    y = temp[column]
    return lineplot(x, y)


app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})


if __name__ == "__main__":
    app.run_server(debug=True)

enter image description here

关于python - `line_mapbox` 和第二个图之间的交叉过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68988634/

相关文章:

python - 调用 pexpect.spawn 时,生成的程序会立即开始执行吗?

Python/Django - *args 作为列表

python - 仅实时更新 Dash/plotly 中的数据

python - 在 Python + Dash 中禁用 "Submit"按钮 30 秒

python - 如何在多个条件下填充数据框中新列的值

python - 如何覆盖 django 文件?

python - plotly 中的相机位置如何工作

python - 将 plot.ly JSON 保存到文件

flask - 不同破折号 session 的唯一 session ID

python - 模块未找到错误: No module named '_brotli' when trying to install dash