Using hexadecimal codes to colour a scatterplot

Dear plot_ly community,

I am having trouble creating a scatterplot in which one of the traces has colours given as hexadecimal code. These codes are passed as a vector to the colors argument, as described in the documentation. However, these values seem to be ignored. I am using the latest plot_ly version (plotly_4.10.4) in R (4.1.2) in a machine running Ubuntu 22.04 from WSL (5.15.153.1-microsoft-standard-WSL2) in Windows.

Minimal reproducible code is:

library("tidyverse")
library("plotly")
library("khroma")

scores <- structure(list(PC1 = c(8L, 13L, -10L, 9L, 4L, 88L, -14L, -10L, -5L, -4L, -5L, 0L, 83L, 84L, 87L, 88L, 88L, 91L, 90L, 89L, 86L, 88L, 0L, -4L, 0L, 4L, 5L, 0L, 0L, -6L, -3L, -1L),
                         PC2 = c(95L, 89L, -7L, 84L, 100L, -6L, -10L, -3L, -5L, -13L, -7L, -4L, -9L, -5L, -6L, -9L, -7L, -7L, -9L, -10L, -7L, -8L, 9L, 8L, 5L, 11L, 3L, 9L, 3L, 6L, 3L, 5L),
                         PC3 = c(12L, 8L, 1L, 13L, 7L, 4L, 1L, -2L, -1L, 1L, -1L, -25L, 4L, 6L, 8L, 6L, 4L, 10L, 0L, 7L, 5L, 5L, -29L, -27L, -23L, -36L, -35L, -38L, -31L, -23L, -24L, -30L),
                         NAME = c("H1", "H1", "H1", "H1", "H1", "H1", "H2", "H2", "H2","H2", "H2", "H2", "OTHER", "OTHER", "OTHER", "OTHER", "OTHER","OTHER", "OTHER", "OTHER", "OTHER", "OTHER", "OTHER", "OTHER","OTHER", "OTHER", "OTHER", "OTHER", "OTHER", "OTHER", "OTHER", "OTHER")),
                    row.names = c(NA, -32L),
                    class = "data.frame")


# Create the obabe palette
okabe <- khroma::colour("okabe ito")
okp <- as.character(okabe(8))

# Subset data into highlighted vs. other samples
highlighted_samples <- c("H1", "H2")
highlighted <- scores[scores$NAME %in% highlighted_samples, ]
other <- scores[!scores$NAME %in% highlighted_samples, ]

plot_PCA <- plot_ly(type = "scatter3d", mode = "markers")

plot_PCA <- plot_PCA |>
  add_trace(
    data = other,
    x = ~PC1,
    y = ~PC2,
    z = ~PC3,
    marker = list(size = 4, opacity = 0.3),
    color = I("lightgrey"),
    name = "Other samples"
  )

plot_PCA |>
  add_trace(
    data = highlighted,
    x = ~PC1,
    y = ~PC2,
    z = ~PC3,
    marker = list(size = 4),
    color = ~NAME,
    colors = unname(setNames(
      okp[seq_along(highlighted_samples)],
      highlighted_samples
    ))
  )

I tried giving the hexadecimal values as one per sample rather than group as defined by the NAME variable, but this still did not solve the problem

highlighted <- highlighted |> dplyr::mutate(okp2 = ifelse(NAME == "H1", "#000000", "#E69F00"))

plot_PCA |>
  add_trace(
    data = highlighted,
    x = ~PC1,
    y = ~PC2,
    z = ~PC3,
    marker = list(size = 4),
    colors = ~okp2
  )

Thank you for your help,
Eugenio

PS: Edit. For clarity, please note that the expected colours for the highlighted samples are black (#000000) for H1, and orange (“#E69F00”) for H2. But these are not the colours returned by plotly.

Hey @elcortegano welcome to the forums.

I can´t help with R, but did you try a simple plot with two values and two colors? Without any assignment logic, just hard coded?

Unfortunately the problem persist even in a simpler scatter plot. Following the previous example:

plot_PCA <- plot_ly(type = "scatter", mode = "markers")
plot_PCA |>
  add_trace(
    data = highlighted,
    x = ~PC1,
    y = ~PC2,
    marker = list(size = 4),
    color = ~NAME,
    colors = ~okp2
  )

The new plot, as the previous one, used a different colour palette:

If a warning appears it seems to be related to the fact that this minimal example only includes two levels for the “NAME” variable, but adding more (e.g. with the code below) does not solve the issue.

highlighted <- highlighted |> dplyr::mutate(okp2 = ifelse(PC3 == 12, "#DD0000", okp2), NAME = ifelse(PC3 == 12, "H0", NAME))
plot_PCA <- plot_ly(type = "scatter", mode = "markers")
plot_PCA |>
  add_trace(
    data = highlighted,
    x = ~PC1,
    y = ~PC2,
    marker = list(size = 4),
    color = ~NAME,
    colors = ~okp2
  )

As I said, I don’t know about R. Should the plot look like that?

import plotly.graph_objects as go
import numpy as np

# var
marker_size = 20

# data
x = np.arange(2)
y = np.arange(2)
size = np.ones_like(x) * marker_size

# base figure
fig = go.Figure()

# trace 1
fig.add_scatter(
    x=x,
    y=y,
    marker_color=["#000000", "#E69F00"],
    marker_size=size,
    line_color="gray",
    name="trace_1"
)

This was actually very helpful. Thank you very much.

The value of color with the hexadecimal values had to be used within the marker argument for it to work. In R, the following does the job:

plot_PCA <- plot_ly(type = "scatter", mode = "markers")
plot_PCA |>
    add_trace(
        data = highlighted,
        x = ~PC1,
        y = ~PC2,
        marker = list(color = okp2)
    )
1 Like