timelyportfolio / rcdimple

htmlwidgets for rCharts + dimple
http://www.buildingwidgets.com/blog/2015/3/18/week-11-dimple-as-htmlwidget
MIT License
28 stars 9 forks source link

Access "_getFormat" in rcdimple? #9

Closed walkerke closed 9 years ago

walkerke commented 9 years ago

Hi Kenton,

Thanks for your great work on the dimple update; I am enjoying working with it. Right now, I am updating my old population pyramids example (http://walkerke.github.io/2014/06/rcharts-pyramids/) with your new package and some of the new tools that have been released in the past year.

So far, it is working great; there is just one thing I can't figure out yet. Last year, you and John helped me display all of the values in the tooltip and on the X-axis as absolute values with x._getFormat, which was passed to afterScript in rCharts (https://github.com/ramnathv/rCharts/issues/421). Is there a way to do this in rcdimple? Here is where I'm at so far:

library(dplyr)
library(tidyr)
library(rvest)
library(rcdimple)

url <- "http://www.census.gov/population/international/data/idb/region.php?N=%20Results%20&T=10&A=separate&RT=0&Y=2015,2020,2025,2030,2035,2040,2045,2050&R=-1&C=IN"

df <- url %>%
  html() %>%
  html_nodes("table") %>%
  html_table() %>%
  data.frame()

names(df) <- c("Year", "Age", "total", "Male", "Female", "percent", "pctMale", "pctFemale", "sexratio") 

cols <- c(1, 3:9)

df[,cols] <- apply(df[,cols], 2, function(x) as.numeric(as.character(gsub(",", "", x))))

df1 <- df %>%
  mutate(Order = 1:nrow(df), 
         Male = -1 * Male) %>%
  filter(Age != "Total") %>%
  select(Year, Age, Male, Female, Order) %>%
  gather(Gender, Population, -Age, -Order, -Year)

max_x <- plyr::round_any(max(df1$Population), 10000, f = ceiling)
min_x <- plyr::round_any(min(df1$Population), 10000, f = floor)

df1 %>%
  dimple(x = "Population", y = "Age", group = "Gender", type = 'bar', storyboard = "Year") %>%
  yAxis(type = "addCategoryAxis", orderRule = "Order") %>%
  xAxis(type = "addMeasureAxis", overrideMax = max_x, overrideMin = min_x) %>%
  default_colors(c("green", "orange")) %>%
  add_legend()

Thanks for any advice you can provide, and the work you've put in on this package!

timelyportfolio commented 9 years ago

Most definitely a way. I'll be right back with a demo.

timelyportfolio commented 9 years ago

Ok, what a great use of all the new R tools. I'm still not sure this is the best implementation, but I provided an undocumented chart hook that we can use in options to make this work. rCharts2 will have tack which allows us to change/add options to a widget within a pipe. I tried to inline comment the JavaScript to explain what I did. Please ask questions.

library(dplyr)
library(tidyr)
library(rvest)
library(rcdimple)

url <- "http://www.census.gov/population/international/data/idb/region.php?N=%20Results%20&T=10&A=separate&RT=0&Y=2015,2020,2025,2030,2035,2040,2045,2050&R=-1&C=IN"

df <- url %>%
  html() %>%
  html_nodes("table") %>%
  html_table() %>%
  data.frame()

names(df) <- c("Year", "Age", "total", "Male", "Female", "percent", "pctMale", "pctFemale", "sexratio") 

cols <- c(1, 3:9)

df[,cols] <- apply(df[,cols], 2, function(x) as.numeric(as.character(gsub(",", "", x))))

df1 <- df %>%
  mutate(Order = 1:nrow(df), 
         Male = -1 * Male) %>%
  filter(Age != "Total") %>%
  select(Year, Age, Male, Female, Order) %>%
  gather(Gender, Population, -Age, -Order, -Year)

max_x <- plyr::round_any(max(df1$Population), 10000, f = ceiling)
min_x <- plyr::round_any(min(df1$Population), 10000, f = floor)

df1 %>%
  dimple(x = "Population", y = "Age", group = "Gender", type = 'bar', storyboard = "Year") %>%
  yAxis(type = "addCategoryAxis", orderRule = "Order") %>%
  xAxis(type = "addMeasureAxis", overrideMax = max_x, overrideMin = min_x) %>%
  default_colors(c("green", "orange")) %>%
  add_legend() %>%
  tack(., options = list(
    chart = htmlwidgets::JS("
      function(){
        var self = this;
        // x axis should be first or [0] but filter to make sure
        self.axes.filter(function(ax){
          return ax.position == 'x'
        })[0] // now we have our x axis set _getFormat as before
          ._getFormat = function () {
            return function(d) {
              return d3.format(',.1f')(Math.abs(d) / 1000000) + 'm';
            };
        };
        // return self to return our chart
        return self;
      }
    "))
  )
walkerke commented 9 years ago

Brilliant, works great! Thanks for your swift reply.