首页 > 解决方案 > R:在图表之间切换

问题描述

我正在使用 R 编程语言。我正在尝试按照此处有关“在图表之间切换”的教程进行操作:https ://plotly.com/r/dropdowns/ (第一个示例)。

首先,我在 R 中生成了一些数据:

library(plotly)
library(MASS)

x <- sample( LETTERS[1:4], 1000, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25) )
y <- rnorm(1000,10,10)
z <- rnorm(1000,5,5)
    
    df <- data.frame(x,y, z)
df$x = as.factor(df$x)
    colnames(df) <- c("x", "y", "z")

我尝试修改本教程中的代码以获得最终结果:

fig <- plot_ly(df, x = ~x, y = ~y, z = ~z alpha = 0.3)
fig <- fig %>% add_markers(marker = list(line = list(color = "black", width = 1)))
fig <- fig %>% layout(
    title = "Drop down menus - Plot type",
    xaxis = list(domain = c(0.1, 1)),
    yaxis = list(title = "y"),
    updatemenus = list(
        list(
            y = 0.8,
            buttons = list(
                
                list(method = "restyle",
                     args = list("type", "scatter"),
                     label = "Scatter A"),
                
                list(method = "restyle",
                     args = list("type", "scatter"),
                     label = "Scatter B"),
                
                list(method = "restyle",
                     args = list("type", "scatter"),
                     label = "Scatter C"),
                
                list(method = "restyle",
                     args = list("type", "scatter"),
                     label = "Scatter D")
                
                
            ))

但这似乎不起作用。

相反,我有一个不同的想法:也许我可以创建一系列我希望能够在以下之间“切换”的图表:

df_1 <- df[which(df$x == "A"),]
df_2 <- df[which(df$x == "B"),]
df_3 <- df[which(df$x == "C"),]
df_4 <- df[which(df$x == "D"),]


graph_1 <- plot_ly( data = df_1, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 1")

graph_2 <- plot_ly( data = df_2, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 2")

graph_3 <- plot_ly( data = df_3, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 3")

graph_4 <- plot_ly( data = df_4, type = "scatter", mode = "markers", x = ~ y, y = ~z) %>% layout(title = "graph 4")

graph_5 <- plot_ly(df, y = ~y, color = ~x, type = "box") %>% layout(title = "boxplot")

现在,是否可以修改 plotly 代码以将所有这些图(graph_1、graph_2、graph_3、graph_4、graph_5)“绑定”在一起,以便用户可以单击左侧的选项卡并在这些图之间切换?

谢谢

标签: ronclickplotlydata-visualizationinteractive

解决方案


您应该查看本教程的示例是最后一个示例(带有正弦波)。它根据下拉菜单中的选择值隐藏和显示绘图的不同轨迹。

您只需要将数据框的格式更改为宽。

df.wide <- df %>% tidyr::pivot_wider(names_from = x, values_from=z)

df.wide
## A tibble: 1,000 x 5
#       y     D     B       A     C
#   <dbl> <dbl> <dbl>   <dbl> <dbl>
# 1  6.48  6.21 NA    NA      NA   
# 2 23.6  NA    15.3  NA      NA   
# 3 -9.99 -2.16 NA    NA      NA   
# 4 19.6  NA    NA     0.0683 NA   
# 5 18.8  -1.40 NA    NA      NA   
# 6 -2.71  9.80 NA    NA      NA   
# 7  2.32 NA    NA    NA       3.77
# 8 11.9  NA     4.35 NA      NA   
# 9 21.4  NA    NA    NA      13.9 
#10  2.34 NA     2.10 NA      NA   
## … with 990 more rows

然后为每列添加单独的散点图。在下拉菜单的参数中,您可以设置在选择每个选项时哪些轨迹可见。例如args = list("visible", list(TRUE, FALSE, FALSE, FALSE))意味着只有添加的第一个跟踪(在本例中为 column A)将是可见的。

fig <- plot_ly(df.wide, x = ~y)
fig <- fig %>% 
  add_trace(y = ~A, name = "A", type='scatter', mode='markers') %>% 
  add_trace(y = ~B, name = "B", type='scatter', mode='markers', visible = F) %>%
  add_trace(y = ~C, name = "C", type='scatter', mode='markers', visible = F) %>%
  add_trace(y = ~D, name = "D", type='scatter', mode='markers', visible = F) %>% 
  layout(xaxis = list(domain = c(0.1, 1)),
         yaxis = list(title = "y"),
         updatemenus = list(
           list(
             y = 0.7,
             buttons = list(
               list(method = "restyle",
                    args = list("visible", list(TRUE, FALSE, FALSE, FALSE)),
                    label = "A"),
               list(method = "restyle",
                    args = list("visible", list(FALSE, TRUE, FALSE, FALSE)),
                    label = "B"),
               list(method = "restyle",
                    args = list("visible", list(FALSE, FALSE, TRUE, FALSE)),
                    label = "C"),
               list(method = "restyle",
                    args = list("visible", list(FALSE, FALSE, FALSE, TRUE)),
                    label = "D")))))

在此处输入图像描述 在此处输入图像描述

编辑:还添加一个箱线图

为不同类型的图(如箱线图)添加一个选项有点困难。现在的问题是箱线图中的 x 轴和散点图中的 x 轴是不同的。所以你不能使用相同的轴。幸运的是,plotly 允许您将不同的轨迹映射到不同的轴。domain然后,您可以使用该属性在完整图中设置此新轴的位置。

我的解决方案有点hacky,因为我使用该domain属性来“隐藏”我不想使用的“情节”,方法是使其非常小(我还通过设置使相应的数据不可见visible = FALSE)。这是因为隐藏轴只会隐藏线条。你仍然留下了情节的背景。

请注意,现在我使用该方法update(而不是restyle),因为它还允许您更改绘图的布局(https://plotly.com/r/custom-buttons/)。

但它似乎工作得很好!

# I had to reorder the dataframe because the boxplot was not following the order of the factors. Apparently it follows the orders that the letter appear.
df <- df %>% dplyr::arrange(x)

df.wide <- df %>% tidyr::pivot_wider(names_from = x, values_from=z)

# this is a list with axis config for scatter plot (define here to avoid repetition)
axis.config.scatter <- list(xaxis = list(title = "x", domain = c(0.1, 1), visible=T),
                            yaxis = list(title = "y", domain = c(0, 1), visible=T),
                            xaxis2 = list(title = "group", domain = c(0.99, 1), visible=F),
                            yaxis2 = list(title = "y", domain = c(0,99, 1), visible=F))

# this is a list with axis config for box plot (define here to avoid repetition)
axis.config.box <- list(xaxis = list(title = "x", domain = c(0.99, 1), visible=F),
                        yaxis = list(title = "y", domain = c(0.99, 1), visible=F),
                        xaxis2 = list(title = "group", domain = c(0.1, 1), visible=T, anchor='free'),
                        yaxis2 = list(title = "y", domain = c(0, 1), visible=T, anchor='free'))


fig <- plot_ly(df.wide)
fig <- fig %>% 
  add_trace(x = ~y, y = ~A, name = "A", type='scatter', mode='markers') %>% 
  add_trace(x = ~y, y = ~B, name = "B", type='scatter', mode='markers', visible = F) %>%
  add_trace(x = ~y, y = ~C, name = "C", type='scatter', mode='markers', visible = F) %>%
  add_trace(x = ~y, y = ~D, name = "D", type='scatter', mode='markers', visible = F) %>% 
  add_trace(data=df, x=~x, y=~z, name='box', type='box', visible=F, xaxis='x2', yaxis='y2') %>%
  layout(xaxis = list(title = "x", domain = c(0.1, 1)),
         yaxis = list(title = "y"),
         xaxis2 = list(title = "group", domain = c(0.99, 1), visible=F),
         yaxis2 = list(title = "y", domain = c(0.99, 1), visible=F),
         updatemenus = list(
           list(
             y = 0.7,
             buttons = list(
               list(method = "update",
                    args = list(list(visible = c(TRUE, FALSE, FALSE, FALSE, FALSE)),
                                axis.config.scatter),
                    label = "A"),
               list(method = "update",
                    args = list(list(visible = c(FALSE, TRUE, FALSE, FALSE, FALSE)),
                                axis.config.scatter),
                    label = "B"),
               list(method = "update",
                    args = list(list(visible = c(FALSE, FALSE, TRUE, FALSE, FALSE)),
                                axis.config.scatter),
                    label = "C"),
               list(method = "update",
                    args = list(list(visible = c(FALSE, FALSE, FALSE, TRUE, FALSE)),
                                axis.config.scatter),
                    label = "D"),
               list(method = "update",
                    args = list(list(visible = c(FALSE, FALSE, FALSE, FALSE, TRUE)),
                                axis.config.box),
                    label = "box")
               ))))

在此处输入图像描述 在此处输入图像描述


推荐阅读