2

I am trying to access the customdata assigned to each data point via the javascrit (for instance to assign an hyperlink to each point). However, I noticed that the data format changes from one plot to the other, which seems bizarre.

This works perfectly in this example (based on this post), that is when the fill aesthetic is a character vector:

library(plotly)
library(htmlwidgets)

js <- "function(el, x) {
         el.on('plotly_click', function(d) {
           console.log(d);
           console.log(d.points[0].data.customdata[0]);
       });
       }"

X <- data.frame(x = c(1, 2, 1, 2), y = c(1, 1, 2, 2), z = as.character(1:4), mydata = letters[1:4])

gg <- ggplot(X, aes(x = x, y = y, customdata = mydata)) + geom_tile(aes(fill = z))

ggplotly(gg) %>% onRender(js)

enter image description here As can be seen, a single and correct custom data shows up when clicking on each point. The structure of the customdata is similar to other plots.

However, when z is entered as a numerical variable, the structure of the customdata behaves bizarrely:

X <- data.frame(x = c(1, 2, 1, 2), y = c(1, 1, 2, 2), z = 1:4, mydata = letters[1:4])

gg <- ggplot(X, aes(x = x, y = y, customdata = mydata)) + geom_tile(aes(fill = z))

ggplotly(gg) %>% onRender(js)

enter image description here Is this a bug? How can I fix this? In fact, my dataset is much larger than the one in this example.


Edit
@ismirsehregal provided a solution that works for the above example. However, it seems that customdata takes the vector data as is, which seems quite wrong. Therefore, if we change the order of X the js script stop working.

Showcase:

library(plotly)
library(htmlwidgets)

js <- "function(el, x) {
         el.on('plotly_click', function(d) {
           var zdimensions = [ 0, 0 ];
           var vecindex = 0;
           var clickedcustomdata = '';
           
           var zdimensions = [ d.points[0].data.z.length, d.points[0].data.z[0].length ];
           vecindex = d.points[0].pointIndex[0]*zdimensions[1] + d.points[0].pointIndex[1];
           clickedcustomdata = d.points[0].data.customdata[vecindex];
           console.log(d);
           console.log(clickedcustomdata);
         });
       }"

X <- data.frame(x = c(1, 2, 3, 1, 2, 3),
                y = c(1, 1, 1, 2, 2, 2), 
                z = 1:6,
                mydata = letters[1:6])

X <- X[order(-X$z),]

gg <- ggplot(X, aes(x = x, y = y, customdata = mydata)) + geom_tile(aes(fill = z))
fig <- ggplotly(gg) %>% onRender(js)
fig

enter image description here

I guess a potential solution would be to previously order X in R so it matches the matrix order?

mat
  • 2,412
  • 5
  • 31
  • 69
  • It might be possible to find a workaround using the `pointIndex`. I'd also consider [filing an issue](https://github.com/plotly/plotly.R/issues). – ismirsehregal Apr 05 '22 at 09:58
  • @ismirsehregal Will file a issue. I am not sure how to build an index from `pointIndex`. Do you have any idea? – mat Apr 05 '22 at 11:55

1 Answers1

2

This is a workaround based on the pointIndex.

I'm calculating the vector index for customdata based on the provided pointIndex:

library(plotly)
library(htmlwidgets)

js <- "function(el, x) {
         el.on('plotly_click', function(d) {
           var zdimensions = [ 0, 0 ];
           var vecindex = 0;
           var clickedcustomdata = '';
           
           var zdimensions = [ d.points[0].data.z.length, d.points[0].data.z[0].length ];
           vecindex = d.points[0].pointIndex[0]*zdimensions[1] + d.points[0].pointIndex[1];
           clickedcustomdata = d.points[0].data.customdata[vecindex];
           console.log(clickedcustomdata);
         });
       }"

X <- data.frame(x = c(1, 2, 1, 2, 1, 2), y = c(1, 1, 2, 2, 3, 3), z = 1:6, mydata = letters[1:6])
gg <- ggplot(X, aes(x = x, y = y, customdata = mydata)) + geom_tile(aes(fill = z))
fig <- ggplotly(gg) %>% onRender(js)
fig

result

This was useful to get here.

Still I'd encourage you to file an issue on GitHub, so this is fixed officially.

ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
  • 1
    Thanks, works perfectly! Filed an issue [here](https://github.com/plotly/plotly.R/issues/2120). – mat Apr 08 '22 at 08:17
  • Could you please have a look at my edit? The script stops working as soon as we reorder the dataset. – mat Apr 11 '22 at 13:38
  • @mat - yes you'll have to maintain the order of the `customdata` before passing it to plotly otherwise the array/vector mapping won't work. – ismirsehregal Apr 11 '22 at 13:52