在 plotly 中自动创建子图(例如 R 中的 Facetting)

Posted

技术标签:

【中文标题】在 plotly 中自动创建子图(例如 R 中的 Facetting)【英文标题】:Automatically creating subplots in plotly (e.g. Facetting in R) 【发布时间】:2022-01-08 21:06:33 【问题描述】:

我很喜欢使用 tidyverse 和 ggplot。我正在尝试生成一个交互式图表以使用 flexdashboard 进行部署。因此,我试图在 plotly 中生成我常用的 ggplots。

假设我有以下数据框:

data.frame(id = c(1:5),
           product = c("product1","product2","product1","product3","product2"),
           variable = c("var1","var1","var3","var2","var1"),
           price = c(100,120,140,90,80))

有输出:

  id  product variable price
1  1 product1     var1   100
2  2 product2     var1   120
3  3 product1     var3   140
4  4 product3     var2    90
5  5 product2     var1    80

如果我想在绘图上显示所有这些,我会在 ggplot 中执行以下操作:

library(tidyverse)
library(hrbrthemes)

data.frame(id = c(1:5),
           product = c("product1","product2","product1","product3","product2"),
           variable = c("var1","var1","var3","var2","var1"),
           price = c(100,120,140,90,80)) %>%
  ggplot(aes(x = id, y = price, color = variable)) +
  geom_point() +
  facet_wrap(~product) +
  theme_ft_rc()

哪个会产生:

我知道我可以通过使用subplot() 在情节上实现类似的目标 功能。问题是我有 14-28 个类别可以绘制为方面。据我了解,这意味着我必须制作 14-28 个图,然后将它们排列在网格中。这似乎有点乏味,我想知道是否有更有效的方法来实现这一点,例如 ggplot 中的 facet 选项。我还在另一篇文章中获得了一段代码:

library(plotly)

dataframe <- data.frame(id = c(1:5),
           product = c("product1","product2","product1","product3","product2"),
           variable = c("var1","var1","var3","var2","var1"),
           price = c(100,120,140,90,80)) %>%
  pivot_wider(names_from = "product", values_from = "price")

vars <- setdiff(names(dataframe),"id")

plots <- lapply(vars, function(var)
   plot_ly(dataframe, x = ~id, color =~variable, y = as.formula(paste0("~",var))) %>%
  add_bars(name = var)
 )
 subplot(plots, nrows = length(plots), shareX = TRUE, titleX = FALSE)

产量:

并且需要使用 tidyr 的 pivot_wider() 函数和示例框架中的 product 列。但是,我的真实列包含数字和字符,使用上述示例代码时会产生错误。变量列也以更奇怪的方式显示。是否有解决此问题的方法,或者是真正为每个绘图手动编写代码的最佳方法?

【问题讨论】:

【参考方案1】:

根据您的第一个示例(我刚刚删除了您的主题样式),它的工作原理是这样的。

df <- data.frame(
  id = c(1:5),
  product = c("product1","product2","product1","product3","product2"),
  variable = c("var1","var1","var3","var2","var1"),
  price = c(100,120,140,90,80)
)

plot <- ggplot(df, aes(x = id, y = price, color = variable)) +
  geom_point() +
  facet_wrap(~product)

ggplotly(plot)

唯一的区别是我没有与 %>% 链接,因为当我在下面尝试这个时似乎会抛出错误:

data.frame(
  id = c(1:5),
  product = c("product1","product2","product1","product3","product2"),
  variable = c("var1","var1","var3","var2","var1"),
  price = c(100,120,140,90,80)
) %>% ggplot(aes(x = id, y = price, color = variable)) +
  geom_point() +
  facet_wrap(~product) %>% ggplotly()

# Error in UseMethod("ggplotly", p) : 
#   no applicable method for 'ggplotly' applied to an object of class "c('FacetWrap', 'Facet', 'ggproto', 'gg')"

带有自定义工具提示的扩展示例

您可以随心所欲地制作它,我添加了价格格式,并且为了它的乐趣将产品和变量组合为工具提示中的一行。

custom_tooltip <- paste0("ID: ", df$id, "\n", "Product: ", df$product, " (", df$variable, ")\n", "Sold for: £ ", df$price)

plot <- ggplot(df, aes(x = id, y = price, color = variable)) +
  geom_point(aes(text = custom_tooltip)) +
  facet_wrap(~product)

ggplotly(plot, tooltip = c("text"))

【讨论】:

谢谢!我想我可以试试这样。我对 ggplotly 的问题是它有时会以一种奇怪的方式格式化绘图。主要是我似乎无法找到如何正确格式化悬停文本,使其显示类似paste("£", price) 您可以重写工具提示的文本,给我一秒钟将其添加到我的答案中。 哦,谢谢,这真是太棒了,我整个星期都在为这个工具提示问题苦苦挣扎。我不知道您必须将其传递给绘图类型aes()。非常感谢您的解决方案,我将尝试稍微编辑我的问题,以便它反映您的答案。唯一的问题是我的构面图的格式很奇怪。我在方面有 22 个子图。第一行正常显示,最后一行也正常显示。但是中间的三排被压缩得扁平且难以辨认。你知道为什么吗? 是使用 ggplot 代码,然后将其设为 ggplotly,还是使用子图得到刻面问题? 不,我正在使用 ggplot2 创建与上面相同的构面图,然后通过 ggplotly 将其传递给 plotly。如果我为一个产品做一个点图,它工作得很好,但是当我面对所有这些时,格式是随机的。我将尝试以重现我的问题为例。

以上是关于在 plotly 中自动创建子图(例如 R 中的 Facetting)的主要内容,如果未能解决你的问题,请参考以下文章

在 Matplotlib 中循环创建子图?

使用 pandas 数据透视表创建子图

VB 在Visio 2010 以编程方式创建子进程图

如何从 Java 中的另一个数组创建子数组?

Python - 自动创建子记录

如何使用 matplotlib 创建子图的大图?