如何使用plotly在散点图中同时应用颜色/形状/大小?

时间:2016-01-03 22:55:50

标签: r ggplot2 plotly

我正在尝试创建(在plotly中)一个散点图,它将同一系列的点区分为两个(或三个)美学 - 颜色,形状,大小。最终目标是能够使用三种美学中的任何一种通过图例打开/关闭点组。这适用于一种美学。

[已添加2016-06-20] 要扩展所需的互动行为:一旦显示图形,该想法就是能够通过点击任何一个点来切换点组。传说。例如(在下面的示例数据中),如果我点击图例中的y,它将隐藏/显示所有系列中的点#4,5和10。如果点击A,则切换点#1,2和8。 作为一个真实的用例 - 考虑债券价格,水平轴上的成熟度和纵向的价格。债券的特点是原产国,信用评级和发行规模。因此,如果我点击信用评级“A”,我希望隐藏所有A级问题,无论其大小和来源国家。目前,它们仅与评级相关的跟踪隐藏。反映其他属性(大小和国家/地区)的痕迹中的点仍然显示。 鉴于下面的详细解答,我倾向于将此作为功能请求发布在plotly的网站上。

我已经为plotly设置了问题,但如果这个行为可以在R的另一个包/库中实现,并且疼痛程度相对较低(意味着没有自定义JavaScript等),我会接受这也是一个答案。 [结束编辑]

静态部分可以在ggplot2中轻松完成,但我无法在plotly(用于交互性)中重新创建它,即使使用ggplotly()也是如此。不确定是否有可能,但我想我会问。样本数据&代码如下。

(可能与Using 2+ legends from R to plotly / plot.ly相关)

生成一些虚拟数据:

library(data.table)
library(plotly)
library(ggplot2)


DT <- data.table(
    x = c(1:10), y = 1:10/2,
    gr1 = c("A", "A", "B", "C", "D", "D", "B", "A", "E", "E"),
    gr2 = c("x", "x", "x", "y", "y", "z", "z", "x", "x", "y"),
    gr3 = c(1,2,2,1,3,4,1,2,2,1)
)

ggplot()版本看起来像这样,是我想要得到的:

p <- ggplot(data = DT) + geom_point(aes(x = x, y = y, color = gr1, shape = gr2, size = gr3))
p

图例中有三组标准,这些点的颜色,形状和大小各不相同。 ggplot version

调用ggplotly(p)会产生一系列警告:

Warning messages:
1: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
2: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
3: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
4: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
5: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
6: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
7: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used
8: In if (s == Inf) { :
  the condition has length > 1 and only the first element will be used

并产生这个数字:

ggplotly version

尝试使用plot_ly(),我得到以下内容:

plot_ly(data = DT, x = x, y = y, color = gr1, symbol = gr2, type = "scatter", mode = "markers", marker = list(size = 10 * gr3)) # size is multiplied by 10, in plotly it is in pixels

plot_ly version

问题在图的中间最明显 - 而不是彩色十字架,有几种不同颜色的形状相互叠加。由于这是一个单点,我期待一个单一的彩色形状,如ggplot。在情节上,“颜色”,“符号”和“大小”参数是否会创建新的跟踪?

我仍然是plotly的新手,所以我可能会遗漏一些明显的东西。

上述操作是在Windows下使用R 3.2.2完成的,plotly_2.0.16ggplot2_2.0.0

1 个答案:

答案 0 :(得分:6)

不幸的是,情节并没有自动给出这种行为。但是,通过使用colors =size =symbols =参数单独指定每个点的颜色,形状和大小,可以做到这一点。这样可以控制点的绘制方式,但不能获得所需的图例。因此,我们在主图中使用showlegend = FALSE并通过添加另外三条(不可见)跟踪来构建图例,这些跟踪仅用于生成图例项目。

请注意,我们需要在此处应用另一项技巧。要获得显示颜色或大小的图例,可以使用参数visible = "legendonly"创建图例条目,而不会在图表上过度绘制额外点。但这不适用于形状。将visible = "legendonly"symbols =结合起来似乎有一个错误,将错误的项目放入图例中。因此,要创建形状的图例条目,您可以将它们绘制在远离平流层的位置,在这些位置它们将永远不可见(这里我使用x = y = 1e6)并设置x和y轴限制以保持这些观点。

DT <- data.table(
  x = c(1:10), y = 1:10/2,
  gr1 = as.factor(c("A", "A", "B", "C", "D", "D", "B", "A", "E", "E")),
  gr2 = as.factor(c("x", "x", "x", "y", "y", "z", "z", "x", "x", "y")),
  gr3 = c(1,2,2,1,3,4,1,2,2,1)
)
shapes <- c("circle", "square", "diamond","cross", "x","square-open","circle-open","diamond-open")
DT$shapes <- shapes[DT$gr1]
DT$col <- rainbow(3)[DT$gr2]
DT$size <- DT$gr3*10

plot_ly() %>%
  add_trace(data = DT, x = x, y = y, type = "scatter", mode = "markers", 
            color=gr2, colors=col,
            marker = list(size = size, symbol=shapes), showlegend=F) %>%
  add_trace(data = DT, x = x, y = y, type = "scatter",mode = "markers", 
            color= factor(gr2), colors=col, 
            visible="legendonly", showlegend=T, legendgroup="color",
            marker = list(size = 14)) %>%
  add_trace(data = DT, x = x, y = y, type = "scatter",mode = "markers", 
            color=factor(gr3), colors="#000000", 
            marker = list(size = size),
            visible="legendonly", showlegend=T, legendgroup="size") %>%
  add_trace(data = DT, x = 1e6, y = 1e6, type = "scatter", mode = "markers", 
            color=factor(gr1), colors="#000000", 
            marker = list(size=14, symbol=shapes),
            showlegend=T, legendgroup="shape") %>%
  layout(legend=list(traceorder="grouped+reversed", tracegroupgap =30),
         xaxis=list(range=c(0,12)),
         yaxis=list(range=c(0,6)))

enter image description here