0

I wish to build a scatter plot but using 2 drop down where I can switch between variables one for x axis and the other for y axis(e.g Total tests and Total cases, or Recent cases and Total cases), i have tried building off a solution i found by replacing

cols_dd = ["Total tests", "Total cases", "Total deaths"]

for value in cols_dd: 

with

cols_dd = {"Total tests":"Total cases", "Total deaths":"Recent cases", "Population":"Total vaccinations"}

k,v in cols_dd.items(): 

and the using k and v in place of values but it returns an error ('dict_keys' object is not subscriptable)

can someone please share a way to achive this, here is my code.

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

# get OWID data
df = pd.read_csv(
    "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/latest/owid-covid-latest.csv"
)
# rename columns as sample code uses other names....
df = df.rename(
    columns={
        "location": "Location",
        "iso_code": "Iso code",
        "total_tests": "Total tests",
        "people_vaccinated_per_hundred": "Vaccines",
        "new_cases": "Recent cases",
        "total_cases": "Total cases",
        "total_deaths": "Total deaths",
        "total_vaccinations": "Total vaccinations",
        "people_vaccinated": "People vaccinated",
        "population": "Population",
        "total_boosters": "Vaccination policy",
    }
).fillna(0)

cols_dd = {"Total tests":"Total cases", "Total deaths":"Recent cases", "Population":"Total vaccinations"}


fig = go.Figure()

for k,v in cols_dd.items():
    fig.add_traces(px.scatter(df, x=k, y=v, color="Location",
            hover_data={
                "Iso code": False,
                "Vaccines": True,
                "Total tests": ": ,0.f",
                "Recent cases": ": ,0.f",
                "Total cases": ": ,0.f",
                "Total deaths": ": ,0.f",
                "Total vaccinations": ": ,0.f",
                "People vaccinated": ": ,0.f",
                "Population": ": ,0.f",
                "Vaccination policy": ": 0.f",
            },
            color_continuous_scale="spectral_r",
            hover_name="Location",
        )
        .update_traces(visible=(k == list(cols_dd.keys()[0]))
        .data
    ))


fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": value,
                    "method": "update",
                    "args": [
                        {"visible": [v2 == value for v2 in cols_dd]},
                        {"title": f"<b>{k}</b> vs <b>{v}</b>"},
                    ],
                }
                for k in cols_dd
            ]
        }
    ]
)
Rich
  • 9
  • 6

1 Answers1

1

You can build all the combinations of variables as both traces and a menu.

cols_dd = ["Total tests", "Total cases", "Total deaths"]
hd = {
    "Iso code": False,
    "Vaccines": True,
    "Total tests": ": ,0.f",
    "Recent cases": ": ,0.f",
    "Total cases": ": ,0.f",
    "Total deaths": ": ,0.f",
    "Total vaccinations": ": ,0.f",
    "People vaccinated": ": ,0.f",
    "Population": ": ,0.f",
    "Vaccination policy": ": 0.f",
}

# px.scatter(df, x="Total cases", y="Total deaths", hover_data=hd, hover_name="Location")
fig = go.Figure()
for k, v in itertools.combinations(cols_dd, 2):
    figt = px.scatter(df, x=k, y=v, hover_data=hd, hover_name="Location").update_traces(
        visible=False
    )
    fig = fig.add_traces(figt.data)

fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": f"{k} - {v}",
                    "method": "update",
                    "args": [
                        {
                            "visible": [
                                (k2 == k and v2 == v)
                                for k2, v2 in itertools.combinations(cols_dd, 2)
                            ]
                        },
                        {"title": f"<b>{k} - {v}</b>"},
                    ],
                }
                for k, v in itertools.combinations(cols_dd, 2)
            ]
        }
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
).update_traces(visible=True, selector=0)

independent

cols_dd = ["Total tests", "Total cases", "Total deaths"]

fig = go.Figure(
    go.Scatter(
        x=df[np.random.choice(cols_dd, 1)[0]],
        y=df[np.random.choice(cols_dd, 1)[0]],
        hovertemplate='x: %{x} <br>y: %{y}',
        mode="markers"
    )
)

fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": f"x - {x}",
                    "method": "update",
                    "args": [
                        {"x": [df[x]]},
                        {"xaxis": {"title": x}},
                    ],
                }
                for x in cols_dd
            ]
        },
        {
            "buttons": [
                {
                    "label": f"y - {x}",
                    "method": "update",
                    "args": [{"y": [df[x]]}, {"yaxis": {"title": x}}],
                }
                for x in cols_dd
            ],
            "y": 0.9,
        },
    ],
    margin={"l": 0, "r": 0, "t": 25, "b": 0},
)
fig
Rob Raymond
  • 29,118
  • 3
  • 14
  • 30
  • Thanks a lot Rob, I have accepted both answers but unfortunately I do not have enough reputation to make it count, but as soon as i do, i will accept them both. – Rich Sep 19 '21 at 16:12
  • I was hoping for a method that has two independent buttons for each axis. – Rich Sep 19 '21 at 16:22
  • it's all coding... same pattern – Rob Raymond Sep 19 '21 at 18:46
  • done - as noted it's just coding only 10 mins – Rob Raymond Sep 19 '21 at 19:10
  • Thanks a lot Rob, really thanks to you and every other person out here offering sincere help to those in need, i cant say thank you enough, I have learnt so much playing around with your solutions. This worked for me and I have been able to tweak and re-use for other purposes. – Rich Sep 19 '21 at 21:47
  • i wasn't supposed to use the hover data on the scatter plot, when i remove that the x and y axis stay constant and don't update on the hover displays as the buttons are selected – Rich Sep 20 '21 at 07:50
  • https://meta.stackexchange.com/questions/4421/can-new-users-upvote-answers-to-their-questions – Rob Raymond Sep 20 '21 at 08:03
  • https://stackoverflow.com/questions/69247915/update-plotly-color-discrete-map-on-choropleth-map-using-buttons – Rich Sep 20 '21 at 08:08
  • `fig = go.Figure( go.Scatter( x=df[np.random.choice(cols_dd, 1)[0]], y=df[np.random.choice(cols_dd, 1)[0]], hovertemplate='x: %{x}
    y: %{y}', mode="markers" ) ) ` just create a simpler figure to hold what you want
    – Rob Raymond Sep 20 '21 at 08:11