helgasoft / echarty

Minimal R/Shiny Interface to ECharts.js
https://helgasoft.github.io/echarty/
86 stars 3 forks source link

Features question #32

Closed MrMisc closed 9 months ago

MrMisc commented 10 months ago

I am curious about how to leverage features from echarts using echarty such as emphasis and marker/line size. I am using pretty much the same example as before (I opened this up as a separate issue since I do not know if it is right to squeeze all my issues into one thread).

modifiedanthrax_WAHIS_dataset.csv

remotes::install_github('helgasoft/echarty',force = TRUE)  # get latest
library(echarty)
wahis<-read.csv("modifiedanthrax_WAHIS_dataset.csv")
data2<-wahis %>% mutate(Cases = as.integer(Cases),Deaths = as.integer(Deaths)) %>%
  filter(`Animal Category` == "Domestic" &
           Species %in% c("Cattle","Sheep","Sheep/goats (mixed herd)","Goats","Swine")) %>%
  group_by(Year,Sub_Continent, Country) %>%
  summarise(n = n(),Cases = sum(Cases), Deaths = sum(Deaths)) %>%
  ungroup()

setting <- list(show = T,type= "scroll",orient= "horizontal", pageButtonPosition= 'start',
                right= 5,top = 30, icon = 'circle', align= 'right', height='85%')

data2 |> group_by(Sub_Continent) |> ec.init(
  tooltip= list(show= TRUE),
  tl.series= list(encode = list(x = 'Year',y = 'n',emphasis = list(focus ="series")),type= 'line', groupBy= 'Country'), ##Focus here does not work- probably wrong implementation
  xAxis = list(max = 2023,min = 2009),
  legend = setting,
  # visualMap= list(dimension=2, inRange= list( symbolSize = c(35,5)))
)

My current implementation of focus doesn't work, and I am currently just trying to tinker randomly with the code since I do not believe there is an example using emphasis on the echarty examples site you have kindly provided.

I would really appreciate your guidance regarding this. Thank you for your time.

helgasoft commented 10 months ago

trying to tinker randomly with the code since I do not believe there is an example using emphasis on the echarty examples site you have kindly provided.

There are several emphasis examples in ?ec.examples help. All example locations are listed in ?'-- Introduction --'. But no need to limit yourself to examples only. I recommend reading the official ECharts API. Then you'll realize that emphasis in your code is inside the encode list, but should be outside.

MrMisc commented 10 months ago

Thank you!

I would like to ask you as well, is it possible for 2 things:

  1. Is it possible to have 2 datazooms? One that is vertical and another that is horizontal? I notice that the swapping between orient = "horizontal" and orient = "vertical" actually adjust the graph in those orientations. It isn't that setting it to vertical, that the bar still causes a zoom in or out effect on along the x-axis, but instead on the y-axis, matching the orientation of the zoombar instead.
  2. Is it possible to make the legend bar be sensitive to each frame inside the timeline? This would make it such that the countries listed in the legend bar are for the sub continent, not, listing all the countries within the entire dataset.

Below is my current code depicting what I have managed to do thanks to your examples and help! Thank you!

scatter<-data2 |> group_by(Sub_Continent) |> ec.init(
  dataZoom= list(type= 'slider', end= 100,start = 77
  ,top = '2%',height = 20),
  # dataZoom= list(type= 'slider', end= 50,orient = 'vertical'
  #                ,left = '2%',height = 20),
  tooltip= list(show= TRUE),
  tl.series= list(lineStyle= list(cap = 'square',opacity = 0.75,curveness=0.1, width=1.5),
                  encode = list(x = 'Year',y = 'n'),
                  emphasis= list(focus= 'adjacency',
                                 itemStyle=list(shadowBlur=10,shadowColor='rgba(0,0,0,0.5)'),
                                 label= list(position= 'right',
                                             rotate = 350,
                                             show=TRUE)),
                  type= 'line', groupBy= 'Country'),
  xAxis = list(max = 2023,min = 2005)
  # visualMap= list(dimension=2, inRange= list( symbolSize = c(35,5)))
)|>ec.upd({legend<-setting})
helgasoft commented 10 months ago
  1. Is it possible to have 2 datazooms?

Yes

  dataZoom= list(
    list(type= 'slider', end= 100, start= 77,top= '2%',height= 20),
    list(type= 'slider', end= 100, start= 0, orient='vertical', right=0)
  ),
  1. Is it possible to make the legend bar be sensitive to each frame inside the timeline?

Yes, I answered already with demo code in "Legend issue".

MrMisc commented 10 months ago

You're right. My apologies, I missed that. Thank you so much.

Can I also get some advice on what I should be doing to avoid the x-axis for bar plots "leaving out" some of the labels? Like for the following


animals<-wahis %>% mutate(Cases = as.integer(Cases),Deaths = as.integer(Deaths)) %>% 
  filter(`Animal Category` == "Domestic") %>% 
  group_by(Year,Country,Species) %>% 
  summarise(n = n(),Cases = sum(Cases), Deaths = sum(Deaths)) %>% 
  ungroup()

tmp <- animals |> group_by(Year) |> group_split()
cns <- lapply(seq_along(tmp), \(i) { as.list(unique(tmp[[i]]$Country)) })

animals %>% 
  group_by(Year) |> 
  ec.init(
    title= list(text= 'locale test'),
    dataZoom= list(list(type= 'slider'
                        ,top = '2%',height = 20),
                   list(type= 'slider',orient = 'vertical'
                        ,left = '2%')),
    tl.series = list(type  ='bar',stack = "grp",
                     encode = list(x = 'Species',y = 'n'), groupBy= 'Country',
                     emphasis= list(focus= 'series',
                                    itemStyle=list(shadowBlur=10,
                                                   shadowColor='rgba(0,0,0,0.5)'),
                                    label= list(position= 'right',
                                                rotate = 350,
                                                show=TRUE))),
    tooltip = list(show = T))|>
  ec.upd({legend<-setting
  options <- lapply(seq_along(options), \(i) {  
    options[[i]]$legend$data <- cns[[i]]  # fine-tune legends: data by continent
    options[[i]] 
  })
  })

And some of the labels go missing for some reason periodically - which wouldn't be so much of an issue if the x-axis was just numeric, but in this case it is meant to name the different species in the dataset.

Additionally, do you know how echarty, if it is able to, make a horizontal bar chart in descending order, like here?

helgasoft commented 10 months ago

avoid the x-axis for bar plots "leaving out" some of the labels

ECharts is smart to not overlap axis labels, so it hides some of them. To see them all, labels need to be rotated.

make a horizontal bar chart in descending order

yes, by doing data preprocessing

animals<-wahis %>% mutate(Cases = as.integer(Cases),Deaths = as.integer(Deaths)) %>% 
  filter(`Animal.Category` == "Domestic") %>% 
  group_by(Year,Country,Species) %>% 
  summarise(n = n(),Cases = sum(Cases), Deaths = sum(Deaths)) %>% 
  ungroup()
legset <- list(show = T,type= "scroll",orient= "horizontal", pageButtonPosition= 'start',
                right= 5,top = 30, icon = 'circle', align= 'right', height='85%')

tmp <- animals |> group_by(Year) |> group_split()
cns <- lapply(seq_along(tmp), \(i) { as.list(unique(tmp[[i]]$Country)) })

tmp <- animals |> group_by(Year,Species) |> summarize(ss= sum(n)) |>
  ungroup() |> inner_join(animals) |>  arrange(desc(ss)) |> group_by(Year) |> group_split()
xax <- lapply(seq_along(tmp), \(i) { as.list(unique(tmp[[i]]$Species)) })

animals |> group_by(Year) |> 
ec.init(
    title= list(text= 'locale test'), xAxis= list(axisLabel= list(rotate=75)),
    dataZoom= list(list(type= 'slider',top = '2%',height = 20),
                   list(type= 'slider',orient = 'vertical',left = '2%')),
    tl.series = list(type  ='bar',stack = "grp",
                     encode = list(x = 'Species',y = 'n'), groupBy= 'Country',
                     emphasis= list(focus= 'series',
                                    itemStyle=list(shadowBlur=10,
                                                   shadowColor='rgba(0,0,0,0.5)'),
                                    label= list(position= 'right',
                                                rotate = 350,
                                                show=TRUE))),
    tooltip = list(show= T))|>
  ec.upd({ legend <- legset
  options <- lapply(seq_along(options), \(i) {  
    options[[i]]$legend$data <- cns[[i]]  # fine-tune legends: data by continent
    options[[i]]$xAxis$data <- xax[[i]]  # bars sorted by height
    options[[i]] 
  })
})

image

MrMisc commented 10 months ago

Thank you so much!

I apologise but for this type of configuration, why does the title argument not quite work here? I have been trying to tinker with that as well but to no avail.

I am also struggling to understand what causes the timeline Year title to pop up on the top left here (not that I don't want it)? I want to understand where this is being instructed in the code.

Just as an update, I am at this point thanks to you.

animals<-wahis %>% mutate(Cases = as.integer(Cases),Deaths = as.integer(Deaths)) %>% 
  filter(`Animal Category` == "Domestic") %>% 
  group_by(Year,Country,Species) %>% 
  summarise(n = n(),Cases = sum(Cases), Deaths = sum(Deaths)) %>% 
  ungroup()

tmp <- animals |> group_by(Year) |> group_split()
cns <- lapply(seq_along(tmp), \(i) { as.list(unique(tmp[[i]]$Country)) })

tmp <- animals |> group_by(Year,Species) |> summarize(ss= sum(n)) |>
  ungroup() |> inner_join(animals) |>  arrange(desc(ss)) |> group_by(Year) |> group_split()
xax <- lapply(seq_along(tmp), \(i) { as.list(unique(tmp[[i]]$Species)) })

subset(animals,Species != "0") %>% 
  group_by(Year) |> 
  ec.init(
    xAxis = list(name = 'Species',nameLocation = 'start',
                 nameTextStyle = list(fontWeight ='bolder'),
                 axisLabel = list(rotate = 346,width = 65,
                                  overflow = 'truncate')),
    yAxis = list(name = "Count",nameLocation = 'start',
                 nameTextStyle = list(fontWeight ='bolder')),
    dataZoom= list(type= 'slider',orient = 'vertical'
                        ,left = '2%'),
    tl.series = list(type  ='bar',stack = "grp",
                     encode = list(x = 'Species',y = 'n'), groupBy= 'Country',
                     emphasis= list(focus= 'series',
                                    itemStyle=list(shadowBlur=10,
                                                   shadowColor='rgba(0,0,0,0.5)'),
                                    label= list(position= 'right',
                                                rotate = 350,
                                                show=TRUE)),
    title = list(text = "Outbreak incidents by year", 
            left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20),
            text = "WAHIS Dataset", 
            left = "10%", top = 17, textStyle = list(fontWeight = "normal", fontSize = 14))),
    tooltip = list(show = T))|>
  ec.upd({legend<-setting
  options <- lapply(seq_along(options), \(i) {  
    options[[i]]$legend$data <- cns[[i]]  # fine-tune legends: data by continent
    options[[i]]$xAxis$data <- xax[[i]] 
    options[[i]] 
  })
  })

image

helgasoft commented 10 months ago

good progress, several issues need to be addressed however:

what causes the timeline Year title to pop up on the top left here

Automatically generated by echarty and that is a bug - should not overwrite the one set by the user. Below is a workaround, it will work after you take care of the above three issues.

 options <- lapply(seq_along(options), \(i) {  
    options[[i]]$legend$data <- cns[[i]]
    options[[i]]$xAxis$data <- xax[[i]]
    tita <- title  # that is the 'general' title from ec.init
    tita$text <- paste(tita$text, options[[i]]$title$text)
    options[[i]]$title <- tita   # here we set a title for each timeline step
    options[[i]]
 })

image

MrMisc commented 10 months ago

Brilliant. Thank you so much.

I think it would be appropriate to ask my next question in the next thread, but just so I am not potentially wasting time, I would like to simply clarify - is it possible for echarty to connect 2 plots together like echarts4r demonstrates with e_connect and binding datasets together?

I was planning on asking a question on asking about binding something like this to a pie chart that would change alongside the barchart with every frame in the timeline?

helgasoft commented 10 months ago

a pie chart that would change alongside the barchart with every frame in the timeline?

See latest example in #3, it has sample code.

helgasoft commented 10 months ago

is it possible for echarty to connect 2 plots together like echarts4r demonstrates with e_connect and binding datasets together?

Yes, charts having the same dataset are easily connected, see API connect.

main <- mtcars |> mutate(name=rownames(mtcars)) |> 
ec.init(height= 300,
  legend= list(show=T), 
  dataZoom= list(type='inside'), 
  tooltip= list(axisPointer= list(axis='x'))
)
main$x$group <- 'group1'     # same group name for all charts
main$x$connect <- 'group1'   # activate connection
chs <- lapply(list('hp','wt','drat','qsec'), \(vv) {
  main$x$opts <- within(main$x$opts, {
     series[[1]]$encode <- list(y= vv)
     series[[1]]$name <- yAxis$name <- vv 
     tooltip$formatter <- ec.clmn(paste('%@<br>',vv,': %@'), 'name', vv)
  })
  main
})
ec.util(cmd='layout', chs, cols=2, title='group connect on zoom & tooltip')