I have some data like this:
data <- data.frame(x=runif(500), y=runif(500), z=runif(500))
I want a scatterplot with points colored independently/discretely in each dimension (X, Y, and Z) using RGB values.
This is what I have tried:
Code:
library(dplyr)
library(plotly)
xyz_colors <- rgb(data$x, data$y, data$z)
plot_ly(data = data,
x = ~x, y = ~y, z = ~z,
color= xyz_colors,
type = 'scatter3d',
mode='markers') %>%
layout(scene = list(xaxis = list(title = 'X'),
yaxis = list(title = 'Y'),
zaxis = list(title = 'Z')))
Plot:
RColorBrewer thinks I'm trying to create a continuous scale from 500 intermediate colors:
Warning messages:
1: In RColorBrewer::brewer.pal(N, "Set2") :
n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
2: In RColorBrewer::brewer.pal(N, "Set2") :
n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
What are some correct ways to color the points like this in R with Plotly? Also, how can one generally assign colors to data points in R with Plotly, individually?
To clarify, I am trying to color each point where the color is of the format "#XXYYZZ" where 'XX' a value between 00 and FF linearly mapped to the value of data$x from 0 to 1. That is, the X dimension determines the amount of red, the Y dimension determines the amount of green, and the Z dimension determines the amount of blue. At 0,0,0 the point should be black and at 1,1,1 the point should be white. The reason for this is to make as easy to visualize the 3D position of the points as possible.
So, is there no way to color every point separately?
Yes, there is through the power and flexibility of add_traces(). And it's a lot less cumbersome than I first thought.
Just set up an empty plotly figure with some required 3D features:
p <-plot_ly(data = data, type = 'scatter3d', mode='markers')
And apply add_traces()
in a loop over each defined color:
for (i in seq_along(xyz_colors)){
p <- p %>% add_trace(x=data$x[i], y=data$y[i], z=data$z[i],
marker = list(color = xyz_colors[i], opacity=0.6, size = 5),
name = xyz_colors[i])
}
And you can easily define single points with a color of your choice like this:
p <- p %>% add_trace(x=0, y=0, z=0,
marker = list(color = rgb(0, 0, 0), opacity=0.8, size = 20),
name = xyz_colors[i])
Plot:
Complete code:
library(dplyr)
library(plotly)
# data and colors
data <- data.frame(x=runif(500), y=runif(500), z=runif(500))
xyz_colors <- rgb(data$x, data$y, data$z)
# empty 3D plot
p <-plot_ly(data = data, type = 'scatter3d', mode='markers') %>%
layout(scene = list(xaxis = list(title = 'X'),
yaxis = list(title = 'Y'),
zaxis = list(title = 'Z')))
# one trace per color
for (i in seq_along(xyz_colors)){
p <- p %>% add_trace(x=data$x[i], y=data$y[i], z=data$z[i],
marker = list(color = xyz_colors[i], opacity=0.6, size = 5),
name = xyz_colors[i])
}
# Your favorite data point with your favorite color
p <- p %>% add_trace(x=0, y=0, z=0,
marker = list(color = rgb(0, 0, 0), opacity=0.8, size = 20),
name = xyz_colors[i])
p
In 3D plots you can use the same color for all of the points, discern different clusters or categories from each other using different colors, or you use individual colors for each point to illustrate a fourth value (or fourth dimension if you like, as described here) in your dataset. All these approaches are, as you put it, examples of '[...] correct ways to color the points [...]'
. Have a look below and see if this suits your needs. I've included fourthVal <- data$x+data$y+data$z
as an example for an extra dimension. What you end up using will depend entirely on your dataset and what you'd like to illustrate.
Code:
library(dplyr)
library(plotly)
data <- data.frame(x=runif(500), y=runif(500), z=runif(500))
xyz_colors <- rgb(data$x, data$y, data$z)
fourthVal <- data$x+data$y+data$z
plot_ly(data = data,
x = ~x, y = ~y, z = ~z,
color= fourthVal,
type = 'scatter3d',
mode='markers') %>%
layout(scene = list(xaxis = list(title = 'X'),
yaxis = list(title = 'Y'),
zaxis = list(title = 'Z')))
Plot: