JohnCoene / echarts4r

🐳 ECharts 5 for R
http://echarts4r.john-coene.com/
Other
585 stars 82 forks source link

Bubble size on grouped bubble plot - bubbles scaled within groups #625

Closed bluefoxr closed 1 month ago

bluefoxr commented 2 months ago

Hi, first thanks so much for the fantastic package.

I am trying make bubble plots which also include a grouping variable, along the lines of your example. However, I encounter an "unexpected behaviour". Basically, the bubble sizes seem to be scaled within groups when I would normally expect them to be scaled globally. For example:

library(echarts4r)

bubble_size <- 1:5
x <- 1:5
y <- 1:5

# in this df I set the size in one group to be 10x the other group
# I also space the two groups on x and y axis, just for clarity
df1 <- data.frame(
  Size = c(bubble_size, bubble_size*10),
  x = c(x, x + 6),
  y = c(y, y + 6),
  Group = c(rep("SMALL", 5), rep("BIG", 5))
)

df1 |> 
  group_by(Group) |> 
  e_charts(x) |> 
  e_scatter(y, Size)

Here I am intentionally making the "size" of one group to be 10 times more than the size of the other group, but here's what I get:

image

So clearly the scale function is scaling the bubble size within groups. However what I would like is to have the scaling done globally, so the size of the bubble reflects the "Size" value without rescaling within groups, if that makes sense. I would also say this could be the "expected" behaviour which might make more sense as a default.

Is there a way to do this, or a feature I have missed? Really appreciate any input. I went through your documentation but didn't find anything, sorry if I overlooked something. Best, Will

rdatasculptor commented 2 months ago

What happens if you do: e_scatter(y, Size, scale = NULL)? At least I would start there.

rdatasculptor commented 2 months ago

okay, so if you do this:

df1 |> 
  group_by(Group) |> 
  e_charts(x) |> 
  e_scatter(y, Size, scale = NULL)

then this is the result:

image

isn't that what you intended?

bluefoxr commented 1 month ago

Hi @rdatasculptor thanks very much for this, yes it is nearly what I am looking for but not quite. The problem with that approach (as I understand it) is that the vector "Size" could be on any scale, and the points will be exactly take that size. So e.g. if I have data with the "Size" with very small values (say, below 1), the points will be tiny. What I would like is to be able to control the minimum and max bubble sizes regardless of the data range.

This did inspire me to come up with a solution though. I find the global min and max first, then define a scaling function which can access the global min and max. This gets round the problem that the scaling function is passed the data one group at a time, so it cannot "see" the global min and max unless explicitly passed to it. Not sure if there is a simpler solution but it works at least!

Thanks again for all your input here.

library(echarts4r)

bubble_size <- 1:5
x <- 1:5
y <- 1:5

# in this df I set the size in one group to be 10x the other group
# I also space the two groups on x and y axis, just for clarity
df1 <- data.frame(
  Size = c(bubble_size, bubble_size*20),
  x = c(x, x + 6),
  y = c(y, y + 6),
  Group = c(rep("SMALL", 5), rep("BIG", 5))
)

global_min <- min(df1$Size, na.rm = TRUE)
global_max <- max(df1$Size, na.rm = TRUE)

# min and max bubble sizes - have to define here since point_scaler is passed
# the data one group at a time
min_bubble_size <- 1
max_bubble_size <- 50

# function maps "Size" vector to a scale within specified bounds 
point_scaler <- function(x){
  (x-global_min)/(global_max - global_min)*(max_bubble_size - min_bubble_size) + min_bubble_size
}

# plot
df1 |> 
  group_by(Group) |> 
  e_charts(x) |> 
  e_scatter(y, Size, scale = point_scaler)

image

rdatasculptor commented 1 month ago

For me this seems to be a clever solution. Wel done! Let's close the issue

JohnCoene commented 1 month ago

Thanks for helping with this @rdatasculptor, and thanks for your patience @bluefoxr !

bluefoxr commented 1 month ago

Thanks @rdatasculptor and @JohnCoene, I will close the issue now. All the best.