R plot_ly通过连续交互散点图回归线与颜色和符号分类

时间:2017-03-10 01:58:17

标签: r plotly scatter-plot lm interaction

我需要为分类因子的两个级别(在我的例子中,性别)构建一个带有两条回归线的散点图。散点图应具有所有观察值,但每个级别的线性模型需要单独绘制。换句话说,以下模型的散点图:

continuousA = intercept + continuousB +分类+连续B *分类。

Plotly不会注册add_markers()指定的颜色,除非删除了add_lines()和add_ribbons()。如果Plotly无法做到这一点(一个bug?)那么可以用ggplot(也许是GGally)完成吗?

此外,我很想看看是否可以使用更短,更整洁或更漂亮的代码或使用函数来完成此操作。最好一次做所有三个虹膜$ Species。

library(plotly)
library(broom)
plot_ly() %>%
  add_lines(data = iris[which(iris$Species=='versicolor'), ],
            y = ~fitted(lm(data = iris[which(iris$Species=='versicolor'), ], Petal.Width ~ Petal.Length)),
            x = ~Petal.Length,
            line = list(color = "red"),
            name = "Versicolor") %>%
  # Plot the 95% CI of slope ribbon
  add_ribbons(data = augment(lm(data = iris[which(iris$Species=='versicolor'), ], Petal.Width ~ Petal.Length)),
              y = ~Petal.Width,
              x = ~Petal.Length,
              ymin = ~.fitted - 1.96 * .se.fit,
              ymax = ~.fitted + 1.96 * .se.fit,
              line = list(color = 'rgba(255, 255, 255, 0.05)'), #get rid of the border line
              fillcolor = 'rgba(255, 0, 0, 0.1)', #red with alpha transparency
              name = "Versicolor (Standard Error)",
              showlegend = FALSE) %>%
  add_lines(data = iris[which(iris$Species=='virginica'), ],
            y = ~fitted(lm(data = iris[which(iris$Species=='virginica'), ], Petal.Width ~ Petal.Length)),
            x = ~Petal.Length,
            line = list(color = "green", dash = "dash"),
            name = "Viginica") %>%
  add_ribbons(data = augment(lm(data = iris[which(iris$Species=='virginica'), ], Petal.Width ~ Petal.Length)),
              y = ~Petal.Width,
              x = ~Petal.Length,
              ymin = ~.fitted - 1.96 * .se.fit,
              ymax = ~.fitted + 1.96 * .se.fit,
              line = list(color = 'rgba(255, 255, 255, 0.05)'), #get rid of the border line
              fillcolor = 'rgba(0, 255, 0, 0.1)', #green with alpha transparency
              name = "Virginica (Standard Error)",
              showlegend = FALSE) %>%
  add_markers(data = iris[which(iris$Species=='versicolor' | iris$Species=='virginica'), ], 
              x = ~Petal.Length, 
              y = ~Petal.Width,
              symbol = ~Species,
              color = ~Species, colors = c("versicolor" = "red", "virginica" = "green")) %>%
  layout(xaxis = list(title = "Petal Length"), yaxis = list(title = "Petal Width"))

Interaction Scatterplot

2 个答案:

答案 0 :(得分:2)

  

Plotly不会注册add_markers()指定的颜色,除非   add_lines()和add_ribbons()被删除。如果做不到这一点   用Plotly(一个bug?)然后就可以用ggplot来完成(也许吧   GGally)?

您可以单独为不同类别添加标记,即重复调用add_markers

  

另外,我很想知道这是否可以用更短,更整洁或者更好的方式来完成   更漂亮的代码,或具有功能。做所有事情会更好   三个虹膜$物种一次。

你可以遍历所有三个物种,因此你只需要编写一次代码。

library(plotly)
library(broom)

species <-  unique(iris$Species)
colors <- c('(255, 0, 0', '(0, 255, 0', '(0, 0, 255')

p <- plot_ly()

for (i in 1:length(species)) {
  p <- add_lines(p, data = iris[which(iris$Species==species[[i]]), ],
            y = fitted(lm(data = iris[which(iris$Species==species[[i]]), ], Petal.Width ~ Petal.Length)),
            x = ~Petal.Length,
            line = list(color = paste('rgb', colors[[i]], ')')),
            name = species[[i]])
    p <- add_ribbons(p, data = augment(lm(data = iris[which(iris$Species==species[[i]]), ], Petal.Width ~ Petal.Length)),
                y = ~Petal.Width,
                x = ~Petal.Length,
                ymin = ~.fitted - 1.96 * .se.fit,
                ymax = ~.fitted + 1.96 * .se.fit,
                line = list(color = paste('rgba', colors[[i]], ', 0.05)')), 
                fillcolor = paste('rgba', colors[[i]], ', 0.1)'),
                showlegend = FALSE)
    p <- add_markers(p, data = iris[which(iris$Species==species[[i]]), ], 
              x = ~Petal.Length, 
              y = ~Petal.Width,
              symbol = ~Species,
              marker=list(color=paste('rgb', colors[[i]])))
}
p <- layout(p, xaxis = list(title = "Petal Length"), yaxis = list(title = "Petal Width"))

p

enter image description here

答案 1 :(得分:0)

Maximillian Peters为这个问题提供了一个很好的答案。这是我从他的回答中做出的一个功能。

plotly_interaction <- function(data, x, y, category, colors = col2rgb(viridis(nlevels(as.factor(data[[category]])))), ...) {
  # Create Plotly scatter plot of x vs y, with separate lines for each level of the categorical variable. 
  # In other words, create an interaction scatter plot.
  # The "colors" must be supplied in a RGB triplet, as produced by col2rgb().

  require(plotly)
  require(viridis)
  require(broom)

  groups <- unique(data[[category]])

  p <- plot_ly(...)

  for (i in 1:length(groups)) {
    groupData = data[which(data[[category]]==groups[[i]]), ]
    p <- add_lines(p, data = groupData,
                   y = fitted(lm(data = groupData, groupData[[y]] ~ groupData[[x]])),
                   x = groupData[[x]],
                   line = list(color = paste('rgb', '(', paste(colors[, i], collapse = ", "), ')')),
                   name = groups[[i]],
                   showlegend = FALSE)
    p <- add_ribbons(p, data = augment(lm(data = groupData, groupData[[y]] ~ groupData[[x]])),
                     y = groupData[[y]],
                     x = groupData[[x]],
                     ymin = ~.fitted - 1.96 * .se.fit,
                     ymax = ~.fitted + 1.96 * .se.fit,
                     line = list(color = paste('rgba','(', paste(colors[, i], collapse = ", "), ', 0.05)')), 
                     fillcolor = paste('rgba', '(', paste(colors[, i], collapse = ", "), ', 0.1)'),
                     showlegend = FALSE)
    p <- add_markers(p, data = groupData, 
                     x = groupData[[x]], 
                     y = groupData[[y]],
                     symbol = groupData[[category]],
                     marker = list(color=paste('rgb','(', paste(colors[, i], collapse = ", "))))
  }
  p <- layout(p, xaxis = list(title = x), yaxis = list(title = y))
  return(p)
}