Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate needle position in plotly gauge chart

Tags:

r

plotly

I'm trying to create a gauge chart using plotly in R/Shiny and am having a hard time figuring out how to determine the (x,y) coordinates of the point of the needle depending on value.

My gauge min = 18792 and max = 29472, with a mid-point of 24132. I use the following code to calculate (x,y) coords:

x1 = round(0.5 + (0.2 * cos(deg2rad(180-degs))), digits = 3)
y1 = round(0.5 + (0.2* sin(deg2rad(180-degs))), digits = 3)

I'm assuming the circle origin is (0.5,0.5). I need the needle to be ~ 0.2 in length (so r = 0.2).

As expected, whenever the minimum value is reached (18792), the needle position is (0.3, 0.5), and, reviewing it on screen, looks normal:

enter image description here

However, when the value reaches mid-point (24132), while (x,y) come up as expected (0.5, 0.7), the needle doesn't seem to be as long as the previous example:

enter image description here

The code I am using is as follows. You can switch between min and mid by commenting out the appropriate county value:

max = 29472
min = 18792
california = 23364
county = 24132
# county = 18792

min_label = paste0("$", format(min, big.mark = ","))
max_label = paste0("$", format(max, big.mark = ","))
california_label = paste0("$", format(california, big.mark = ","))
county_label = paste0("$", format(county, big.mark = ","))


# Define needle points
perDeg = (max - min)/180

degs = round((county - min)/perDeg, digits = 0)

deg2rad <- function(deg) { deg * pi / 180 }


# Define [x2,y2] - the needle point
  x1 = round(0.5 + (0.2 * cos(deg2rad(180-degs))), digits = 3)
  y1 = round(0.5 + (0.2* sin(deg2rad(180-degs))), digits = 3)



basePlot <- plot_ly(
  type = "pie",
  values = c(40, 10, 40, 10),
  labels = c(" ", min_label, "  ", max_label),
  rotation = 108,
  direction = "clockwise",
  hole = 0.7,
  textinfo = "label",
  textposition = "outside",
  hoverinfo = "none",
  domain = list(x = c(0, 1), y = c(0, 1)),
  # marker = list(colors = c('rgb(100, 100, 255)', 'rgb(100, 100, 255)', 'rgb(100, 100, 255)', 'rgb(100, 100, 255)')),
  showlegend = FALSE,
  sort = FALSE
)

basePlot <- add_trace(
  basePlot,
  type = "pie",
  values = c(50, 50),
  labels = c("Estimated Annual Cost of Living", " "),
  rotation = 90,
  direction = "clockwise",
  hole = 0.7,
  textinfo = "label",
  textposition = "inside",
  hoverinfo = "none",
  domain = list(x = c(0, 1), y = c(0, 1)),
  # marker = list(colors = c('rgb(255, 255, 255)', 'rgb(255, 255, 255)')),
  showlegend= FALSE
)

basePlot <- layout(
  basePlot,
  shapes = list(
    list(
      type = 'path',
      path = paste0('M 0.5 0.5 L ', x1, ' ', y1, ' Z'),
      xref = 'paper',
      yref = 'paper',
      fillcolor = 'rgb(226,210,172)'
    )
  ),
  annotations = list(
    list(
      xref = 'paper',
      yref = 'paper',
      x = 0.5,
      y = 0.4,
      showarrow = FALSE,
      text = paste0('<b>', county_label, '</b>')
    )
  )
)

basePlot

There has to be something that I'm totally missing. Any help is greatly appreciated!

like image 485
Bogdan Rau Avatar asked Nov 25 '25 22:11

Bogdan Rau


1 Answers

I know this is a little after the fact, but I've just been experiencing the exact same issue, but with the Python API. I didn't need my guages to be absolutely precise and 'near enough' would do. I resolved the issue by doubling the radius value in the y-axis.

This produced acceptable results and I assume it's because plotly treats both x and y axis as a value between 0 and 1.0. I'm using a rectangular display panel which means x=0.1 and y=0.1 are different measures. Hope this helps somebody else!

like image 146
gutbobs Avatar answered Nov 28 '25 16:11

gutbobs