Tutuchan / chartjs

An implementation of the Chart.js library in R
MIT License
30 stars 7 forks source link

Is it possible to derive a series of plots by looping over a list of data.frames? #12

Closed NikosAlexandris closed 8 years ago

NikosAlexandris commented 8 years ago

For example, why isn't the following working:

# define custom function
chartjs.polar <- function(plot.data, plot.labels, plot.height = "200px"){
    chartjs(height = plot.height)  %>%
    cjsPolar(labels = plot.labels) %>%
    cjsSeries(data =  plot.data) %>%
    cjsEditScale(axis = NULL, ticks = list(beginAtZero = TRUE))
}

# loop over 
for ( set in seq_along(scores.split)) {
    plot.data <- as.numeric( as.data.frame(scores.split[[set]][components.labels]))
    chartjs.polar( plot.labels = components.labels, plot.data = plot.data)
}

ps- Thanks for the great work.

Tutuchan commented 8 years ago

Hi and thanks for using the package.

I don't really understand what you are trying to accomplish here and I cannot try it out because I don't know what your scores.split and components.labels variables look like.

Could you paste the output from dput(scores.split) and dput(components.labels) here so I could have a better view ?

NikosAlexandris commented 8 years ago
  1. The (custom) function chartjs.polar(), above, is obviously nothing but a simple wrapper over chartjs(...) %>% ... et.c..
  2. The for loop tries to feed with data the custom function.

The target is to create multiple plots, each from an independent data.frame, of the same structure of course, in one go.

Using your example.Rmd, which contains:


```{r bar}
chartjs(height = "200px") %>%
  cjsBar(labels = LETTERS[1:10]) %>%
  cjsSeries(data = c(abs(c(rnorm(8))), NA, 0.5), label = "Series 1") %>%
  cjsSeries(data = abs(c(rnorm(10))), label = "Series 2") %>%
  cjsSeries(data = abs(c(rnorm(10))), label = "Series 3") %>% 
  cjsLegend()
\```

imagine you have a series of similar data to plot. Say the example above plus another two:


```{r bar-2}
chartjs(height = "200px") %>%
  cjsBar(labels = LETTERS[1:10]) %>%
  cjsSeries(data = c(abs(c(rnorm(7))), NA, NA, 0.6), label = "Series 1") %>%
  cjsSeries(data = abs(c(rnorm(9)), NA), label = "Series 2") %>%
  cjsSeries(data = abs(c(rnorm(10))), label = "Series 3") %>% 
  cjsLegend()
\```

```{r bar-3}
chartjs(height = "200px") %>%
  cjsBar(labels = LETTERS[1:10]) %>%
  cjsSeries(data = c(abs(c(rnorm(6))), 0.5, 0.6, NA, 0.5), label = "Series 1") %>%
  cjsSeries(data = abs(c(rnorm(8)), NA, NA), label = "Series 2") %>%
  cjsSeries(data = abs(c(rnorm(9)), 0.7), label = "Series 3") %>% 
  cjsLegend()
\```

Now, let's say the data (Series 1, Series 2, Series 3) for each of 'bar', 'bar-2', 'bar-3', are stored each in a data.frame. In turn, the data.frames are packed in a list. Well, we have a list of data.frames.

How do we loop over these to plot them in one go? To avoid, of course, code repetition and hardcoded stuff.

Something like (kind of pseudo-code):


```{r loop}
for (df in list.of.dfs){

LABELS = ... # get plot labels to feed labels
DATA.? = ...# get plot data to feed data, where ? = 1, 2, 3
chartjs(height = "200px") %>%
  cjsBar(labels = LABELS) %>%
  cjsSeries(data = DATA.1, label = "Series 1") %>%
  cjsSeries(data = DATA.2, label = "Series 2") %>%
  cjsSeries(data = DATA.3, label = "Series 3") %>% 
  cjsLegend()
}
\```

I hope this is more clear now. Thanks.

ps- not sure how to escape the "closing" three backticks insider and ``` !

Tutuchan commented 8 years ago

Thanks a lot for the detailed writeup !

It is clearer now, I thought you were trying to plot multiple series on the same graph and this does not look so well with polar area charts.

This is more of a knitr/rmarkdown interacting with htmlwidgets issue and it seems to be a bit tricky. I'll see what I can find out about this tonight.

Tutuchan commented 8 years ago

Alright, this issue showed me it is actually pretty simple, try this gist out and let me know if it works for you (it does on my end).

NikosAlexandris commented 8 years ago

If it matters, here my knitr_options.R,

# ---- knitr-options ----
library(knitr)

# root
# opts_knit$set(root.dir=normalizePath('../'))
# opts_knit$set(root.dir='../')

# set global chunk options: images will be 7x5 inches
exported_plots_directory <- "plots/"

# settings for figures
knitr::opts_chunk$set(echo=FALSE,
                      fig.path=exported_plots_directory, dpi=72, dev="png",
                      fig.width=12, fig.height=12,
                      out.width='500px', out.height='500px')

#
echo=TRUE

#
options(digits = 4)

#
tidy=TRUE
tidy.opts=list(blank=FALSE, width.cutoff=60)

# the default output hook
hook_output = knit_hooks$get('output')
knit_hooks$set(output = function(x, options) {
  if (!is.null(n <- options$out.lines)) {
    x = unlist(stringr::str_split(x, '\n'))
    if (length(x) > n) {
      # truncate the output
      x = c(head(x, n), '....\n')
    }
    x = paste(x, collapse = '\n') # paste first n lines together
  }
  hook_output(x, options)
})
\```

which I source in my .Rmd file via

```{r echo=FALSE, cache=FALSE}
knitr::read_chunk('knitr_options.R')
\```

I don't see, however, how the plot options would be relevant here.

Checking your gist right after...

NikosAlexandris commented 8 years ago

Done :+1: