R plot_ly 由带有颜色和符号的连续交互散点图回归线分类
R plot_ly categorical by continuous interaction scatterplot regression lines with colors and symbols
我需要为分类因素的两个水平(在我的例子中是性别)构建一个包含两条回归线的散点图。散点图应该包含所有观察值,但每个级别的线性模型需要单独绘制。换句话说,以下模型的散点图:
连续 A = 截距 + 连续 B + 分类 + 连续 B* 分类。
Plotly 不会注册 add_markers() 指定的颜色,除非删除 add_lines() 和 add_ribbons()。如果这不能用 Plotly 完成(一个错误?)那么可以用 ggplot(也许还有 GGally)来完成吗?
另外,我很想看看这是否可以用更短、更整洁或更漂亮的代码或函数来完成。一次做所有三个 iris$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
Plotly does not register the colors specified by add_markers(), unless
the add_lines() and add_ribbons() are removed. If this cannot be done
with Plotly (a bug?) then can it be done with ggplot (and perhaps
GGally)?
您可以分别为不同的类别添加标记,即重复调用 add_markers
。
Also, I would love to see if this can be done with shorter, tidier, or
prettier code, or with a function. It would be even better to do all
three iris$Species at once.
您可以遍历所有三个物种,因此您只需要编写一次代码。
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
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)
}
我需要为分类因素的两个水平(在我的例子中是性别)构建一个包含两条回归线的散点图。散点图应该包含所有观察值,但每个级别的线性模型需要单独绘制。换句话说,以下模型的散点图:
连续 A = 截距 + 连续 B + 分类 + 连续 B* 分类。
Plotly 不会注册 add_markers() 指定的颜色,除非删除 add_lines() 和 add_ribbons()。如果这不能用 Plotly 完成(一个错误?)那么可以用 ggplot(也许还有 GGally)来完成吗?
另外,我很想看看这是否可以用更短、更整洁或更漂亮的代码或函数来完成。一次做所有三个 iris$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
Plotly does not register the colors specified by add_markers(), unless the add_lines() and add_ribbons() are removed. If this cannot be done with Plotly (a bug?) then can it be done with ggplot (and perhaps GGally)?
您可以分别为不同的类别添加标记,即重复调用 add_markers
。
Also, I would love to see if this can be done with shorter, tidier, or prettier code, or with a function. It would be even better to do all three iris$Species at once.
您可以遍历所有三个物种,因此您只需要编写一次代码。
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
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)
}