helgasoft / echarty

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

Regarding geo plots #29

Closed MrMisc closed 11 months ago

MrMisc commented 12 months ago

Hello again,

Thank you very much for your help! It has enabled me to present alot more beautiful and properly intricate plots for my work, and I really appreciate it.

Continuing from your last solution regarding the dataset regarding cases across the world DirectExample.csv

input <- read.csv("DirectExample.csv")
input |> mutate(
  vleth= scales::rescale(lethality, to = c(0.01,100.00)),
  sleth= scales::rescale(n, to = c(13,36)),
  pleth= lethality *100
) |> na.omit() |>
  group_by(Year) |> 
  ec.init(load= 'world', geo= list(roam=T), animation=F,
          tl.series= list(type='scatter', coordinateSystem='geo',
                          name= "reports",
                          encode= list(lng='lon', lat='lat'), symbolSize= ec.clmn('sleth') ),
          visualMap = list(dimension='vleth',
                           inRange = list(symbol = "diamond", bottom= 3, color= c('#6EA5FF','#DB2D12'),colorLightness = c(0.7,0.45), colorSaturation = c(10,300)) ),
          options= list(legend= list(show=T)),
          title = list(list(left="80%", top="1%", textStyle=list(fontSize=30, color='#11111166')), 
                       list(text = "Life expectancy and GDP by year", 
                            left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20))),
          tooltip= list(formatter= 
                          ec.clmn('%@<br>Number of Outbreak Incidents: %@<br />Lethality: %R@%', 'Country','n','pleth'))
  ) |> ec.theme("something",code = jsonfile)

This works, and I was beginning to wonder if there was a way to simply colour the countries based off of n (ie what you rescaled as sleth in the previous solution you provided). I realised that you had an example pertaining to that . However, I got a bit confused as to how I would go about doing that. I ended up here, and am not sure how I should be referencing the data for the map to show colours.

#Different type of map??

input |> mutate(
  vleth= scales::rescale(lethality, to = c(0.01,100.00)),
  sleth= scales::rescale(n, to = c(13,36)),
  pleth= lethality *100
) |> na.omit() |>
  group_by(Year) |> 
  ec.init(load= 'world', geo= list(roam=T), animation=F,
          tl.series= list(type='map', coordinateSystem='geo',
                          name= "reports",
                          encode= list(lng='lon', lat='lat')),
          visualMap = list(type = 'continuous',calculable = TRUE),
          options= list(legend= list(show=T)),
          title = list(list(left="80%", top="1%", textStyle=list(fontSize=30, color='#11111166')), 
                       list(text = "Life expectancy and GDP by year", 
                            left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20))),
          tooltip= list(formatter= 
                          ec.clmn('%@<br>Number of Outbreak Incidents: %@<br />Lethality: %R@%', 'Country','n','pleth'))
  ) |> ec.theme("something",code = jsonfile)

I tried looking at the dataset in your example to try to understand this segment here and how it was perhaps used to point to the data for it to recognise the city names that were being used in your example, but I was not able to access the html link for :

library(rvest)
wp <- read_html('https://www.ined.fr/en/everything_about_population/data/france/population-structure/regions_departments')
wt <- wp %>% html_node('#para_nb_1 > div > div > div > table') %>% html_table(header=TRUE)
wt

So I am not sure how to replicate what you have done here for my dataset here. I would really appreciate if you were able to guide me through that, if possible. Thank you for your help thus far.

helgasoft commented 12 months ago

if there was a way to simply colour the countries based off of n

Yes, good idea, for much better visual. Working with 'geo' in ECharts has its quirks. When echarty loads the built-in ECharts map with load='world', it creates geo and series$coordinateSystem='geo'.

Keep in mind that, as shown in example, the built-in 'world' country names may not match the data names and they have to be converted. Like important 'Turkey' in your data. Here is the code:

remotes::install_github('helgasoft/echarty')    # get latest from 11/28/23
input <- read.csv("DirectExample.csv")

library(echarty); library(dplyr)
input |> mutate(
  pleth= lethality *100,
  Country = case_when(    # fix mismatch with map name, could be others...
    Country=='Türkiye' ~'Turkey', TRUE ~ Country)
) |> na.omit() |>
group_by(Year) |>

ec.init(load= 'world', geo= list(roam=T), animation=F,
    tl.series= list( type= 'map', encode= list(name= 'Country', value= 'n') ),
    visualMap = list( text='n',
       inRange = list(bottom= 3, color= c('#6EA5FF','#DB2D12'), colorLightness = c(0.7,0.45), colorSaturation = c(10,300)) ),
    tooltip= list(formatter= ec.clmn('%@<br>Outbreak Incidents: %@<br />Lethality: %R@%', 'name', 'value', 'pleth')),
    title = list(list(left="80%", top="1%", textStyle=list(fontSize=30, color='#11111166')), 
         list(text = "Outbreak incidents by year", 
            left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20)))
) 

image

MrMisc commented 12 months ago

Thank you so much!

With some adjustments, I was able to make something sort of full and made me very content!

input<-read.csv("DirectExample.csv")

listofcountries<-c("Japan","Korea","Cambodia","Bangladesh","Uzbekistan","New Caledonia","Fiji","Ireland","Denmark","Latvia","Estonia","Portugal","W. Sahara","Puerto Rico","Honduras","Papua New Guinea","New Zealand","Norway","Iceland","Greenland","Cuba","Venezuela","Panama","Algeria","Libya","Egypt","Mauritania", "Saudi Arabia", "Yemen", "Oman","Thailand","Malaysia")
input<-rbind(input,data.frame(Country =listofcountries ,Year = rep(2005,length(listofcountries)),n = rep(0,length(listofcountries)), Deaths = rep(0,length(listofcountries)) , Cases = rep(0,length(listofcountries)), lethality = rep(0,length(listofcountries)), database_name = listofcountries, lat = rep(0,length(listofcountries)), lon = rep(0,length(listofcountries))))

all_years <- data.frame(Year = unique(input$Year))
all_countries <- data.frame(Country = unique(input$Country))

template <- expand.grid(Year = all_years$Year, Country = all_countries$Country)

# Merge the template dataset with the original dataset
filled_data <- merge(template, input, by = c("Year", "Country"), all = TRUE)
filled_data[is.na(filled_data)] <- 0  # Replace NA values with 0

filled_data %>%
  mutate(
    pleth = lethality * 100,
    Country = case_when(
      Country == 'Türkiye' ~ 'Turkey',
      Country == "China (People's Rep. of)" ~ "China",
      Country == "Congo (Dem. Rep. of the)" ~ "Dem. Rep. Congo",
      Country == "United States of America" ~ "United States",
      Country == "South Sudan (Rep. of)" ~ "S. Sudan",
      Country == "Cote D'Ivoire" ~ "Côte d'Ivoire",
      TRUE ~ Country
    )
  ) %>% na.omit() |>
  group_by(Year) |>

  ec.init(load= 'world', geo= list(roam=T), animation=F,
          tl.series= list( type= 'map', encode= list(name= 'Country', value= 'n') ),
          visualMap = list( text='n',scale = my_scale,
                            inRange = list(bottom= 3, color= c('#00DDF5','#A793FF','#DB2D12'), colorLightness = c(0.7,0.45), colorSaturation = c(100,300)) ),
          tooltip= list(formatter= ec.clmn('%@<br>Outbreak Incidents: %@<br />Lethality: %R@%', 'name', 'value', 'pleth')),
          title = list(list(left="80%", top="1%", textStyle=list(fontSize=30, color='#11111166')), 
                       list(text = "Outbreak incidents by year", 
                            left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20)))
  ) |> ec.theme("something", westeros)

rstudio_ILweX57RY3

MrMisc commented 11 months ago

Hello again,

My apologies, but I am having trouble understanding how this actually works. After tinkering with this original code for a bit, I am not understanding for instance, how the range for visual map is determined, and where the variables are being used to determine in this instance, the colour and the visual map range. For example, when I replicated the following using the same dataset.

input<-read.csv("DirectExample.csv")

listofcountries<-c("Japan","Korea","Cambodia","Bangladesh","Uzbekistan","New Caledonia","Fiji","Ireland","Denmark","Latvia","Estonia","Portugal","W. Sahara","Puerto Rico","Honduras","Papua New Guinea","New Zealand","Norway","Iceland","Greenland","Cuba","Venezuela","Panama","Algeria","Libya","Egypt","Mauritania", "Saudi Arabia", "Yemen", "Oman","Thailand","Malaysia")
input<-rbind(input,data.frame(Country =listofcountries ,Year = rep(2005,length(listofcountries)),n = rep(0,length(listofcountries)), Deaths = rep(0,length(listofcountries)) , Cases = rep(0,length(listofcountries)), lethality = rep(0,length(listofcountries)), database_name = listofcountries, lat = rep(0,length(listofcountries)), lon = rep(0,length(listofcountries))))

all_years <- data.frame(Year = unique(input$Year))
all_countries <- data.frame(Country = unique(input$Country))

template <- expand.grid(Year = all_years$Year, Country = all_countries$Country)

# Merge the template dataset with the original dataset
filled_data <- merge(template, input, by = c("Year", "Country"), all = TRUE)
filled_data[is.na(filled_data)] <- 0  # Replace NA values with 0

minima<-data.frame(n = filled_data$n, Country = filled_data$Country, Year = filled_data$Year,lethality = filled_data$lethality)

minima %>%
  mutate(
    Country = case_when(
      Country == 'Türkiye' ~ 'Turkey',
      Country == "China (People's Rep. of)" ~ "China",
      Country == "Congo (Dem. Rep. of the)" ~ "Dem. Rep. Congo",
      Country == "United States of America" ~ "United States",
      Country == "South Sudan (Rep. of)" ~ "S. Sudan",
      Country == "Cote D'Ivoire" ~ "Côte d'Ivoire",
      TRUE ~ Country
    )
  ) %>% na.omit() |>
  group_by(Year) |>
  ec.init(load= 'world', geo= list(roam=T), animation=F,
          tl.series= list( type= 'map', encode= list(name= 'Country', value= 'n') ),
          visualMap = list(min = 1000, text='n',
                            inRange = list(bottom= 3, color= c('#00DDF5','#A793FF','#DB2D12'), colorLightness = c(0.9,0.45), colorSaturation = c(100,300)) ),
          tooltip= list(formatter= ec.clmn('%@<br>Outbreak Incidents: %@<br />', 'name', 'value')),
          title = list(list(left="80%", top="1%", textStyle=list(fontSize=30, color='#11111166')), 
                       list(text = "Outbreak incidents by year", 
                            left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20)))
  )

The visual map range goes by some large negative number onwards, skewing the colouring for the points when I use filled_data, and when I try to use a minimized version of the dataset as I used here with 'minima', the whole map just becomes monotone?

helgasoft commented 11 months ago

Currently echarty maps do not support visualMap.dimension. We are working on fixing that soon. Without dimension, ECharts by default takes the visualMap range automatically from the last column of the dataset. Below are examples on how to map Cases (column 'n') and Lethality (column 'pleth'). Notice the differences in relocate, tl.series and tooltip.

input <- read.csv("DirectExample.csv")
data <- input |> mutate(
  pleth= round(lethality *100),
  Country = case_when(
    Country == 'Türkiye' ~ 'Turkey',
    Country == "China (People's Rep. of)" ~ "China",
    Country == "Congo (Dem. Rep. of the)" ~ "Dem. Rep. Congo",
    Country == "United States of America" ~ "United States",
    Country == "South Sudan (Rep. of)" ~ "S. Sudan",
    Country == "Cote D'Ivoire" ~ "Côte d'Ivoire",
    TRUE ~ Country
  )
) |> na.omit()

inRange <- list(bottom= 3, color= c('#6EA5FF','#DB2D12'), colorLightness = c(0.7,0.45), colorSaturation = c(10,300)) 
titleL <- titleN <- list(list(left="80%", top="1%", textStyle=list(fontSize=30, color='#11111166')), 
     list(text = "Outbreak incidents by year", 
        left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20)))
titleL[[2]]$text <- sub('incidents', 'lethality', titleL[[2]]$text)

data |> relocate(n, .after = last_col()) |> group_by(Year) |>
ec.init(load= 'world',
  tl.series= list( type= 'map', encode= list(name= 'Country', value= 'n') ),
  tooltip= list(formatter= ec.clmn('%@<br>Outbreak Incidents: %@<br />Lethality: %R@%', 'name', 'value', 'pleth')),
  visualMap = list( text='n', inRange=inRange),
  title= titleN
)

data |> relocate(pleth, .after = last_col()) |> group_by(Year) |>
ec.init(load= 'world',
  tl.series= list( type= 'map', encode= list(name= 'Country', value= 'pleth') ),
  tooltip= list(formatter= ec.clmn('%@<br>Outbreak Incidents: %@<br />Lethality: %R@%', 'name', 'n', 'value')),
  visualMap = list(text=c('pleth',''), inRange=inRange),
  title= titleL
)
helgasoft commented 11 months ago

The latest version of echarty is available. Install: remotes::install_github('helgasoft/echarty',force = TRUE) Check: RStudio > Packages > click echarty > click DESCRIPTION > Date should be >= 2023-12-14

World map charts are now compliant with ECharts:

Here is the updated code.

input <- read.csv("DirectExample.csv")
data <- input |> mutate(
  pleth= round(lethality *100),
  Country = case_when(
    Country == 'Türkiye' ~ 'Turkey',
    Country == "China (People's Rep. of)" ~ "China",
    Country == "Congo (Dem. Rep. of the)" ~ "Dem. Rep. Congo",
    Country == "United States of America" ~ "United States",
    Country == "South Sudan (Rep. of)" ~ "S. Sudan",
    Country == "Cote D'Ivoire" ~ "Côte d'Ivoire",
    TRUE ~ Country
  )
) |> na.omit()

inRange <- list(bottom= 3, color= c('#6EA5FF','#DB2D12'), colorLightness = c(0.7,0.45), colorSaturation = c(10,300)) 
titleL <- titleN <- list(list(left="80%", top="1%", textStyle=list(fontSize=30, color='#11111166')), 
     list(text = "Outbreak incidents by year", 
        left = "10%", top = 10, textStyle = list(fontWeight = "normal", fontSize = 20)))
titleL[[2]]$text <- sub('incidents', 'lethality', titleL[[2]]$text)
tooltip= list(formatter= ec.clmn('%@<br>Outbreak Incidents: %@<br />Lethality: %R@%', 'Country', 'n', 'pleth'))

data |> group_by(Year) |>
ec.init(load= 'world', tl.series= list( type= 'map'),
  tooltip= tooltip, title= titleN,
  visualMap = list( text='n', inRange=inRange, dimension=3)  # 3= column 'n'
)

data |> group_by(Year) |>
ec.init(load= 'world', tl.series= list( type= 'map'),
  tooltip= tooltip, title= titleL,
  visualMap = list(text=c('pleth',''), inRange=inRange),  # defaults to last column 'pleth'
)

NB: 📌 please close issue if problem solved.