简体   繁体   English

如何将 OLS 趋势线添加到使用 updatemenus 显示数据子集的 plotly 散点图 plot 图形 object?

[英]How to add a OLS trendline to a plotly scatter plot graph object that uses updatemenus to display subsets of data?

I am trying to make a plotly scatter plot with a OLS trendline and provide a dropdown menu what let's the user pick from a different of X's and Y's.我正在尝试使用 OLS 趋势线制作 plotly 散点图 plot 并提供一个下拉菜单,让用户从不同的 X 和 Y 中进行选择。 The plot almost works. plot 几乎可以正常工作。 Where the first figure produced by the code has the data and the trendline, but when you choose an option from the drop down the trendline instead connects every done with another dot, seeminly in the order the coordinated appear in the data frame.代码生成的第一个图形具有数据和趋势线,但是当您从下拉列表中选择一个选项时,趋势线反而将每个完成的点与另一个点连接起来,似乎按照协调出现在数据框中的顺序。 ` `

The code:代码:

import plotly.graph_objects as go
import plotly.express as px
#making a figure
fig = go.Figure()
x1 = df['crttotal']
x2 = df['nfcc_mean']
x3 = df['bficonmean']
x4 = df['bfiopmean']

y1 = df['avg_misperception_score']
y2 = df['avg_ambiguous_score']

fig = px.scatter(df, x=x2, y=y1, trendline="ols", trendline_scope="overall")

#making the dropdown
fig.update_layout(
    updatemenus=[
        go.layout.Updatemenu(
            type="dropdown",
            buttons=list([

                dict(label="NFCC vs Misperception",
                     method="update",
                     args=[{"x": [x2], "y": [y1], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "NFCC vs Misperception"}]),
                dict(label="CRT vs Misperception",
                     method="update",
                     args=[{"x": [x1], "y": [y1], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "CRT vs Misperception"}]),
                dict(label="bficonmean vs Misperception",
                     method="update",
                     args=[{"x": [x3], "y": [y1], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "bficonmean vs Misperception"}]),
                dict(label="bfiopmean vs Misperception",
                     method="update",
                     args=[{"x": [x4], "y": [y1], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "bfiopmean vs Misperception"}]),

                dict(label="CRT vs Ambiguity",
                     method="update",
                     args=[{"x": [x1], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "CRT vs Ambiguity"}]),
                dict(label="NFCC vs Ambiguity",
                     method="update",
                     args=[{"x": [x2], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "NFCC vs Ambiguity"}]),
                dict(label="bficonmean vs Ambiguity",
                     method="update",
                     args=[{"x": [x3], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "bficonmean vs Ambiguity"}]),
                dict(label="bfiopmean vs Ambiguity",
                     method="update",
                     args=[{"x": [x4], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "bfiopmean vs Ambiguity"}])

            ])
        )
    ]
)

#set the title
fig.update_layout(title="Dropdown")

fig.show()

the Data数据

   crttotal  nfcc_mean  bficonmean  bfiopmean  avg_misperception_score  \
0         3       2.87       3.875      3.000                   -0.062   
1         0       3.53       3.625      3.125                   -0.235   
2         0       3.80       4.000      3.000                    0.077   
3         0       3.73       3.750      3.500                    0.067   
4         2       3.87       3.125      3.000                    0.368   
5         0       3.47       2.750      3.500                   -0.200   
6         0       4.33       3.625      3.625                   -0.200   
7         0       4.13       3.250      3.125                   -0.500   
8         0       4.73       3.250      3.250                   -0.643   
9         3       5.20       3.750      2.750                    0.000   

   avg_ambiguous_score  
0                 2.60  
1                 2.10  
2                 3.35  
3                 2.55  
4                 2.90  
5                 2.80  
6                 2.85  
7                 3.30  
8                 3.15  
9                 2.70  

What I was expecting (and what initially shows when i run the above code) enter image description here我所期待的(以及我运行上述代码时最初显示的内容)在此处输入图像描述

What I get when I change select an option from my dropdown: enter image description here当我从下拉列表中更改 select 选项时得到的结果:在此处输入图片描述

** EDIT: ** ** 编辑: **

"AS DISCUSSED IN COMMENT" your solution worked, but the trenline info box always reads with the same equation: avg_misperception = -.004*crttotal +.073 “正如评论中讨论的那样”您的解决方案有效,但 trenline 信息框始终使用相同的等式读取:avg_misperception = -.004*crttotal +.073

How do I get it so that the info box also updates?我如何获得它以便信息框也更新? [![Trendline info box does not match graph variables][1]][1] [![Trendline info box does not match graph variables][2]][2] [![趋势线信息框与图形变量不匹配][1]][1] [![趋势线信息框与图形变量不匹配][2]][2]

Seriously, you're amazing.说真的,你太棒了。 TY so much for providing such a clear answer.非常感谢 TY 提供了如此明确的答案。 [1]: https://i.stack.imgur.com/zPxBL.png [2]: https://i.stack.imgur.com/fy7m6.png [1]: https://i.stack.imgur.com/zPxBL.png [2]: https://i.stack.imgur.com/fy7m6.png

EDIT: the same is the case for the data point labels.编辑:数据点标签也是如此。 When you hover over a data their values are labeled as "crttotal" and "avg_misperception_score."当您对数据进行 hover 时,它们的值被标记为“crttotal”和“avg_misperception_score”。 I assume I need to update something in the Layout Attribute - https://plotly.com/python/figure-structure/#the-toplevel-layout-attribute ?我假设我需要更新布局属性中的某些内容 - https://plotly.com/python/figure-structure/#the-toplevel-layout-attribute trying to figure it out on my own as well - just new to plotly.我也想自己弄明白——刚接触 plotly。

Short answer简答

Add more data in the lists for "x" and "y" in {"x": [x2, <regression x>], "y": [y1, <regression y>], ...} to display a trendline.{"x": [x2, <regression x>], "y": [y1, <regression y>], ...}的列表中为"x""y"添加更多数据以显示趋势线. Of course, you'll need to calculate those values somehow.当然,您需要以某种方式计算这些值。 The suggestion below shows one possible way to do exactly that.下面的建议显示了一种可能的方法来做到这一点。

The details细节

The reason why you're not seeing trendlines after clicking the button options is that there is no definition and/or data for a trendline in, for example:单击按钮选项后看不到趋势线的原因是没有趋势线的定义和/或数据,例如:

args=[{"x": [x2], "y": [y1], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "NFCC vs Misperception"}]

And this is not very apparent, but you could easily add data for more traces in the layout that the button-click creates by adding more data in the lists associated with "x" and "y" like this:这不是很明显,但是您可以通过在与"x""y"关联的列表中添加更多数据,轻松地在单击按钮创建的布局中添加更多跟踪数据,如下所示:

args=[{"x": [x2, x21], "y": [y1, y11], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "NFCC vs Misperception"}]

How you choose to create that data is up to you.您选择如何创建该数据取决于您。 But sticking to Plotly Express , you can create and retrieve data for an OLS regression like this:但坚持使用Plotly Express ,您可以像这样为OLS回归创建和检索数据:

px.scatter(x=x2, y=y1, trendline='ols').data[1].x

And:和:

px.scatter(x=x2, y=y1, trendline='ols').data[1].y

Using that, the args for your first button would look like this:使用它,您的第一个按钮的args将如下所示:

args=[{"x": [x2, px.scatter(x=x2, y=y1, trendline='ols').data[1].x], "y": [y1, px.scatter(x=x2, y=y1, trendline='ols').data[1].y], "trendline":["ols"], "trendline_scope":["overall"]},
    {"title": "NFCC vs Misperception"}]

Here's a complete setup for your two first buttons with some random data:这是带有一些随机数据的前两个按钮的完整设置:

Plot1:情节1:

在此处输入图像描述

Plot2:情节2:

在此处输入图像描述

If you would share your data in your code snippet with the output from df.to_dict() I might find the time to write up a complete solution.如果您将代码片段中的数据与来自df.to_dict()的 output 共享,我可能会找到时间编写完整的解决方案。

Code:代码:

import plotly.graph_objects as go
import plotly.express as px
import numpy as np
import pandas as pd
# making a figure

df = pd.DataFrame({'crttotal': np.random.random(8),
                   'nfcc_mean': np.random.random(8),
                   'bficonmean': np.random.random(8),
                   'bfiopmean': np.random.random(8),
                   'avg_misperception_score': np.random.random(8),
                   'avg_ambiguous_score': np.random.random(8)})

fig = go.Figure()
x1 = df['crttotal']
x2 = df['nfcc_mean']
x3 = df['bficonmean']
x4 = df['bfiopmean']

y1 = df['avg_misperception_score']
y2 = df['avg_ambiguous_score']

fig = px.scatter(df, x=x2, y=y1, trendline="ols", trendline_scope="overall")
fig.show()
# making the dropdown

fig.update_layout(
    updatemenus=[
        go.layout.Updatemenu(
            type="dropdown",
            buttons=list([

                dict(label="NFCC vs Misperception",
                     method="update",
                     args=[{"x": [x2, px.scatter(x=x2, y=y1, trendline='ols').data[1].x], "y": [y1, px.scatter(x=x2, y=y1, trendline='ols').data[1].y], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "NFCC vs Misperception"}]),
                dict(label="CRT vs Misperception",
                     method="update",
                     args=[{"x": [x1, px.scatter(x=x1, y=y1, trendline='ols').data[1].x], "y": [y1, px.scatter(x=x1, y=y1, trendline='ols').data[1].y], "trendline":["ols"], "trendline_scope":["overall"]},
                           {"title": "CRT vs Misperception"}]),
                # dict(label="bficonmean vs Misperception",
                #      method="update",
                #      args=[{"x": [x3], "y": [y1], "trendline":["ols"], "trendline_scope":["overall"]},
                #            {"title": "bficonmean vs Misperception"}]),
                # dict(label="bfiopmean vs Misperception",
                #      method="update",
                #      args=[{"x": [x4], "y": [y1], "trendline":["ols"], "trendline_scope":["overall"]},
                #            {"title": "bfiopmean vs Misperception"}]),

                # dict(label="CRT vs Ambiguity",
                #      method="update",
                #      args=[{"x": [x1], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                #            {"title": "CRT vs Ambiguity"}]),
                # dict(label="NFCC vs Ambiguity",
                #      method="update",
                #      args=[{"x": [x2], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                #            {"title": "NFCC vs Ambiguity"}]),
                # dict(label="bficonmean vs Ambiguity",
                #      method="update",
                #      args=[{"x": [x3], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                #            {"title": "bficonmean vs Ambiguity"}]),
                # dict(label="bfiopmean vs Ambiguity",
                #      method="update",
                #      args=[{"x": [x4], "y": [y2], "trendline":["ols"], "trendline_scope":["overall"]},
                #            {"title": "bfiopmean vs Ambiguity"}])

            ])
        )
    ]
)

# set the title
fig.update_layout(title="Dropdown")

# fig.show()

"AS DISCUSSED IN COMMENT" your solution worked, but the trenline info box always reads with the same equation: avg_misperception = -.004*crttotal +.073 “正如评论中讨论的那样”您的解决方案有效,但 trenline 信息框始终使用相同的等式读取:avg_misperception = -.004*crttotal +.073

How do I get it so that the info box also updates?我如何获得它以便信息框也更新? [![Trendline info box does not match graph variables][1]][1] [![Trendline info box does not match graph variables][2]][2] [![趋势线信息框与图形变量不匹配][1]][1] [![趋势线信息框与图形变量不匹配][2]][2]

Seriously, you're amazing.说真的,你太棒了。 TY so much for providing such a clear answer.非常感谢 TY 提供了如此明确的答案。 [1]: https://i.stack.imgur.com/zPxBL.png [2]: https://i.stack.imgur.com/fy7m6.png [1]: https://i.stack.imgur.com/zPxBL.png [2]: https://i.stack.imgur.com/fy7m6.png

EDIT: the same is the case for the data point labels.编辑:数据点标签也是如此。 When you hover over a data their values are labeled as "crttotal" and "avg_misperception_score."当您对数据进行 hover 时,它们的值被标记为“crttotal”和“avg_misperception_score”。 I assume I need to update something in the Layout Attribute - https://plotly.com/python/figure-structure/#the-toplevel-layout-attribute ?我假设我需要更新布局属性中的某些内容 - https://plotly.com/python/figure-structure/#the-toplevel-layout-attribute trying to figure it out on my own as well - just new to plotly.我也想自己弄明白——刚接触 plotly。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM